[Haiku-commits] r31248 - haiku/trunk/src/add-ons/kernel/file_systems/bfs
axeld at BerliOS
axeld at mail.berlios.de
Fri Jun 26 11:36:18 CEST 2009
Author: axeld
Date: 2009-06-26 11:36:17 +0200 (Fri, 26 Jun 2009)
New Revision: 31248
ViewCVS: http://svn.berlios.de/viewcvs/haiku?rev=31248&view=rev
Modified:
haiku/trunk/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
haiku/trunk/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
haiku/trunk/src/add-ons/kernel/file_systems/bfs/Volume.cpp
Log:
* BFS allocated always full allocation groups in the bitmap, even if the last
group was a partial one. This caused bug #3963 (Be's BFS didn't do that).
* Added new BlockAllocator::CheckBlocks() that does not depend on allocation
group limits - this fixes the problematic check in
BlockAllocator::_Initialize() to see if the super block, the block bitmap,
and the log area are all allocated - this only worked if they all fit into
the first allocation group (which happens only with partitions with more
than 1 billion blocks, ie. 2 TB would already be problematic with a 2K block
size).
Modified: haiku/trunk/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp 2009-06-26 08:57:36 UTC (rev 31247)
+++ haiku/trunk/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp 2009-06-26 09:36:17 UTC (rev 31248)
@@ -533,6 +533,9 @@
{
fNumGroups = fVolume->AllocationGroups();
fBlocksPerGroup = fVolume->SuperBlock().BlocksPerAllocationGroup();
+ fNumBlocks = (fVolume->NumBlocks() + fVolume->BlockSize() * 8 - 1)
+ / (fVolume->BlockSize() * 8);
+
fGroups = new AllocationGroup[fNumGroups];
if (fGroups == NULL)
return B_NO_MEMORY;
@@ -558,11 +561,10 @@
BlockAllocator::InitializeAndClearBitmap(Transaction& transaction)
{
status_t status = Initialize(false);
- if (status < B_OK)
+ if (status != B_OK)
return status;
- uint32 blocks = fBlocksPerGroup;
- uint32 numBits = 8 * blocks * fVolume->BlockSize();
+ uint32 numBits = 8 * fBlocksPerGroup * fVolume->BlockSize();
uint32 blockShift = fVolume->BlockShift();
uint32* buffer = (uint32*)malloc(numBits >> 3);
@@ -572,12 +574,13 @@
memset(buffer, 0, numBits >> 3);
off_t offset = 1;
+ // the bitmap starts directly after the super block
// initialize the AllocationGroup objects and clear the on-disk bitmap
for (int32 i = 0; i < fNumGroups; i++) {
if (write_pos(fVolume->Device(), offset << blockShift, buffer,
- blocks << blockShift) < B_OK)
+ fBlocksPerGroup << blockShift) < B_OK)
return B_ERROR;
// the last allocation group may contain less blocks than the others
@@ -587,14 +590,14 @@
>> (blockShift + 3));
} else {
fGroups[i].fNumBits = numBits;
- fGroups[i].fNumBlocks = blocks;
+ fGroups[i].fNumBlocks = fBlocksPerGroup;
}
fGroups[i].fStart = offset;
fGroups[i].fFirstFree = fGroups[i].fLargestStart = 0;
fGroups[i].fFreeBits = fGroups[i].fLargestLength = fGroups[i].fNumBits;
fGroups[i].fLargestValid = true;
- offset += blocks;
+ offset += fBlocksPerGroup;
}
free(buffer);
@@ -679,16 +682,16 @@
// check if block bitmap and log area are reserved
uint32 reservedBlocks = volume->Log().Start() + volume->Log().Length();
- if (allocator->CheckBlockRun(block_run::Run(0, 0, reservedBlocks)) < B_OK) {
+
+ if (allocator->CheckBlocks(0, reservedBlocks) != B_OK) {
Transaction transaction(volume, 0);
- if (groups[0].Allocate(transaction, 0, reservedBlocks) < B_OK) {
+ if (groups[0].Allocate(transaction, 0, reservedBlocks) != B_OK) {
FATAL(("could not allocate reserved space for block "
"bitmap/log!\n"));
volume->Panic();
} else {
+ transaction.Done();
FATAL(("space for block bitmap or log area was not reserved!\n"));
-
- transaction.Done();
}
}
@@ -1011,19 +1014,19 @@
return B_BAD_VALUE;
}
#ifdef DEBUG
- if (CheckBlockRun(run) < B_OK)
+ if (CheckBlockRun(run) != B_OK)
return B_BAD_DATA;
#endif
CHECK_ALLOCATION_GROUP(group);
- if (fGroups[group].Free(transaction, start, length) < B_OK)
+ if (fGroups[group].Free(transaction, start, length) != B_OK)
RETURN_ERROR(B_IO_ERROR);
CHECK_ALLOCATION_GROUP(group);
#ifdef DEBUG
- if (CheckBlockRun(run, NULL, NULL, false) < B_OK) {
+ if (CheckBlockRun(run, NULL, NULL, false) != B_OK) {
DEBUGGER(("CheckBlockRun() reports allocated blocks (which were just "
"freed)\n"));
}
@@ -1038,7 +1041,7 @@
size_t
BlockAllocator::BitmapSize() const
{
- return fVolume->BlockSize() * fNumGroups * fBlocksPerGroup;
+ return fVolume->BlockSize() * fNumBlocks;
}
@@ -1501,7 +1504,43 @@
}
+/*! Checks whether or not the specified block range is allocated or not,
+ depending on the \a allocated argument.
+*/
status_t
+BlockAllocator::CheckBlocks(off_t start, off_t length, bool allocated)
+{
+ if (start < 0 || start + length > fVolume->NumBlocks())
+ return B_BAD_VALUE;
+
+ uint32 group = start >> fVolume->AllocationGroupShift();
+ uint32 groupBlock = start % (fVolume->BlockSize() << 3);
+ uint32 blockOffset = start % fVolume->BlockSize();
+
+ AllocationBlock cached(fVolume);
+
+ while (groupBlock < fGroups[group].NumBlocks() && length > 0) {
+ if (cached.SetTo(fGroups[group], groupBlock) != B_OK)
+ RETURN_ERROR(B_IO_ERROR);
+
+ for (; blockOffset < cached.NumBlockBits() && length > 0;
+ blockOffset++, length--) {
+ if (cached.IsUsed(blockOffset) != allocated) {
+ RETURN_ERROR(B_BAD_DATA);
+ }
+ }
+
+ if (++groupBlock >= fGroups[group].NumBlocks()) {
+ groupBlock = 0;
+ group++;
+ }
+ }
+
+ return B_OK;
+}
+
+
+status_t
BlockAllocator::CheckBlockRun(block_run run, const char* type,
check_control* control, bool allocated)
{
Modified: haiku/trunk/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h 2009-06-26 08:57:36 UTC (rev 31247)
+++ haiku/trunk/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h 2009-06-26 09:36:17 UTC (rev 31248)
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2008, Axel Dörfler, axeld at pinc-software.de.
+ * Copyright 2001-2009, Axel Dörfler, axeld at pinc-software.de.
* This file may be used under the terms of the MIT License.
*/
#ifndef BLOCK_ALLOCATOR_H
@@ -48,6 +48,8 @@
status_t StopChecking(check_control* control);
status_t CheckNextNode(check_control* control);
+ status_t CheckBlocks(off_t start, off_t length,
+ bool allocated = true);
status_t CheckBlockRun(block_run run,
const char* type = NULL,
check_control* control = NULL,
@@ -76,6 +78,7 @@
AllocationGroup* fGroups;
int32 fNumGroups;
uint32 fBlocksPerGroup;
+ uint32 fNumBlocks;
uint32* fCheckBitmap;
check_cookie* fCheckCookie;
Modified: haiku/trunk/src/add-ons/kernel/file_systems/bfs/Volume.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/file_systems/bfs/Volume.cpp 2009-06-26 08:57:36 UTC (rev 31247)
+++ haiku/trunk/src/add-ons/kernel/file_systems/bfs/Volume.cpp 2009-06-26 09:36:17 UTC (rev 31248)
@@ -655,8 +655,9 @@
// since the allocator has not been initialized yet, we
// cannot use BlockAllocator::BitmapSize() here
- fSuperBlock.log_blocks = ToBlockRun(AllocationGroups()
- * fSuperBlock.BlocksPerAllocationGroup() + 1);
+ off_t bitmapBlocks = (numBlocks + blockSize * 8 - 1) / (blockSize * 8);
+
+ fSuperBlock.log_blocks = ToBlockRun(bitmapBlocks + 1);
fSuperBlock.log_blocks.length = HOST_ENDIAN_TO_BFS_INT16(logSize);
fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64(
ToBlock(Log()));
More information about the Haiku-commits
mailing list