[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