* 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). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31248 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -533,6 +533,9 @@ BlockAllocator::Initialize(bool full)
|
|||||||
{
|
{
|
||||||
fNumGroups = fVolume->AllocationGroups();
|
fNumGroups = fVolume->AllocationGroups();
|
||||||
fBlocksPerGroup = fVolume->SuperBlock().BlocksPerAllocationGroup();
|
fBlocksPerGroup = fVolume->SuperBlock().BlocksPerAllocationGroup();
|
||||||
|
fNumBlocks = (fVolume->NumBlocks() + fVolume->BlockSize() * 8 - 1)
|
||||||
|
/ (fVolume->BlockSize() * 8);
|
||||||
|
|
||||||
fGroups = new AllocationGroup[fNumGroups];
|
fGroups = new AllocationGroup[fNumGroups];
|
||||||
if (fGroups == NULL)
|
if (fGroups == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -558,11 +561,10 @@ status_t
|
|||||||
BlockAllocator::InitializeAndClearBitmap(Transaction& transaction)
|
BlockAllocator::InitializeAndClearBitmap(Transaction& transaction)
|
||||||
{
|
{
|
||||||
status_t status = Initialize(false);
|
status_t status = Initialize(false);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
uint32 blocks = fBlocksPerGroup;
|
uint32 numBits = 8 * fBlocksPerGroup * fVolume->BlockSize();
|
||||||
uint32 numBits = 8 * blocks * fVolume->BlockSize();
|
|
||||||
uint32 blockShift = fVolume->BlockShift();
|
uint32 blockShift = fVolume->BlockShift();
|
||||||
|
|
||||||
uint32* buffer = (uint32*)malloc(numBits >> 3);
|
uint32* buffer = (uint32*)malloc(numBits >> 3);
|
||||||
@@ -572,12 +574,13 @@ BlockAllocator::InitializeAndClearBitmap(Transaction& transaction)
|
|||||||
memset(buffer, 0, numBits >> 3);
|
memset(buffer, 0, numBits >> 3);
|
||||||
|
|
||||||
off_t offset = 1;
|
off_t offset = 1;
|
||||||
|
// the bitmap starts directly after the super block
|
||||||
|
|
||||||
// initialize the AllocationGroup objects and clear the on-disk bitmap
|
// initialize the AllocationGroup objects and clear the on-disk bitmap
|
||||||
|
|
||||||
for (int32 i = 0; i < fNumGroups; i++) {
|
for (int32 i = 0; i < fNumGroups; i++) {
|
||||||
if (write_pos(fVolume->Device(), offset << blockShift, buffer,
|
if (write_pos(fVolume->Device(), offset << blockShift, buffer,
|
||||||
blocks << blockShift) < B_OK)
|
fBlocksPerGroup << blockShift) < B_OK)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
// the last allocation group may contain less blocks than the others
|
// the last allocation group may contain less blocks than the others
|
||||||
@@ -587,14 +590,14 @@ BlockAllocator::InitializeAndClearBitmap(Transaction& transaction)
|
|||||||
>> (blockShift + 3));
|
>> (blockShift + 3));
|
||||||
} else {
|
} else {
|
||||||
fGroups[i].fNumBits = numBits;
|
fGroups[i].fNumBits = numBits;
|
||||||
fGroups[i].fNumBlocks = blocks;
|
fGroups[i].fNumBlocks = fBlocksPerGroup;
|
||||||
}
|
}
|
||||||
fGroups[i].fStart = offset;
|
fGroups[i].fStart = offset;
|
||||||
fGroups[i].fFirstFree = fGroups[i].fLargestStart = 0;
|
fGroups[i].fFirstFree = fGroups[i].fLargestStart = 0;
|
||||||
fGroups[i].fFreeBits = fGroups[i].fLargestLength = fGroups[i].fNumBits;
|
fGroups[i].fFreeBits = fGroups[i].fLargestLength = fGroups[i].fNumBits;
|
||||||
fGroups[i].fLargestValid = true;
|
fGroups[i].fLargestValid = true;
|
||||||
|
|
||||||
offset += blocks;
|
offset += fBlocksPerGroup;
|
||||||
}
|
}
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
@@ -679,16 +682,16 @@ BlockAllocator::_Initialize(BlockAllocator* allocator)
|
|||||||
|
|
||||||
// check if block bitmap and log area are reserved
|
// check if block bitmap and log area are reserved
|
||||||
uint32 reservedBlocks = volume->Log().Start() + volume->Log().Length();
|
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);
|
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 "
|
FATAL(("could not allocate reserved space for block "
|
||||||
"bitmap/log!\n"));
|
"bitmap/log!\n"));
|
||||||
volume->Panic();
|
volume->Panic();
|
||||||
} else {
|
} else {
|
||||||
FATAL(("space for block bitmap or log area was not reserved!\n"));
|
|
||||||
|
|
||||||
transaction.Done();
|
transaction.Done();
|
||||||
|
FATAL(("space for block bitmap or log area was not reserved!\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1011,19 +1014,19 @@ BlockAllocator::Free(Transaction& transaction, block_run run)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (CheckBlockRun(run) < B_OK)
|
if (CheckBlockRun(run) != B_OK)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CHECK_ALLOCATION_GROUP(group);
|
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);
|
RETURN_ERROR(B_IO_ERROR);
|
||||||
|
|
||||||
CHECK_ALLOCATION_GROUP(group);
|
CHECK_ALLOCATION_GROUP(group);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#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 "
|
DEBUGGER(("CheckBlockRun() reports allocated blocks (which were just "
|
||||||
"freed)\n"));
|
"freed)\n"));
|
||||||
}
|
}
|
||||||
@@ -1038,7 +1041,7 @@ BlockAllocator::Free(Transaction& transaction, block_run run)
|
|||||||
size_t
|
size_t
|
||||||
BlockAllocator::BitmapSize() const
|
BlockAllocator::BitmapSize() const
|
||||||
{
|
{
|
||||||
return fVolume->BlockSize() * fNumGroups * fBlocksPerGroup;
|
return fVolume->BlockSize() * fNumBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1501,6 +1504,42 @@ BlockAllocator::_SetCheckBitmapAt(off_t block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! 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
|
status_t
|
||||||
BlockAllocator::CheckBlockRun(block_run run, const char* type,
|
BlockAllocator::CheckBlockRun(block_run run, const char* type,
|
||||||
check_control* control, bool allocated)
|
check_control* control, bool allocated)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2008, Axel Dörfler, [email protected].
|
* Copyright 2001-2009, Axel Dörfler, [email protected].
|
||||||
* This file may be used under the terms of the MIT License.
|
* This file may be used under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef BLOCK_ALLOCATOR_H
|
#ifndef BLOCK_ALLOCATOR_H
|
||||||
@@ -48,6 +48,8 @@ public:
|
|||||||
status_t StopChecking(check_control* control);
|
status_t StopChecking(check_control* control);
|
||||||
status_t CheckNextNode(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,
|
status_t CheckBlockRun(block_run run,
|
||||||
const char* type = NULL,
|
const char* type = NULL,
|
||||||
check_control* control = NULL,
|
check_control* control = NULL,
|
||||||
@@ -76,6 +78,7 @@ private:
|
|||||||
AllocationGroup* fGroups;
|
AllocationGroup* fGroups;
|
||||||
int32 fNumGroups;
|
int32 fNumGroups;
|
||||||
uint32 fBlocksPerGroup;
|
uint32 fBlocksPerGroup;
|
||||||
|
uint32 fNumBlocks;
|
||||||
|
|
||||||
uint32* fCheckBitmap;
|
uint32* fCheckBitmap;
|
||||||
check_cookie* fCheckCookie;
|
check_cookie* fCheckCookie;
|
||||||
|
|||||||
@@ -655,8 +655,9 @@ Volume::Initialize(int fd, const char* name, uint32 blockSize,
|
|||||||
|
|
||||||
// since the allocator has not been initialized yet, we
|
// since the allocator has not been initialized yet, we
|
||||||
// cannot use BlockAllocator::BitmapSize() here
|
// cannot use BlockAllocator::BitmapSize() here
|
||||||
fSuperBlock.log_blocks = ToBlockRun(AllocationGroups()
|
off_t bitmapBlocks = (numBlocks + blockSize * 8 - 1) / (blockSize * 8);
|
||||||
* fSuperBlock.BlocksPerAllocationGroup() + 1);
|
|
||||||
|
fSuperBlock.log_blocks = ToBlockRun(bitmapBlocks + 1);
|
||||||
fSuperBlock.log_blocks.length = HOST_ENDIAN_TO_BFS_INT16(logSize);
|
fSuperBlock.log_blocks.length = HOST_ENDIAN_TO_BFS_INT16(logSize);
|
||||||
fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64(
|
fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64(
|
||||||
ToBlock(Log()));
|
ToBlock(Log()));
|
||||||
|
|||||||
Reference in New Issue
Block a user