BlockAllocator::CheckInode() now has support for the double indirect region
of the stream (so the "chkbfs" functionality is complete now). Fixed wrong block number report in BlockAllocator::CheckBlockRun(), blocks are now printed out in absolute numbers (not allocation_group relative anymore). Use Inode::IsContainer() where necessary instead of Inode::IsDirectory(). Fixed a big and nasty bug in AllocationBlock::SetTo(): the number of bits in a block could be calculated wrong for a partial allocation group which need more than one block in the bitmap - hopefully, that was the last remaining big bug in the block allocator. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2032 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
68ca164dc3
commit
95f8931641
@ -98,7 +98,7 @@ AllocationBlock::SetTo(AllocationGroup &group, uint16 block)
|
||||
// 8 blocks per byte
|
||||
fNumBits = fVolume->BlockSize() << 3;
|
||||
// the last group may have less bits in the last block
|
||||
if ((group.fNumBits % fNumBits) != 0)
|
||||
if (block * fNumBits > group.fNumBits)
|
||||
fNumBits = group.fNumBits % fNumBits;
|
||||
|
||||
return CachedBlock::SetTo(group.fStart + block) != NULL ? B_OK : B_ERROR;
|
||||
@ -574,7 +574,7 @@ BlockAllocator::Allocate(Transaction *transaction, const Inode *inode, off_t num
|
||||
group = data->direct[last].allocation_group;
|
||||
start = data->direct[last].start + data->direct[last].length;
|
||||
}
|
||||
} else if (inode->IsDirectory()) {
|
||||
} else if (inode->IsContainer()) {
|
||||
// directory data will go in the same allocation group as the inode is in
|
||||
// but after the inode data
|
||||
start = inode->BlockRun().start;
|
||||
@ -749,7 +749,7 @@ BlockAllocator::CheckNextNode(check_control *control)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!inode->IsDirectory()) {
|
||||
if (!inode->IsContainer()) {
|
||||
FATAL(("check: inode at %Ld should have been a directory\n", fVolume->ToBlock(cookie->current)));
|
||||
continue;
|
||||
}
|
||||
@ -849,7 +849,7 @@ BlockAllocator::CheckNextNode(check_control *control)
|
||||
Transaction transaction(fVolume, cookie->parent->BlockNumber());
|
||||
|
||||
inode->Node()->flags |= INODE_DONT_FREE_SPACE;
|
||||
status = cookie->parent->Remove(&transaction, name, NULL, inode->IsDirectory());
|
||||
status = cookie->parent->Remove(&transaction, name, NULL, inode->IsContainer());
|
||||
if (status == B_OK)
|
||||
transaction.Done();
|
||||
} else
|
||||
@ -865,7 +865,7 @@ BlockAllocator::CheckNextNode(check_control *control)
|
||||
cookie->stack.Push(inode->Attributes());
|
||||
|
||||
// push the directory on the stack so that it will be scanned later
|
||||
if (inode->IsDirectory() && !inode->IsIndex())
|
||||
if (inode->IsContainer() && !inode->IsIndex())
|
||||
cookie->stack.Push(inode->BlockRun());
|
||||
else {
|
||||
// check it now
|
||||
@ -922,7 +922,7 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
|
||||
uint32 block = run.start / bitsPerBlock;
|
||||
uint32 pos = run.start % bitsPerBlock;
|
||||
int32 length = 0;
|
||||
int64 firstMissing = -1, firstSet = -1;
|
||||
off_t firstMissing = -1, firstSet = -1;
|
||||
off_t firstGroupBlock = (off_t)run.allocation_group << fVolume->AllocationGroupShift();
|
||||
|
||||
AllocationBlock cached(fVolume);
|
||||
@ -931,6 +931,11 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
|
||||
if (cached.SetTo(fGroups[run.allocation_group], block) < B_OK)
|
||||
RETURN_ERROR(B_IO_ERROR);
|
||||
|
||||
if (pos >= cached.NumBlockBits()) {
|
||||
// something very strange has happened...
|
||||
RETURN_ERROR(B_ERROR);
|
||||
}
|
||||
|
||||
while (length < run.length && pos < cached.NumBlockBits()) {
|
||||
if (!cached.IsUsed(pos)) {
|
||||
if (control == NULL) {
|
||||
@ -938,12 +943,12 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
if (firstMissing == -1) {
|
||||
firstMissing = pos + block * bitsPerBlock;
|
||||
firstMissing = firstGroupBlock + pos + block * bitsPerBlock;
|
||||
control->errors |= BFS_MISSING_BLOCKS;
|
||||
}
|
||||
control->stats.missing++;
|
||||
} else if (firstMissing != -1) {
|
||||
PRINT(("%s: block_run(%ld, %u, %u): blocks %Ld - %ld are not allocated!\n", type, run.allocation_group, run.start, run.length, firstMissing, pos + block * bitsPerBlock - 1));
|
||||
PRINT(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are not allocated!\n", type, run.allocation_group, run.start, run.length, firstMissing, firstGroupBlock + pos + block * bitsPerBlock - 1));
|
||||
firstMissing = -1;
|
||||
}
|
||||
|
||||
@ -953,13 +958,13 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
|
||||
uint32 offset = pos + block * bitsPerBlock;
|
||||
if (CheckBitmapIsUsedAt(firstGroupBlock + offset)) {
|
||||
if (firstSet == -1) {
|
||||
firstSet = offset;
|
||||
firstSet = firstGroupBlock + offset;
|
||||
control->errors |= BFS_BLOCKS_ALREADY_SET;
|
||||
}
|
||||
control->stats.already_set++;
|
||||
} else {
|
||||
if (firstSet != -1) {
|
||||
FATAL(("%s: block_run(%ld, %u, %u): blocks %Ld - %ld are already set!\n", type, run.allocation_group, run.start, run.length, firstSet, offset - 1));
|
||||
FATAL(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are already set!\n", type, run.allocation_group, run.start, run.length, firstSet, firstGroupBlock + offset - 1));
|
||||
firstSet = -1;
|
||||
}
|
||||
SetCheckBitmapAt(firstGroupBlock + offset);
|
||||
@ -968,12 +973,14 @@ BlockAllocator::CheckBlockRun(block_run run, const char *type, check_control *co
|
||||
length++;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstMissing != -1)
|
||||
PRINT(("%s: block_run(%ld, %u, %u): blocks %Ld - %ld are not allocated!\n", type, run.allocation_group, run.start, run.length, firstMissing, pos + (block - 1) * bitsPerBlock - 1));
|
||||
if (firstSet != -1)
|
||||
FATAL(("%s: block_run(%ld, %u, %u): blocks %Ld - %ld are already set!\n", type, run.allocation_group, run.start, run.length, firstSet, pos + (block - 1) * bitsPerBlock - 1));
|
||||
if (block + 1 >= fBlocksPerGroup || length >= run.length) {
|
||||
if (firstMissing != -1)
|
||||
PRINT(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are not allocated!\n", type, run.allocation_group, run.start, run.length, firstMissing, firstGroupBlock + pos + block * bitsPerBlock - 1));
|
||||
if (firstSet != -1)
|
||||
FATAL(("%s: block_run(%ld, %u, %u): blocks %Ld - %Ld are already set!\n", type, run.allocation_group, run.start, run.length, firstSet, firstGroupBlock + pos + block * bitsPerBlock - 1));
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@ -1044,8 +1051,47 @@ BlockAllocator::CheckInode(Inode *inode, check_control *control)
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
// ToDo: add test for double indirect range!
|
||||
FATAL(("*** test for the double indirect range is not yet done ***\n"));
|
||||
int32 runsPerBlock = fVolume->BlockSize() / sizeof(block_run);
|
||||
int32 runsPerArray = runsPerBlock << ARRAY_BLOCKS_SHIFT;
|
||||
|
||||
CachedBlock cachedDirect(fVolume);
|
||||
int32 maxIndirectIndex = (data->double_indirect.length << fVolume->BlockShift()) / sizeof(block_run);
|
||||
|
||||
for (int32 indirectIndex = 0; indirectIndex < maxIndirectIndex; indirectIndex++) {
|
||||
// get the indirect array block
|
||||
block_run *array = (block_run *)cached.SetTo(fVolume->ToBlock(data->double_indirect)
|
||||
+ indirectIndex / runsPerBlock);
|
||||
if (array == NULL)
|
||||
return B_IO_ERROR;
|
||||
|
||||
block_run indirect = array[indirectIndex % runsPerBlock];
|
||||
// are we finished yet?
|
||||
if (indirect.IsZero())
|
||||
return B_OK;
|
||||
|
||||
status = CheckBlockRun(indirect, "double indirect->runs", control);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
int32 maxIndex = (indirect.length << fVolume->BlockShift()) / sizeof(block_run);
|
||||
|
||||
for (int32 index = 0; index < maxIndex; ) {
|
||||
block_run *runs = (block_run *)cachedDirect.SetTo(fVolume->ToBlock(indirect)
|
||||
+ index / runsPerBlock);
|
||||
if (runs == NULL)
|
||||
return B_IO_ERROR;
|
||||
|
||||
do {
|
||||
// are we finished yet?
|
||||
if (runs[index % runsPerBlock].IsZero())
|
||||
return B_OK;
|
||||
|
||||
status = CheckBlockRun(runs[index % runsPerBlock], "double indirect->runs->run", control);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
} while ((++index % runsPerArray) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
Loading…
x
Reference in New Issue
Block a user