* added some support for 64bit feature: extended struct ext2_block_group, block number types changed from uint32 to off_t

* added error traces, asserts
* BitmapBlock::CheckUnmarked() and CheckMarked() computed a wrong remainingBits and mask


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39203 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2010-10-30 13:45:01 +00:00
parent 0a5b0dae01
commit d8772e0c20
14 changed files with 434 additions and 239 deletions
@@ -251,11 +251,11 @@ Attribute::_Find(const char* name, int32 index)
// try to find it in the small data region // try to find it in the small data region
if (fInode->HasExtraAttributes() if (fInode->HasExtraAttributes()
&& recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) { && recursive_lock_lock(&fInode->SmallDataLock()) == B_OK) {
uint32 block; off_t blockNum;
fVolume->GetInodeBlock(fInode->ID(), block); fVolume->GetInodeBlock(fInode->ID(), blockNum);
if (block != 0) { if (blockNum != 0) {
fBlock.SetTo(block); fBlock.SetTo(blockNum);
const uint8* start = fBlock.Block() const uint8* start = fBlock.Block()
+ fVolume->InodeBlockIndex(fInode->ID()) * fVolume->InodeSize(); + fVolume->InodeBlockIndex(fInode->ID()) * fVolume->InodeSize();
const uint8* end = start + fVolume->InodeSize(); const uint8* end = start + fVolume->InodeSize();
@@ -63,10 +63,12 @@ BitmapBlock::CheckUnmarked(uint32 start, uint32 length)
if (start + length > fNumBits) if (start + length > fNumBits)
return false; return false;
if (length == 0)
return true;
uint32 startIndex = start >> 5; uint32 startIndex = start >> 5;
uint32 startBit = start & 0x1F; uint32 startBit = start & 0x1F;
uint32 remainingBits = (length - startBit) & 0x1F; uint32 remainingBits = (length + startBit) & 0x1F;
uint32 iterations; uint32 iterations;
@@ -86,28 +88,39 @@ BitmapBlock::CheckUnmarked(uint32 start, uint32 length)
uint32 index = startIndex; uint32 index = startIndex;
uint32 mask = 0; uint32 mask = 0;
TRACE("BitmapBlock::CheckUnmarked(): startBit: %lu iterations %lu remainingbits %lu\n",
startBit, iterations, remainingBits);
if (startBit != 0) { if (startBit != 0) {
mask = ~((1 << startBit) - 1); mask = ~((1 << startBit) - 1);
uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]); uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
if ((bits & mask) != 0) if ((bits & mask) != 0) {
TRACE("BitmapBlock::CheckUnmarked(): start %lx mask %lx\n", bits, mask);
return false; return false;
}
index += 1; index += 1;
} else } else
iterations++; iterations++;
for (; iterations > 0; --iterations) { for (; iterations > 0; --iterations) {
if (data[index++] != 0) if (data[index++] != 0) {
TRACE("BitmapBlock::CheckUnmarked(): iterations %lu bits: %lX\n", iterations,
data[index - 1]);
return false; return false;
}
} }
if (remainingBits != 0) { if (remainingBits != 0) {
mask = (1 << (remainingBits + 1)) - 1; mask = (1 << remainingBits) - 1;
uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]); uint32 bits = B_LENDIAN_TO_HOST_INT32(data[index]);
if ((bits & mask) != 0) if ((bits & mask) != 0) {
TRACE("BitmapBlock::CheckUnmarked(): remainingBits %ld remaining %lX mask %lX\n",
remainingBits, bits, mask);
return false; return false;
}
} }
return true; return true;
@@ -123,10 +136,12 @@ BitmapBlock::CheckMarked(uint32 start, uint32 length)
if (start + length > fNumBits) if (start + length > fNumBits)
return false; return false;
if (length == 0)
return true;
uint32 startIndex = start >> 5; uint32 startIndex = start >> 5;
uint32 startBit = start & 0x1F; uint32 startBit = start & 0x1F;
uint32 remainingBits = (length - startBit) & 0x1F; uint32 remainingBits = (length + startBit) & 0x1F;
uint32 iterations; uint32 iterations;
@@ -164,7 +179,7 @@ BitmapBlock::CheckMarked(uint32 start, uint32 length)
} }
if (remainingBits != 0) { if (remainingBits != 0) {
mask = (1 << (remainingBits + 1)) - 1; mask = (1 << remainingBits) - 1;
uint32 bits = B_HOST_TO_LENDIAN_INT32(data[index]); uint32 bits = B_HOST_TO_LENDIAN_INT32(data[index]);
if ((bits & mask) != mask) if ((bits & mask) != mask)
@@ -183,7 +198,7 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
uint32 startIndex = start >> 5; uint32 startIndex = start >> 5;
uint32 startBit = start & 0x1F; uint32 startBit = start & 0x1F;
uint32 remainingBits = (length - 32 + startBit) & 0x1F; uint32 remainingBits = (length + startBit) & 0x1F;
uint32 iterations; uint32 iterations;
@@ -194,8 +209,11 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
uint32 mask = (1 << (startBit + length)) - 1; uint32 mask = (1 << (startBit + length)) - 1;
mask &= ~((1 << startBit) - 1); mask &= ~((1 << startBit) - 1);
if ((bits & mask) != 0) if ((bits & mask) != 0) {
TRACE("BitmapBlock::Mark() Marking failed bits %lx "
"startBit %ld\n", bits, startBit);
return false; return false;
}
bits |= mask; bits |= mask;
@@ -221,8 +239,11 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
TRACE("BitmapBlock::Mark(): index %lu mask: %lX, bits: %lX\n", index, TRACE("BitmapBlock::Mark(): index %lu mask: %lX, bits: %lX\n", index,
mask, bits); mask, bits);
if (!force && (bits & mask) != 0) if (!force && (bits & mask) != 0) {
TRACE("BitmapBlock::Mark() Marking failed bits %lx "
"startBit %ld\n", bits, startBit);
return false; return false;
}
bits |= mask; bits |= mask;
fData[index] = B_HOST_TO_LENDIAN_INT32(bits); fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
@@ -233,8 +254,11 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
mask = 0xFFFFFFFF; mask = 0xFFFFFFFF;
for (; iterations > 0; --iterations) { for (; iterations > 0; --iterations) {
if (!force && fData[index] != 0) if (!force && fData[index] != 0) {
TRACE("BitmapBlock::Mark() Marking failed "
"index %ld, iterations %ld\n", index, iterations);
return false; return false;
}
fData[index++] |= mask; fData[index++] |= mask;
} }
@@ -244,8 +268,10 @@ BitmapBlock::Mark(uint32 start, uint32 length, bool force)
TRACE("BitmapBlock::Mark(): marking index %lu remaining %lu bits: %lX," TRACE("BitmapBlock::Mark(): marking index %lu remaining %lu bits: %lX,"
" mask: %lX\n", index, remainingBits, bits, mask); " mask: %lX\n", index, remainingBits, bits, mask);
if (!force && (bits & mask) != 0) if (!force && (bits & mask) != 0) {
TRACE("BitmapBlock::Mark() Marking failed remaining\n");
return false; return false;
}
bits |= mask; bits |= mask;
fData[index] = B_HOST_TO_LENDIAN_INT32(bits); fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
@@ -266,7 +292,7 @@ BitmapBlock::Unmark(uint32 start, uint32 length, bool force)
uint32 startIndex = start >> 5; uint32 startIndex = start >> 5;
uint32 startBit = start & 0x1F; uint32 startBit = start & 0x1F;
uint32 remainingBits = (length - 32 + startBit) & 0x1F; uint32 remainingBits = (length + startBit) & 0x1F;
TRACE("BitmapBlock::Unmark(): start index: %lu, start bit: %lu, remaining " TRACE("BitmapBlock::Unmark(): start index: %lu, start bit: %lu, remaining "
"bits: %lu)\n", startIndex, startBit, remainingBits); "bits: %lu)\n", startIndex, startBit, remainingBits);
@@ -282,8 +308,11 @@ BitmapBlock::Unmark(uint32 start, uint32 length, bool force)
TRACE("BitmapBlock::Unmark(): mask: %lx\n", mask); TRACE("BitmapBlock::Unmark(): mask: %lx\n", mask);
if ((bits & mask) != mask) if ((bits & mask) != mask) {
TRACE("BitmapBlock::Unmark() Marking failed bits %lx "
"startBit %ld\n", bits, startBit);
return false; return false;
}
bits &= ~mask; bits &= ~mask;
@@ -319,8 +348,11 @@ BitmapBlock::Unmark(uint32 start, uint32 length, bool force)
mask = 0xFFFFFFFF; mask = 0xFFFFFFFF;
for (; iterations > 0; --iterations) { for (; iterations > 0; --iterations) {
if (!force && fData[index] != mask) if (!force && fData[index] != mask) {
TRACE("BitmapBlock::Unmark() Marking failed "
"index %ld, iterations %ld\n", index, iterations);
return false; return false;
}
fData[index++] = 0; fData[index++] = 0;
} }
@@ -332,8 +364,10 @@ BitmapBlock::Unmark(uint32 start, uint32 length, bool force)
TRACE("BitmapBlock::Unmark(): mask: %lx, bits: %lx\n", mask, bits); TRACE("BitmapBlock::Unmark(): mask: %lx, bits: %lx\n", mask, bits);
if (!force && (bits & mask) != mask) if (!force && (bits & mask) != mask) {
TRACE("BitmapBlock::Unmark() Marking failed remaining\n");
return false; return false;
}
bits &= ~mask; bits &= ~mask;
fData[index] = B_HOST_TO_LENDIAN_INT32(bits); fData[index] = B_HOST_TO_LENDIAN_INT32(bits);
@@ -460,7 +494,7 @@ BitmapBlock::FindNextUnmarked(uint32& pos)
} }
} }
panic("Couldn't find unmarked bit inside an int32 whith value zero!?\n"); panic("Couldn't find unmarked bit inside an int32 with value zero!?\n");
} }
@@ -504,6 +538,9 @@ BitmapBlock::FindPreviousMarked(uint32& pos)
bit = 31; bit = 31;
} }
TRACE("BitmapBlock::FindPreviousMarked(): index: %lu bit: %lu bits: %lx\n",
index, bit, bits);
for (; bit >= 0; --bit) { for (; bit >= 0; --bit) {
// Find the unmarked bit // Find the unmarked bit
if ((bits >> bit & 1) != 0) { if ((bits >> bit & 1) != 0) {
@@ -512,7 +549,7 @@ BitmapBlock::FindPreviousMarked(uint32& pos)
} }
} }
panic("Couldn't find marked bit inside an int32 whith value different than " panic("Couldn't find marked bit inside an int32 with value different than "
"zero!?\n"); "zero!?\n");
} }
@@ -15,12 +15,16 @@
#include "Inode.h" #include "Inode.h"
#undef ASSERT
//#define TRACE_EXT2 //#define TRACE_EXT2
#ifdef TRACE_EXT2 #ifdef TRACE_EXT2
# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x) # define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
# define ASSERT(x) { if (!(x)) kernel_debugger("ext2: assert failed: " #x "\n"); }
#else #else
# define TRACE(x...) ; # define TRACE(x...) ;
# define ASSERT(x) ;
#endif #endif
#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x)
class AllocationBlockGroup : public TransactionListener { class AllocationBlockGroup : public TransactionListener {
@@ -67,7 +71,7 @@ private:
uint32 fStart; uint32 fStart;
uint32 fNumBits; uint32 fNumBits;
uint32 fBitmapBlock; off_t fBitmapBlock;
uint32 fFreeBits; uint32 fFreeBits;
uint32 fFirstFree; uint32 fFirstFree;
@@ -122,14 +126,15 @@ AllocationBlockGroup::Initialize(Volume* volume, uint32 blockGroup,
if (status != B_OK) if (status != B_OK)
return status; return status;
fBitmapBlock = fGroupDescriptor->BlockBitmap(); fBitmapBlock = fGroupDescriptor->BlockBitmap(fVolume->Has64bitFeature());
status = ScanFreeRanges(); status = ScanFreeRanges();
if (fGroupDescriptor->FreeBlocks() != fFreeBits) { if (fGroupDescriptor->FreeBlocks(fVolume->Has64bitFeature()) != fFreeBits) {
TRACE("AllocationBlockGroup::Initialize(): Mismatch between counted " TRACE("AllocationBlockGroup::Initialize(): Mismatch between counted "
"free blocks (%lu) and what is set on the group descriptor " "free blocks (%lu) and what is set on the group descriptor "
"(%lu)\n", fFreeBits, (uint32)fGroupDescriptor->FreeBlocks()); "(%lu)\n", fFreeBits,
fGroupDescriptor->FreeBlocks(fVolume->Has64bitFeature()));
return B_BAD_DATA; return B_BAD_DATA;
} }
@@ -161,6 +166,7 @@ AllocationBlockGroup::ScanFreeRanges()
if (start != block.NumBits()) { if (start != block.NumBits()) {
block.FindNextMarked(end); block.FindNextMarked(end);
_AddFreeRange(start, end - start); _AddFreeRange(start, end - start);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
start = end; start = end;
} }
} }
@@ -191,15 +197,19 @@ AllocationBlockGroup::Allocate(Transaction& transaction, uint32 start,
if (!block.SetToWritable(transaction, fBitmapBlock)) if (!block.SetToWritable(transaction, fBitmapBlock))
return B_ERROR; return B_ERROR;
TRACE("AllocationBlockGroup::Allocate(): Largest range in %lu-%lu\n",
fLargestStart, fLargestStart + fLargestLength);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
if (!block.Mark(start, length)) { if (!block.Mark(start, length)) {
TRACE("Failed to allocate blocks from %lu to %lu. Some were " ERROR("Failed to allocate blocks from %lu to %lu. Some were "
"already allocated.\n", start, start + length); "already allocated.\n", start, start + length);
return B_ERROR; return B_ERROR;
} }
fFreeBits -= length; fFreeBits -= length;
fGroupDescriptor->SetFreeBlocks((uint16)fFreeBits); fGroupDescriptor->SetFreeBlocks(fFreeBits, fVolume->Has64bitFeature());
fVolume->WriteBlockGroup(transaction, fBlockGroup); fVolume->WriteBlockGroup(transaction, fBlockGroup);
if (start == fLargestStart) { if (start == fLargestStart) {
@@ -227,6 +237,10 @@ AllocationBlockGroup::Allocate(Transaction& transaction, uint32 start,
return B_OK; return B_OK;
} }
TRACE("AllocationBlockGroup::Allocate(): Largest range in %lu-%lu\n",
fLargestStart, fLargestStart + fLargestLength);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
if (fLargestLength < fNumBits / 2) if (fLargestLength < fNumBits / 2)
block.FindLargestUnmarkedRange(fLargestStart, fLargestLength); block.FindLargestUnmarkedRange(fLargestStart, fLargestLength);
@@ -256,8 +270,12 @@ AllocationBlockGroup::Free(Transaction& transaction, uint32 start,
if (!block.SetToWritable(transaction, fBitmapBlock)) if (!block.SetToWritable(transaction, fBitmapBlock))
return B_ERROR; return B_ERROR;
TRACE("AllocationBlockGroup::Free(): Largest range in %lu-%lu\n",
fLargestStart, fLargestStart + fLargestLength);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
if (!block.Unmark(start, length)) { if (!block.Unmark(start, length)) {
TRACE("Failed to free blocks from %lu to %lu. Some were " ERROR("Failed to free blocks from %lu to %lu. Some were "
"already freed.\n", start, start + length); "already freed.\n", start, start + length);
return B_ERROR; return B_ERROR;
} }
@@ -279,6 +297,7 @@ AllocationBlockGroup::Free(Transaction& transaction, uint32 start,
uint32 newStart = start; uint32 newStart = start;
block.FindPreviousMarked(newStart); block.FindPreviousMarked(newStart);
newStart++;
if (newEnd - newStart > fLargestLength) { if (newEnd - newStart > fLargestLength) {
fLargestLength = newEnd - newStart; fLargestLength = newEnd - newStart;
@@ -286,8 +305,12 @@ AllocationBlockGroup::Free(Transaction& transaction, uint32 start,
} }
} }
TRACE("AllocationBlockGroup::Free(): Largest range in %lu-%lu\n",
fLargestStart, fLargestStart + fLargestLength);
ASSERT(block.CheckUnmarked(fLargestStart, fLargestLength));
fFreeBits += length; fFreeBits += length;
fGroupDescriptor->SetFreeBlocks((uint16)fFreeBits); fGroupDescriptor->SetFreeBlocks(fFreeBits, fVolume->Has64bitFeature());
fVolume->WriteBlockGroup(transaction, fBlockGroup); fVolume->WriteBlockGroup(transaction, fBlockGroup);
return B_OK; return B_OK;
@@ -459,17 +482,17 @@ BlockAllocator::Initialize()
status_t status_t
BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum, BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum,
uint32 maximum, uint32& blockGroup, uint32& start, uint32& length) uint32 maximum, uint32& blockGroup, off_t& start, uint32& length)
{ {
TRACE("BlockAllocator::AllocateBlocks()\n"); TRACE("BlockAllocator::AllocateBlocks()\n");
MutexLocker lock(fLock); MutexLocker lock(fLock);
TRACE("BlockAllocator::AllocateBlocks(): Acquired lock\n"); TRACE("BlockAllocator::AllocateBlocks(): Acquired lock\n");
TRACE("BlockAllocator::AllocateBlocks(): transaction: %ld, min: %lu, " TRACE("BlockAllocator::AllocateBlocks(): transaction: %ld, min: %lu, "
"max: %lu, block group: %lu, start: %lu, num groups: %lu\n", "max: %lu, block group: %lu, start: %llu, num groups: %lu\n",
transaction.ID(), minimum, maximum, blockGroup, start, fNumGroups); transaction.ID(), minimum, maximum, blockGroup, start, fNumGroups);
uint32 bestStart = 0; off_t bestStart = 0;
uint32 bestLength = 0; uint32 bestLength = 0;
uint32 bestGroup = 0; uint32 bestGroup = 0;
@@ -490,7 +513,7 @@ BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum,
bestGroup = groupNum; bestGroup = groupNum;
TRACE("BlockAllocator::AllocateBlocks(): Found a better " TRACE("BlockAllocator::AllocateBlocks(): Found a better "
"range: block group: %lu, %lu-%lu\n", groupNum, "range: block group: %lu, %llu-%llu\n", groupNum,
bestStart, bestStart + bestLength); bestStart, bestStart + bestLength);
if (bestLength >= maximum) if (bestLength >= maximum)
@@ -520,7 +543,7 @@ BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum,
bestLength = maximum; bestLength = maximum;
TRACE("BlockAllocator::AllocateBlocks(): Selected range: block group %lu, " TRACE("BlockAllocator::AllocateBlocks(): Selected range: block group %lu, "
"%lu-%lu\n", bestGroup, bestStart, bestStart + bestLength); "%llu-%llu\n", bestGroup, bestStart, bestStart + bestLength);
status_t status = fGroups[bestGroup].Allocate(transaction, bestStart, status_t status = fGroups[bestGroup].Allocate(transaction, bestStart,
bestLength); bestLength);
@@ -540,7 +563,7 @@ BlockAllocator::AllocateBlocks(Transaction& transaction, uint32 minimum,
status_t status_t
BlockAllocator::Allocate(Transaction& transaction, Inode* inode, BlockAllocator::Allocate(Transaction& transaction, Inode* inode,
off_t numBlocks, uint32 minimum, uint32& start, uint32& allocated) off_t numBlocks, uint32 minimum, off_t& start, uint32& allocated)
{ {
if (numBlocks <= 0) if (numBlocks <= 0)
return B_ERROR; return B_ERROR;
@@ -617,9 +640,9 @@ BlockAllocator::Allocate(Transaction& transaction, Inode* inode,
status_t status_t
BlockAllocator::Free(Transaction& transaction, uint32 start, uint32 length) BlockAllocator::Free(Transaction& transaction, off_t start, uint32 length)
{ {
TRACE("BlockAllocator::Free(%lu, %lu)\n", start, length); TRACE("BlockAllocator::Free(%llu, %lu)\n", start, length);
MutexLocker lock(fLock); MutexLocker lock(fLock);
if (start <= fFirstBlock) { if (start <= fFirstBlock) {
@@ -633,17 +656,19 @@ BlockAllocator::Free(Transaction& transaction, uint32 start, uint32 length)
TRACE("BlockAllocator::Free(): first block: %lu, blocks per group: %lu\n", TRACE("BlockAllocator::Free(): first block: %lu, blocks per group: %lu\n",
fFirstBlock, fBlocksPerGroup); fFirstBlock, fBlocksPerGroup);
start -= fFirstBlock; //start -= fFirstBlock;
uint32 end = start + length - 1; off_t end = start + length - 1;
uint32 group = start / fBlocksPerGroup; uint32 group = start / fBlocksPerGroup;
if (group >= fNumGroups)
panic("BlockAllocator::Free() group %ld too big (fNumGroups %ld)\n", group, fNumGroups);
uint32 lastGroup = end / fBlocksPerGroup; uint32 lastGroup = end / fBlocksPerGroup;
start = start % fBlocksPerGroup; start = start % fBlocksPerGroup;
if (group == lastGroup) if (group == lastGroup)
return fGroups[group].Free(transaction, start, length); return fGroups[group].Free(transaction, start, length);
TRACE("BlockAllocator::Free(): Freeing from group %lu: %lu, %lu\n", group, TRACE("BlockAllocator::Free(): Freeing from group %lu: %llu, %llu\n", group,
start, fGroups[group].NumBits() - start); start, fGroups[group].NumBits() - start);
status_t status = fGroups[group].Free(transaction, start, status_t status = fGroups[group].Free(transaction, start,
@@ -658,7 +683,7 @@ BlockAllocator::Free(Transaction& transaction, uint32 start, uint32 length)
return status; return status;
} }
TRACE("BlockAllocator::Free(): Freeing from group %lu: 0-%lu \n", group, TRACE("BlockAllocator::Free(): Freeing from group %lu: 0-%llu \n", group,
end % fBlocksPerGroup); end % fBlocksPerGroup);
return fGroups[group].Free(transaction, 0, (end + 1) % fBlocksPerGroup); return fGroups[group].Free(transaction, 0, (end + 1) % fBlocksPerGroup);
} }
@@ -674,8 +699,8 @@ BlockAllocator::_Initialize(BlockAllocator* allocator)
AllocationBlockGroup* groups = allocator->fGroups; AllocationBlockGroup* groups = allocator->fGroups;
uint32 numGroups = allocator->fNumGroups - 1; uint32 numGroups = allocator->fNumGroups - 1;
uint32 freeBlocks = 0; off_t freeBlocks = 0;
TRACE("BlockAllocator::_Initialize(): free blocks: %lu\n", freeBlocks); TRACE("BlockAllocator::_Initialize(): free blocks: %llu\n", freeBlocks);
for (uint32 i = 0; i < numGroups; ++i) { for (uint32 i = 0; i < numGroups; ++i) {
status_t status = groups[i].Initialize(volume, i, status_t status = groups[i].Initialize(volume, i,
@@ -686,7 +711,7 @@ BlockAllocator::_Initialize(BlockAllocator* allocator)
} }
freeBlocks += groups[i].FreeBits(); freeBlocks += groups[i].FreeBits();
TRACE("BlockAllocator::_Initialize(): free blocks: %lu\n", freeBlocks); TRACE("BlockAllocator::_Initialize(): free blocks: %llu\n", freeBlocks);
} }
// Last block group may have less blocks // Last block group may have less blocks
@@ -700,13 +725,13 @@ BlockAllocator::_Initialize(BlockAllocator* allocator)
freeBlocks += groups[numGroups].FreeBits(); freeBlocks += groups[numGroups].FreeBits();
TRACE("BlockAllocator::_Initialize(): free blocks: %lu\n", freeBlocks); TRACE("BlockAllocator::_Initialize(): free blocks: %llu\n", freeBlocks);
mutex_unlock(&allocator->fLock); mutex_unlock(&allocator->fLock);
if (freeBlocks != volume->NumFreeBlocks()) { if (freeBlocks != volume->NumFreeBlocks()) {
TRACE("Counted free blocks (%lu) doesn't match value in the " TRACE("Counted free blocks (%llu) doesn't match value in the "
"superblock (%lu).\n", freeBlocks, (uint32)volume->NumFreeBlocks()); "superblock (%llu).\n", freeBlocks, volume->NumFreeBlocks());
return B_BAD_DATA; return B_BAD_DATA;
} }
@@ -27,11 +27,11 @@ public:
status_t AllocateBlocks(Transaction& transaction, status_t AllocateBlocks(Transaction& transaction,
uint32 minimum, uint32 maximum, uint32& blockGroup, uint32 minimum, uint32 maximum, uint32& blockGroup,
uint32& start, uint32& length); off_t& start, uint32& length);
status_t Allocate(Transaction& transaction, Inode* inode, status_t Allocate(Transaction& transaction, Inode* inode,
off_t numBlocks, uint32 minimum, uint32& start, off_t numBlocks, uint32 minimum, off_t& start,
uint32& length); uint32& length);
status_t Free(Transaction& transaction, uint32 start, status_t Free(Transaction& transaction, off_t start,
uint32 length); uint32 length);
uint32 FreeBlocks(); uint32 FreeBlocks();
@@ -16,16 +16,16 @@
class CachedBlock { class CachedBlock {
public: public:
CachedBlock(Volume* volume); CachedBlock(Volume* volume);
CachedBlock(Volume* volume, uint32 block); CachedBlock(Volume* volume, off_t block);
~CachedBlock(); ~CachedBlock();
void Keep(); void Keep();
void Unset(); void Unset();
const uint8* SetTo(uint32 block); const uint8* SetTo(off_t block);
uint8* SetToWritable(Transaction& transaction, uint8* SetToWritable(Transaction& transaction,
uint32 block, bool empty = false); off_t block, bool empty = false);
uint8* SetToWritableWithoutTransaction(uint32 block, uint8* SetToWritableWithoutTransaction(off_t block,
bool empty = false); bool empty = false);
const uint8* Block() const { return fBlock; } const uint8* Block() const { return fBlock; }
@@ -36,12 +36,12 @@ private:
CachedBlock &operator=(const CachedBlock &); CachedBlock &operator=(const CachedBlock &);
// no implementation // no implementation
uint8* _SetToWritableEtc(int32 transaction, uint32 block, uint8* _SetToWritableEtc(int32 transaction, off_t block,
bool empty); bool empty);
protected: protected:
Volume* fVolume; Volume* fVolume;
uint32 fBlockNumber; off_t fBlockNumber;
uint8* fBlock; uint8* fBlock;
}; };
@@ -60,7 +60,7 @@ CachedBlock::CachedBlock(Volume* volume)
inline inline
CachedBlock::CachedBlock(Volume* volume, uint32 block) CachedBlock::CachedBlock(Volume* volume, off_t block)
: :
fVolume(volume), fVolume(volume),
fBlockNumber(0), fBlockNumber(0),
@@ -95,7 +95,7 @@ CachedBlock::Unset()
inline const uint8 * inline const uint8 *
CachedBlock::SetTo(uint32 block) CachedBlock::SetTo(off_t block)
{ {
Unset(); Unset();
fBlockNumber = block; fBlockNumber = block;
@@ -104,20 +104,20 @@ CachedBlock::SetTo(uint32 block)
inline uint8* inline uint8*
CachedBlock::SetToWritable(Transaction& transaction, uint32 block, bool empty) CachedBlock::SetToWritable(Transaction& transaction, off_t block, bool empty)
{ {
return _SetToWritableEtc(transaction.ID(), block, empty); return _SetToWritableEtc(transaction.ID(), block, empty);
} }
inline uint8* inline uint8*
CachedBlock::SetToWritableWithoutTransaction(uint32 block, bool empty) CachedBlock::SetToWritableWithoutTransaction(off_t block, bool empty)
{ {
return _SetToWritableEtc((int32)-1, block, empty); return _SetToWritableEtc((int32)-1, block, empty);
} }
inline uint8* inline uint8*
CachedBlock::_SetToWritableEtc(int32 transaction, uint32 block, bool empty) CachedBlock::_SetToWritableEtc(int32 transaction, off_t block, bool empty)
{ {
Unset(); Unset();
fBlockNumber = block; fBlockNumber = block;
@@ -19,6 +19,7 @@
#else #else
# define TRACE(x...) ; # define TRACE(x...) ;
#endif #endif
#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x)
DataStream::DataStream(Volume* volume, ext2_data_stream* stream, DataStream::DataStream(Volume* volume, ext2_data_stream* stream,
@@ -51,12 +52,12 @@ DataStream::~DataStream()
status_t status_t
DataStream::Enlarge(Transaction& transaction, uint32& numBlocks) DataStream::Enlarge(Transaction& transaction, off_t& numBlocks)
{ {
TRACE("DataStream::Enlarge(): current size: %lu, target size: %lu\n", TRACE("DataStream::Enlarge(): current size: %llu, target size: %llu\n",
fNumBlocks, numBlocks); fNumBlocks, numBlocks);
uint32 targetBlocks = numBlocks; off_t targetBlocks = numBlocks;
fWaiting = _BlocksNeeded(numBlocks); fWaiting = _BlocksNeeded(numBlocks);
numBlocks = fWaiting; numBlocks = fWaiting;
@@ -65,42 +66,57 @@ DataStream::Enlarge(Transaction& transaction, uint32& numBlocks)
if (fNumBlocks <= kMaxDirect) { if (fNumBlocks <= kMaxDirect) {
status = _AddForDirectBlocks(transaction, targetBlocks); status = _AddForDirectBlocks(transaction, targetBlocks);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::Enlarge(): _AddForDirectBlocks() failed\n");
return status; return status;
}
TRACE("DataStream::Enlarge(): current size: %lu, target size: %lu\n", TRACE("DataStream::Enlarge(): current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks); fNumBlocks, targetBlocks);
if (fNumBlocks == targetBlocks) if (fNumBlocks == targetBlocks)
return B_OK; return B_OK;
} }
TRACE("DataStream::Enlarge(): indirect current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks);
if (fNumBlocks <= kMaxIndirect) { if (fNumBlocks <= kMaxIndirect) {
status = _AddForIndirectBlock(transaction, targetBlocks); status = _AddForIndirectBlock(transaction, targetBlocks);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::Enlarge(): _AddForIndirectBlock() failed\n");
return status; return status;
}
TRACE("DataStream::Enlarge(): current size: %lu, target size: %lu\n", TRACE("DataStream::Enlarge(): current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks); fNumBlocks, targetBlocks);
if (fNumBlocks == targetBlocks) if (fNumBlocks == targetBlocks)
return B_OK; return B_OK;
} }
TRACE("DataStream::Enlarge(): indirect2 current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks);
if (fNumBlocks <= kMaxDoubleIndirect) { if (fNumBlocks <= kMaxDoubleIndirect) {
status = _AddForDoubleIndirectBlock(transaction, targetBlocks); status = _AddForDoubleIndirectBlock(transaction, targetBlocks);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::Enlarge(): _AddForDoubleIndirectBlock() failed\n");
return status; return status;
}
TRACE("DataStream::Enlarge(): current size: %lu, target size: %lu\n", TRACE("DataStream::Enlarge(): current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks); fNumBlocks, targetBlocks);
if (fNumBlocks == targetBlocks) if (fNumBlocks == targetBlocks)
return B_OK; return B_OK;
} }
TRACE("DataStream::Enlarge(): indirect3 current size: %llu, target size: %llu\n",
fNumBlocks, targetBlocks);
TRACE("DataStream::Enlarge(): allocated: %lu, waiting: %lu\n", fAllocated, TRACE("DataStream::Enlarge(): allocated: %lu, waiting: %lu\n", fAllocated,
fWaiting); fWaiting);
@@ -109,25 +125,27 @@ DataStream::Enlarge(Transaction& transaction, uint32& numBlocks)
status_t status_t
DataStream::Shrink(Transaction& transaction, uint32& numBlocks) DataStream::Shrink(Transaction& transaction, off_t& numBlocks)
{ {
TRACE("DataStream::Shrink(): current size: %lu, target size: %lu\n", TRACE("DataStream::Shrink(): current size: %llu, target size: %llu\n",
fNumBlocks, numBlocks); fNumBlocks, numBlocks);
fFreeStart = 0; fFreeStart = 0;
fFreeCount = 0; fFreeCount = 0;
fRemovedBlocks = 0; fRemovedBlocks = 0;
uint32 oldNumBlocks = fNumBlocks; off_t oldNumBlocks = fNumBlocks;
uint32 blocksToRemove = fNumBlocks - numBlocks; off_t blocksToRemove = fNumBlocks - numBlocks;
status_t status; status_t status;
if (numBlocks < kMaxDirect) { if (numBlocks < kMaxDirect) {
status = _RemoveFromDirectBlocks(transaction, numBlocks); status = _RemoveFromDirectBlocks(transaction, numBlocks);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::Shrink(): _RemoveFromDirectBlocks() failed\n");
return status; return status;
}
if (fRemovedBlocks == blocksToRemove) { if (fRemovedBlocks == blocksToRemove) {
fNumBlocks -= fRemovedBlocks; fNumBlocks -= fRemovedBlocks;
@@ -140,8 +158,10 @@ DataStream::Shrink(Transaction& transaction, uint32& numBlocks)
if (numBlocks < kMaxIndirect) { if (numBlocks < kMaxIndirect) {
status = _RemoveFromIndirectBlock(transaction, numBlocks); status = _RemoveFromIndirectBlock(transaction, numBlocks);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::Shrink(): _RemoveFromIndirectBlock() failed\n");
return status; return status;
}
if (fRemovedBlocks == blocksToRemove) { if (fRemovedBlocks == blocksToRemove) {
fNumBlocks -= fRemovedBlocks; fNumBlocks -= fRemovedBlocks;
@@ -154,8 +174,10 @@ DataStream::Shrink(Transaction& transaction, uint32& numBlocks)
if (numBlocks < kMaxDoubleIndirect) { if (numBlocks < kMaxDoubleIndirect) {
status = _RemoveFromDoubleIndirectBlock(transaction, numBlocks); status = _RemoveFromDoubleIndirectBlock(transaction, numBlocks);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::Shrink(): _RemoveFromDoubleIndirectBlock() failed\n");
return status; return status;
}
if (fRemovedBlocks == blocksToRemove) { if (fRemovedBlocks == blocksToRemove) {
fNumBlocks -= fRemovedBlocks; fNumBlocks -= fRemovedBlocks;
@@ -167,8 +189,10 @@ DataStream::Shrink(Transaction& transaction, uint32& numBlocks)
status = _RemoveFromTripleIndirectBlock(transaction, numBlocks); status = _RemoveFromTripleIndirectBlock(transaction, numBlocks);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::Shrink(): _RemoveFromTripleIndirectBlock() failed\n");
return status; return status;
}
fNumBlocks -= fRemovedBlocks; fNumBlocks -= fRemovedBlocks;
numBlocks = _BlocksNeeded(oldNumBlocks); numBlocks = _BlocksNeeded(oldNumBlocks);
@@ -178,10 +202,10 @@ DataStream::Shrink(Transaction& transaction, uint32& numBlocks)
uint32 uint32
DataStream::_BlocksNeeded(uint32 numBlocks) DataStream::_BlocksNeeded(off_t numBlocks)
{ {
TRACE("DataStream::BlocksNeeded(): num blocks %lu\n", numBlocks); TRACE("DataStream::BlocksNeeded(): num blocks %llu\n", numBlocks);
uint32 blocksNeeded = 0; off_t blocksNeeded = 0;
if (numBlocks > fNumBlocks) { if (numBlocks > fNumBlocks) {
blocksNeeded += numBlocks - fNumBlocks; blocksNeeded += numBlocks - fNumBlocks;
@@ -214,15 +238,15 @@ DataStream::_BlocksNeeded(uint32 numBlocks)
} }
} }
TRACE("DataStream::BlocksNeeded(): %lu\n", blocksNeeded); TRACE("DataStream::BlocksNeeded(): %llu\n", blocksNeeded);
return blocksNeeded; return blocksNeeded;
} }
status_t status_t
DataStream::_GetBlock(Transaction& transaction, uint32& block) DataStream::_GetBlock(Transaction& transaction, uint32& blockNum)
{ {
TRACE("DataStream::_GetBlock(): allocated: %lu, pos: %lu, waiting: %lu\n", TRACE("DataStream::_GetBlock(): allocated: %lu, pos: %llu, waiting: %lu\n",
fAllocated, fAllocatedPos, fWaiting); fAllocated, fAllocatedPos, fWaiting);
if (fAllocated == 0) { if (fAllocated == 0) {
@@ -232,18 +256,20 @@ DataStream::_GetBlock(Transaction& transaction, uint32& block)
status_t status = fVolume->AllocateBlocks(transaction, 1, fWaiting, status_t status = fVolume->AllocateBlocks(transaction, 1, fWaiting,
blockGroup, fAllocatedPos, fAllocated); blockGroup, fAllocatedPos, fAllocated);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::_GetBlock(): AllocateBlocks() failed()\n");
return status; return status;
}
fWaiting -= fAllocated; fWaiting -= fAllocated;
fAllocatedPos += fVolume->BlocksPerGroup() * blockGroup + fFirstBlock; fAllocatedPos += fVolume->BlocksPerGroup() * blockGroup + fFirstBlock;
TRACE("DataStream::_GetBlock(): newAllocated: %lu, newpos: %lu," TRACE("DataStream::_GetBlock(): newAllocated: %lu, newpos: %llu,"
"newwaiting: %lu\n", fAllocated, fAllocatedPos, fWaiting); "newwaiting: %lu\n", fAllocated, fAllocatedPos, fWaiting);
} }
fAllocated--; fAllocated--;
block = fAllocatedPos++; blockNum = (uint32)fAllocatedPos++;
return B_OK; return B_OK;
} }
@@ -258,8 +284,10 @@ DataStream::_PrepareBlock(Transaction& transaction, uint32* pos,
if (blockNum == 0) { if (blockNum == 0) {
status_t status = _GetBlock(transaction, blockNum); status_t status = _GetBlock(transaction, blockNum);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::_PrepareBlock() _GetBlock() failed blockNum %ld\n", blockNum);
return status; return status;
}
*pos = B_HOST_TO_LENDIAN_INT32(blockNum); *pos = B_HOST_TO_LENDIAN_INT32(blockNum);
clear = true; clear = true;
@@ -270,10 +298,10 @@ DataStream::_PrepareBlock(Transaction& transaction, uint32* pos,
status_t status_t
DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 _count) DataStream::_AddBlocks(Transaction& transaction, uint32* block, off_t _count)
{ {
uint32 count = _count; off_t count = _count;
TRACE("DataStream::_AddBlocks(): count: %lu\n", count); TRACE("DataStream::_AddBlocks(): count: %llu\n", count);
while (count > 0) { while (count > 0) {
uint32 blockNum; uint32 blockNum;
@@ -292,10 +320,10 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 _count)
status_t status_t
DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start, DataStream::_AddBlocks(Transaction& transaction, uint32* block, off_t start,
uint32 end, int recursion) off_t end, int recursion)
{ {
TRACE("DataStream::_AddBlocks(): start: %lu, end %lu, recursion: %d\n", TRACE("DataStream::_AddBlocks(): start: %llu, end %llu, recursion: %d\n",
start, end, recursion); start, end, recursion);
bool clear; bool clear;
@@ -339,8 +367,10 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start,
if (start % elementWidth != 0) { if (start % elementWidth != 0) {
status = _AddBlocks(transaction, &childBlock[elementPos], status = _AddBlocks(transaction, &childBlock[elementPos],
start % elementWidth, elementWidth, recursion); start % elementWidth, elementWidth, recursion);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::_AddBlocks() _AddBlocks() start failed\n");
return status; return status;
}
elementPos++; elementPos++;
} }
@@ -348,8 +378,10 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start,
while (elementPos < endPos) { while (elementPos < endPos) {
status = _AddBlocks(transaction, &childBlock[elementPos], 0, status = _AddBlocks(transaction, &childBlock[elementPos], 0,
elementWidth, recursion); elementWidth, recursion);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::_AddBlocks() _AddBlocks() mid failed\n");
return status; return status;
}
elementPos++; elementPos++;
} }
@@ -357,8 +389,10 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start,
if (end % elementWidth != 0) { if (end % elementWidth != 0) {
status = _AddBlocks(transaction, &childBlock[elementPos], 0, status = _AddBlocks(transaction, &childBlock[elementPos], 0,
end % elementWidth, recursion); end % elementWidth, recursion);
if (status != B_OK) if (status != B_OK) {
ERROR("DataStream::_AddBlocks() _AddBlocks() end failed\n");
return status; return status;
}
} }
return B_OK; return B_OK;
@@ -368,7 +402,7 @@ DataStream::_AddBlocks(Transaction& transaction, uint32* block, uint32 start,
status_t status_t
DataStream::_AddForDirectBlocks(Transaction& transaction, uint32 numBlocks) DataStream::_AddForDirectBlocks(Transaction& transaction, uint32 numBlocks)
{ {
TRACE("DataStream::_AddForDirectBlocks(): current size: %lu, target size: " TRACE("DataStream::_AddForDirectBlocks(): current size: %llu, target size: "
"%lu\n", fNumBlocks, numBlocks); "%lu\n", fNumBlocks, numBlocks);
uint32* direct = &fStream->direct[fNumBlocks]; uint32* direct = &fStream->direct[fNumBlocks];
uint32 end = numBlocks > kMaxDirect ? kMaxDirect : numBlocks; uint32 end = numBlocks > kMaxDirect ? kMaxDirect : numBlocks;
@@ -380,7 +414,7 @@ DataStream::_AddForDirectBlocks(Transaction& transaction, uint32 numBlocks)
status_t status_t
DataStream::_AddForIndirectBlock(Transaction& transaction, uint32 numBlocks) DataStream::_AddForIndirectBlock(Transaction& transaction, uint32 numBlocks)
{ {
TRACE("DataStream::_AddForIndirectBlocks(): current size: %lu, target " TRACE("DataStream::_AddForIndirectBlocks(): current size: %llu, target "
"size: %lu\n", fNumBlocks, numBlocks); "size: %lu\n", fNumBlocks, numBlocks);
uint32 *indirect = &fStream->indirect; uint32 *indirect = &fStream->indirect;
uint32 start = fNumBlocks - kMaxDirect; uint32 start = fNumBlocks - kMaxDirect;
@@ -397,7 +431,7 @@ status_t
DataStream::_AddForDoubleIndirectBlock(Transaction& transaction, DataStream::_AddForDoubleIndirectBlock(Transaction& transaction,
uint32 numBlocks) uint32 numBlocks)
{ {
TRACE("DataStream::_AddForDoubleIndirectBlock(): current size: %lu, " TRACE("DataStream::_AddForDoubleIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks); "target size: %lu\n", fNumBlocks, numBlocks);
uint32 *doubleIndirect = &fStream->double_indirect; uint32 *doubleIndirect = &fStream->double_indirect;
uint32 start = fNumBlocks - kMaxIndirect; uint32 start = fNumBlocks - kMaxIndirect;
@@ -414,7 +448,7 @@ status_t
DataStream::_AddForTripleIndirectBlock(Transaction& transaction, DataStream::_AddForTripleIndirectBlock(Transaction& transaction,
uint32 numBlocks) uint32 numBlocks)
{ {
TRACE("DataStream::_AddForTripleIndirectBlock(): current size: %lu, " TRACE("DataStream::_AddForTripleIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks); "target size: %lu\n", fNumBlocks, numBlocks);
uint32 *tripleIndirect = &fStream->triple_indirect; uint32 *tripleIndirect = &fStream->triple_indirect;
uint32 start = fNumBlocks - kMaxDoubleIndirect; uint32 start = fNumBlocks - kMaxDoubleIndirect;
@@ -446,9 +480,11 @@ DataStream::_PerformFree(Transaction& transaction)
status_t status_t
DataStream::_MarkBlockForRemoval(Transaction& transaction, uint32* block) DataStream::_MarkBlockForRemoval(Transaction& transaction, uint32* block)
{ {
TRACE("DataStream::_MarkBlockForRemoval(*(%p) = %lu): free start: %lu, " TRACE("DataStream::_MarkBlockForRemoval(*(%p) = %lu): free start: %lu, "
"free count: %lu\n", block, *block, fFreeStart, fFreeCount); "free count: %lu\n", block, B_LENDIAN_TO_HOST_INT32(*block),
uint32 blockNum = B_LENDIAN_TO_HOST_INT32(*block); fFreeStart, fFreeCount);
uint32 blockNum = B_LENDIAN_TO_HOST_INT32(*block);
*block = 0; *block = 0;
if (blockNum != fFreeStart + fFreeCount) { if (blockNum != fFreeStart + fFreeCount) {
@@ -491,11 +527,11 @@ DataStream::_FreeBlocks(Transaction& transaction, uint32* block, uint32 _count)
status_t status_t
DataStream::_FreeBlocks(Transaction& transaction, uint32* block, uint32 start, DataStream::_FreeBlocks(Transaction& transaction, uint32* block, off_t start,
uint32 end, bool freeParent, int recursion) off_t end, bool freeParent, int recursion)
{ {
// TODO: Designed specifically for shrinking. Perhaps make it more general? // TODO: Designed specifically for shrinking. Perhaps make it more general?
TRACE("DataStream::_FreeBlocks(%p, %lu, %lu, %c, %d)\n", TRACE("DataStream::_FreeBlocks(%p, %llu, %llu, %c, %d)\n",
block, start, end, freeParent ? 't' : 'f', recursion); block, start, end, freeParent ? 't' : 'f', recursion);
uint32 blockNum = B_LENDIAN_TO_HOST_INT32(*block); uint32 blockNum = B_LENDIAN_TO_HOST_INT32(*block);
@@ -567,10 +603,10 @@ DataStream::_FreeBlocks(Transaction& transaction, uint32* block, uint32 start,
status_t status_t
DataStream::_RemoveFromDirectBlocks(Transaction& transaction, uint32 numBlocks) DataStream::_RemoveFromDirectBlocks(Transaction& transaction, uint32 numBlocks)
{ {
TRACE("DataStream::_RemoveFromDirectBlocks(): current size: %lu, " TRACE("DataStream::_RemoveFromDirectBlocks(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks); "target size: %lu\n", fNumBlocks, numBlocks);
uint32* direct = &fStream->direct[numBlocks]; uint32* direct = &fStream->direct[numBlocks];
uint32 end = fNumBlocks > kMaxDirect ? kMaxDirect : fNumBlocks; off_t end = fNumBlocks > kMaxDirect ? kMaxDirect : fNumBlocks;
return _FreeBlocks(transaction, direct, end - numBlocks); return _FreeBlocks(transaction, direct, end - numBlocks);
} }
@@ -579,11 +615,11 @@ DataStream::_RemoveFromDirectBlocks(Transaction& transaction, uint32 numBlocks)
status_t status_t
DataStream::_RemoveFromIndirectBlock(Transaction& transaction, uint32 numBlocks) DataStream::_RemoveFromIndirectBlock(Transaction& transaction, uint32 numBlocks)
{ {
TRACE("DataStream::_RemoveFromIndirectBlock(): current size: %lu, " TRACE("DataStream::_RemoveFromIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks); "target size: %lu\n", fNumBlocks, numBlocks);
uint32* indirect = &fStream->indirect; uint32* indirect = &fStream->indirect;
uint32 start = numBlocks <= kMaxDirect ? 0 : numBlocks - kMaxDirect; off_t start = numBlocks <= kMaxDirect ? 0 : numBlocks - kMaxDirect;
uint32 end = fNumBlocks - kMaxDirect; off_t end = fNumBlocks - kMaxDirect;
if (end > kIndirectsPerBlock) if (end > kIndirectsPerBlock)
end = kIndirectsPerBlock; end = kIndirectsPerBlock;
@@ -598,11 +634,11 @@ status_t
DataStream::_RemoveFromDoubleIndirectBlock(Transaction& transaction, DataStream::_RemoveFromDoubleIndirectBlock(Transaction& transaction,
uint32 numBlocks) uint32 numBlocks)
{ {
TRACE("DataStream::_RemoveFromDoubleIndirectBlock(): current size: %lu, " TRACE("DataStream::_RemoveFromDoubleIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks); "target size: %lu\n", fNumBlocks, numBlocks);
uint32* doubleIndirect = &fStream->double_indirect; uint32* doubleIndirect = &fStream->double_indirect;
uint32 start = numBlocks <= kMaxIndirect ? 0 : numBlocks - kMaxIndirect; off_t start = numBlocks <= kMaxIndirect ? 0 : numBlocks - kMaxIndirect;
uint32 end = fNumBlocks - kMaxIndirect; off_t end = fNumBlocks - kMaxIndirect;
if (end > kIndirectsPerBlock2) if (end > kIndirectsPerBlock2)
end = kIndirectsPerBlock2; end = kIndirectsPerBlock2;
@@ -617,12 +653,12 @@ status_t
DataStream::_RemoveFromTripleIndirectBlock(Transaction& transaction, DataStream::_RemoveFromTripleIndirectBlock(Transaction& transaction,
uint32 numBlocks) uint32 numBlocks)
{ {
TRACE("DataStream::_RemoveFromTripleIndirectBlock(): current size: %lu, " TRACE("DataStream::_RemoveFromTripleIndirectBlock(): current size: %llu, "
"target size: %lu\n", fNumBlocks, numBlocks); "target size: %lu\n", fNumBlocks, numBlocks);
uint32* tripleIndirect = &fStream->triple_indirect; uint32* tripleIndirect = &fStream->triple_indirect;
uint32 start = numBlocks <= kMaxDoubleIndirect ? 0 off_t start = numBlocks <= kMaxDoubleIndirect ? 0
: numBlocks - kMaxDoubleIndirect; : numBlocks - kMaxDoubleIndirect;
uint32 end = fNumBlocks - kMaxDoubleIndirect; off_t end = fNumBlocks - kMaxDoubleIndirect;
bool freeAll = start == 0; bool freeAll = start == 0;
@@ -22,20 +22,20 @@ public:
off_t size); off_t size);
~DataStream(); ~DataStream();
status_t Enlarge(Transaction& transaction, uint32& numBlocks); status_t Enlarge(Transaction& transaction, off_t& numBlocks);
status_t Shrink(Transaction& transaction, uint32& numBlocks); status_t Shrink(Transaction& transaction, off_t& numBlocks);
private: private:
uint32 _BlocksNeeded(uint32 end); uint32 _BlocksNeeded(off_t end);
status_t _GetBlock(Transaction& transaction, uint32& block); status_t _GetBlock(Transaction& transaction, uint32& block);
status_t _PrepareBlock(Transaction& transaction, uint32* pos, status_t _PrepareBlock(Transaction& transaction, uint32* pos,
uint32& blockNum, bool& clear); uint32& blockNum, bool& clear);
status_t _AddBlocks(Transaction& transaction, uint32* block, status_t _AddBlocks(Transaction& transaction, uint32* block,
uint32 count); off_t count);
status_t _AddBlocks(Transaction& transaction, uint32* block, status_t _AddBlocks(Transaction& transaction, uint32* block,
uint32 start, uint32 end, int recursion); off_t start, off_t end, int recursion);
status_t _AddForDirectBlocks(Transaction& transaction, status_t _AddForDirectBlocks(Transaction& transaction,
uint32 numBlocks); uint32 numBlocks);
@@ -53,7 +53,7 @@ private:
status_t _FreeBlocks(Transaction& transaction, uint32* block, status_t _FreeBlocks(Transaction& transaction, uint32* block,
uint32 count); uint32 count);
status_t _FreeBlocks(Transaction& transaction, uint32* block, status_t _FreeBlocks(Transaction& transaction, uint32* block,
uint32 start, uint32 end, bool freeParent, off_t start, off_t end, bool freeParent,
int recursion); int recursion);
status_t _RemoveFromDirectBlocks(Transaction& transaction, status_t _RemoveFromDirectBlocks(Transaction& transaction,
@@ -80,13 +80,13 @@ private:
uint32 fFirstBlock; uint32 fFirstBlock;
uint32 fAllocated; uint32 fAllocated;
uint32 fAllocatedPos; off_t fAllocatedPos;
uint32 fWaiting; uint32 fWaiting;
uint32 fFreeStart; uint32 fFreeStart;
uint32 fFreeCount; uint32 fFreeCount;
uint32 fNumBlocks; off_t fNumBlocks;
uint32 fRemovedBlocks; uint32 fRemovedBlocks;
}; };
+37 -40
View File
@@ -17,12 +17,16 @@
#include "Utility.h" #include "Utility.h"
#undef ASSERT
//#define TRACE_EXT2 //#define TRACE_EXT2
#ifdef TRACE_EXT2 #ifdef TRACE_EXT2
# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x) # define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
# define ASSERT(x) { if (!(x)) kernel_debugger("ext2: assert failed: " #x "\n"); }
#else #else
# define TRACE(x...) ; # define TRACE(x...) ;
# define ASSERT(x) ;
#endif #endif
#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x)
Inode::Inode(Volume* volume, ino_t id) Inode::Inode(Volume* volume, ino_t id)
@@ -32,8 +36,7 @@ Inode::Inode(Volume* volume, ino_t id)
fCache(NULL), fCache(NULL),
fMap(NULL), fMap(NULL),
fCached(false), fCached(false),
fHasExtraAttributes(false), fHasExtraAttributes(false)
fAttributesBlock(NULL)
{ {
rw_lock_init(&fLock, "ext2 inode"); rw_lock_init(&fLock, "ext2 inode");
recursive_lock_init(&fSmallDataLock, "ext2 inode small data"); recursive_lock_init(&fSmallDataLock, "ext2 inode small data");
@@ -68,7 +71,6 @@ Inode::Inode(Volume* volume)
fCache(NULL), fCache(NULL),
fMap(NULL), fMap(NULL),
fCached(false), fCached(false),
fAttributesBlock(NULL),
fInitStatus(B_NO_INIT) fInitStatus(B_NO_INIT)
{ {
rw_lock_init(&fLock, "ext2 inode"); rw_lock_init(&fLock, "ext2 inode");
@@ -91,12 +93,6 @@ Inode::~Inode()
file_map_delete(Map()); file_map_delete(Map());
} }
if (fAttributesBlock) {
TRACE("Returning the attributes block\n");
uint32 block = B_LENDIAN_TO_HOST_INT32(Node().file_access_control);
block_cache_put(fVolume->BlockCache(), block);
}
TRACE("Inode destructor: Done\n"); TRACE("Inode destructor: Done\n");
} }
@@ -123,9 +119,9 @@ Inode::WriteLockInTransaction(Transaction& transaction)
status_t status_t
Inode::WriteBack(Transaction& transaction) Inode::WriteBack(Transaction& transaction)
{ {
uint32 inodeBlock; off_t blockNum;
status_t status = fVolume->GetInodeBlock(fID, inodeBlock); status_t status = fVolume->GetInodeBlock(fID, blockNum);
if (status != B_OK) if (status != B_OK)
return status; return status;
@@ -136,19 +132,19 @@ Inode::WriteBack(Transaction& transaction)
} }
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
uint8* inodeBlockData = cached.SetToWritable(transaction, inodeBlock); uint8* inodeBlockData = cached.SetToWritable(transaction, blockNum);
if (inodeBlockData == NULL) if (inodeBlockData == NULL)
return B_IO_ERROR; return B_IO_ERROR;
TRACE("Inode::WriteBack(): Inode ID: %d, inode block: %lu, data: %p, " TRACE("Inode::WriteBack(): Inode ID: %lld, inode block: %llu, data: %p, "
"index: %lu, inode size: %lu, node size: %lu, this: %p, node: %p\n", "index: %lu, inode size: %lu, node size: %lu, this: %p, node: %p\n",
(int)fID, inodeBlock, inodeBlockData, fVolume->InodeBlockIndex(fID), fID, blockNum, inodeBlockData, fVolume->InodeBlockIndex(fID),
fVolume->InodeSize(), fNodeSize, this, &fNode); fVolume->InodeSize(), fNodeSize, this, &fNode);
memcpy(inodeBlockData + memcpy(inodeBlockData +
fVolume->InodeBlockIndex(fID) * fVolume->InodeSize(), fVolume->InodeBlockIndex(fID) * fVolume->InodeSize(),
(uint8*)&fNode, fNodeSize); (uint8*)&fNode, fNodeSize);
TRACE("Inode::WriteBack() finished\n"); TRACE("Inode::WriteBack() finished %ld\n", Node().stream.direct[0]);
return B_OK; return B_OK;
} }
@@ -157,16 +153,16 @@ Inode::WriteBack(Transaction& transaction)
status_t status_t
Inode::UpdateNodeFromDisk() Inode::UpdateNodeFromDisk()
{ {
uint32 block; off_t blockNum;
status_t status = fVolume->GetInodeBlock(fID, block); status_t status = fVolume->GetInodeBlock(fID, blockNum);
if (status != B_OK) if (status != B_OK)
return status; return status;
TRACE("inode %Ld at block %lu\n", fID, block); TRACE("inode %lld at block %llu\n", fID, blockNum);
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
const uint8* inodeBlock = cached.SetTo(block); const uint8* inodeBlock = cached.SetTo(blockNum);
if (inodeBlock == NULL) if (inodeBlock == NULL)
return B_IO_ERROR; return B_IO_ERROR;
@@ -238,6 +234,7 @@ Inode::FindBlock(off_t offset, uint32& block)
if (index < EXT2_DIRECT_BLOCKS) { if (index < EXT2_DIRECT_BLOCKS) {
// direct blocks // direct blocks
block = B_LENDIAN_TO_HOST_INT32(Node().stream.direct[index]); block = B_LENDIAN_TO_HOST_INT32(Node().stream.direct[index]);
ASSERT(block != 0);
} else if ((index -= EXT2_DIRECT_BLOCKS) < perBlock) { } else if ((index -= EXT2_DIRECT_BLOCKS) < perBlock) {
// indirect blocks // indirect blocks
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
@@ -247,6 +244,7 @@ Inode::FindBlock(off_t offset, uint32& block)
return B_IO_ERROR; return B_IO_ERROR;
block = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index]); block = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index]);
ASSERT(block != 0);
} else if ((index -= perBlock) < perIndirectBlock) { } else if ((index -= perBlock) < perIndirectBlock) {
// double indirect blocks // double indirect blocks
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
@@ -268,6 +266,7 @@ Inode::FindBlock(off_t offset, uint32& block)
block = B_LENDIAN_TO_HOST_INT32( block = B_LENDIAN_TO_HOST_INT32(
indirectBlocks[index & (perBlock - 1)]); indirectBlocks[index & (perBlock - 1)]);
} }
ASSERT(block != 0);
} else if ((index -= perIndirectBlock) / perBlock < perIndirectBlock) { } else if ((index -= perIndirectBlock) / perBlock < perIndirectBlock) {
// triple indirect blocks // triple indirect blocks
CachedBlock cached(fVolume); CachedBlock cached(fVolume);
@@ -300,13 +299,14 @@ Inode::FindBlock(off_t offset, uint32& block)
indirectBlocks[index & (perBlock - 1)]); indirectBlocks[index & (perBlock - 1)]);
} }
} }
ASSERT(block != 0);
} else { } else {
// Outside of the possible data stream // Outside of the possible data stream
dprintf("ext2: block outside datastream!\n"); dprintf("ext2: block outside datastream!\n");
return B_ERROR; return B_ERROR;
} }
TRACE("inode %Ld: FindBlock(offset %Ld): %lu\n", ID(), offset, block); TRACE("inode %Ld: FindBlock(offset %lld): %lu\n", ID(), offset, block);
return B_OK; return B_OK;
} }
@@ -318,13 +318,13 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length)
// set/check boundaries for pos/length // set/check boundaries for pos/length
if (pos < 0) { if (pos < 0) {
TRACE("inode %Ld: ReadAt failed(pos %Ld, length %lu)\n", ID(), pos, ERROR("inode %lld: ReadAt failed(pos %lld, length %lu)\n", ID(), pos,
length); length);
return B_BAD_VALUE; return B_BAD_VALUE;
} }
if (pos >= Size() || length == 0) { if (pos >= Size() || length == 0) {
TRACE("inode %Ld: ReadAt 0 (pos %Ld, length %lu)\n", ID(), pos, length); TRACE("inode %lld: ReadAt 0 (pos %lld, length %lu)\n", ID(), pos, length);
*_length = 0; *_length = 0;
return B_NO_ERROR; return B_NO_ERROR;
} }
@@ -337,8 +337,8 @@ status_t
Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer, Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
size_t* _length) size_t* _length)
{ {
TRACE("Inode::WriteAt(%lld, %p, *(%p) = %ld)\n", (long long)pos, buffer, TRACE("Inode::WriteAt(%lld, %p, *(%p) = %ld)\n", pos, buffer,
_length, (long)*_length); _length, *_length);
ReadLocker readLocker(fLock); ReadLocker readLocker(fLock);
if (IsFileCacheDisabled()) if (IsFileCacheDisabled())
@@ -398,8 +398,8 @@ Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
return B_OK; return B_OK;
} }
TRACE("Inode::WriteAt(): Performing write: %p, %d, %p, %d\n", TRACE("Inode::WriteAt(): Performing write: %p, %ld, %p, %ld\n",
FileCache(), (int)pos, buffer, (int)*_length); FileCache(), pos, buffer, *_length);
status_t status = file_cache_write(FileCache(), NULL, pos, buffer, _length); status_t status = file_cache_write(FileCache(), NULL, pos, buffer, _length);
WriteLockInTransaction(transaction); WriteLockInTransaction(transaction);
@@ -413,7 +413,7 @@ Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
status_t status_t
Inode::FillGapWithZeros(off_t start, off_t end) Inode::FillGapWithZeros(off_t start, off_t end)
{ {
TRACE("Inode::FileGapWithZeros(%ld - %ld)\n", (long)start, (long)end); TRACE("Inode::FileGapWithZeros(%lld - %lld)\n", start, end);
while (start < end) { while (start < end) {
size_t size; size_t size;
@@ -424,8 +424,7 @@ Inode::FillGapWithZeros(off_t start, off_t end)
size = end - start; size = end - start;
TRACE("Inode::FillGapWithZeros(): Calling file_cache_write(%p, NULL, " TRACE("Inode::FillGapWithZeros(): Calling file_cache_write(%p, NULL, "
"%ld, NULL, &(%ld) = %p)\n", fCache, (long)start, (long)size, "%lld, NULL, &(%lld) = %p)\n", fCache, start, size, &size);
&size);
status_t status = file_cache_write(fCache, NULL, start, NULL, status_t status = file_cache_write(fCache, NULL, start, NULL,
&size); &size);
if (status != B_OK) if (status != B_OK)
@@ -441,7 +440,7 @@ Inode::FillGapWithZeros(off_t start, off_t end)
status_t status_t
Inode::Resize(Transaction& transaction, off_t size) Inode::Resize(Transaction& transaction, off_t size)
{ {
TRACE("Inode::Resize(): size: %ld\n", (long)size); TRACE("Inode::Resize() ID:%lld size: %lld\n", ID(), size);
if (size < 0) if (size < 0)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -450,8 +449,7 @@ Inode::Resize(Transaction& transaction, off_t size)
if (size == oldSize) if (size == oldSize)
return B_OK; return B_OK;
TRACE("Inode::Resize(): old size: %ld, new size: %ld\n", (long)oldSize, TRACE("Inode::Resize(): old size: %lld, new size: %lld\n", oldSize, size);
(long)size);
status_t status; status_t status;
if (size > oldSize) { if (size > oldSize) {
@@ -471,8 +469,7 @@ Inode::Resize(Transaction& transaction, off_t size)
file_cache_set_size(FileCache(), size); file_cache_set_size(FileCache(), size);
file_map_set_size(Map(), size); file_map_set_size(Map(), size);
TRACE("Inode::Resize(): Writing back inode changes. Size: %ld\n", TRACE("Inode::Resize(): Writing back inode changes. Size: %lld\n", Size());
(long)Size());
return WriteBack(transaction); return WriteBack(transaction);
} }
@@ -779,8 +776,8 @@ Inode::EnableFileCache()
return B_OK; return B_OK;
} }
TRACE("Inode::EnableFileCache(): Creating the file cache: %d, %d, %d\n", TRACE("Inode::EnableFileCache(): Creating file cache: %ld, %ld, %lld\n",
(int)fVolume->ID(), (int)ID(), (int)Size()); fVolume->ID(), ID(), Size());
fCache = file_cache_create(fVolume->ID(), ID(), Size()); fCache = file_cache_create(fVolume->ID(), ID(), Size());
fMap = file_map_create(fVolume->ID(), ID(), Size()); fMap = file_map_create(fVolume->ID(), ID(), Size());
@@ -876,13 +873,13 @@ Inode::_EnlargeDataStream(Transaction& transaction, off_t size)
return B_OK; return B_OK;
} }
uint32 end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1; off_t end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1;
DataStream stream(fVolume, &fNode.stream, oldSize); DataStream stream(fVolume, &fNode.stream, oldSize);
stream.Enlarge(transaction, end); stream.Enlarge(transaction, end);
TRACE("Inode::_EnlargeDataStream(): Setting size to %Ld\n", size); TRACE("Inode::_EnlargeDataStream(): Setting size to %lld\n", size);
fNode.SetSize(size); fNode.SetSize(size);
TRACE("Inode::_EnlargeDataStream(): Setting allocated block count to %lu\n", TRACE("Inode::_EnlargeDataStream(): Setting allocated block count to %llu\n",
end); end);
return _SetNumBlocks(_NumBlocks() + end * (fVolume->BlockSize() / 512)); return _SetNumBlocks(_NumBlocks() + end * (fVolume->BlockSize() / 512));
} }
@@ -910,7 +907,7 @@ Inode::_ShrinkDataStream(Transaction& transaction, off_t size)
return B_OK; return B_OK;
} }
uint32 end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1; off_t end = size == 0 ? 0 : (size - 1) / fVolume->BlockSize() + 1;
DataStream stream(fVolume, &fNode.stream, oldSize); DataStream stream(fVolume, &fNode.stream, oldSize);
stream.Shrink(transaction, end); stream.Shrink(transaction, end);
@@ -145,7 +145,6 @@ private:
uint32 fNodeSize; uint32 fNodeSize;
// Inodes have a variable size, but the important // Inodes have a variable size, but the important
// information is always the same size (except in ext4) // information is always the same size (except in ext4)
ext2_xattr_header* fAttributesBlock;
status_t fInitStatus; status_t fInitStatus;
mutable recursive_lock fSmallDataLock; mutable recursive_lock fSmallDataLock;
@@ -68,15 +68,19 @@ InodeAllocator::Free(Transaction& transaction, ino_t id, bool isDirectory)
numInodes = fVolume->NumInodes() - blockGroup * numInodes; numInodes = fVolume->NumInodes() - blockGroup * numInodes;
TRACE("InodeAllocator::Free(): Updating block group data\n"); TRACE("InodeAllocator::Free(): Updating block group data\n");
group->SetFreeInodes(group->FreeInodes() + 1); group->SetFreeInodes(group->FreeInodes(fVolume->Has64bitFeature()) + 1,
fVolume->Has64bitFeature());
if (isDirectory) if (isDirectory)
group->SetUsedDirectories(group->UsedDirectories() - 1); group->SetUsedDirectories(
group->UsedDirectories(fVolume->Has64bitFeature()) - 1,
fVolume->Has64bitFeature());
status = fVolume->WriteBlockGroup(transaction, blockGroup); status = fVolume->WriteBlockGroup(transaction, blockGroup);
if (status != B_OK) if (status != B_OK)
return status; return status;
return _UnmarkInBitmap(transaction, group->InodeBitmap(), numInodes, id); return _UnmarkInBitmap(transaction,
group->InodeBitmap(fVolume->Has64bitFeature()), numInodes, id);
} }
@@ -97,17 +101,20 @@ InodeAllocator::_Allocate(Transaction& transaction, uint32 preferredBlockGroup,
if (status != B_OK) if (status != B_OK)
return status; return status;
uint32 freeInodes = group->FreeInodes(); uint32 freeInodes = group->FreeInodes(fVolume->Has64bitFeature());
if (freeInodes != 0) { if (freeInodes != 0) {
group->SetFreeInodes(freeInodes - 1); group->SetFreeInodes(freeInodes - 1, fVolume->Has64bitFeature());
if (isDirectory) if (isDirectory)
group->SetUsedDirectories(group->UsedDirectories() + 1); group->SetUsedDirectories(group->UsedDirectories(
fVolume->Has64bitFeature()) + 1,
fVolume->Has64bitFeature());
status = fVolume->WriteBlockGroup(transaction, blockGroup); status = fVolume->WriteBlockGroup(transaction, blockGroup);
if (status != B_OK) if (status != B_OK)
return status; return status;
return _MarkInBitmap(transaction, group->InodeBitmap(), return _MarkInBitmap(transaction,
group->InodeBitmap(fVolume->Has64bitFeature()),
blockGroup, fVolume->InodesPerGroup(), id); blockGroup, fVolume->InodesPerGroup(), id);
} }
} }
@@ -119,11 +126,13 @@ InodeAllocator::_Allocate(Transaction& transaction, uint32 preferredBlockGroup,
if (status != B_OK) if (status != B_OK)
return status; return status;
uint32 freeInodes = group->FreeInodes(); uint32 freeInodes = group->FreeInodes(fVolume->Has64bitFeature());
if (group->FreeInodes() != 0) { if (freeInodes != 0) {
group->SetFreeInodes(freeInodes - 1); group->SetFreeInodes(freeInodes - 1,
fVolume->Has64bitFeature());
return _MarkInBitmap(transaction, group->InodeBitmap(), return _MarkInBitmap(transaction,
group->InodeBitmap(fVolume->Has64bitFeature()),
blockGroup, fVolume->NumInodes() blockGroup, fVolume->NumInodes()
- blockGroup * fVolume->InodesPerGroup(), id); - blockGroup * fVolume->InodesPerGroup(), id);
} }
+26 -22
View File
@@ -231,9 +231,8 @@ Volume::~Volume()
if (fGroupBlocks != NULL) { if (fGroupBlocks != NULL) {
uint32 blockCount = (fNumGroups + fGroupsPerBlock - 1) uint32 blockCount = (fNumGroups + fGroupsPerBlock - 1)
/ fGroupsPerBlock; / fGroupsPerBlock;
for (uint32 i = 0; i < blockCount; i++) { for (uint32 i = 0; i < blockCount; i++)
free(fGroupBlocks[i]); free(fGroupBlocks[i]);
}
free(fGroupBlocks); free(fGroupBlocks);
} }
@@ -303,16 +302,22 @@ Volume::Mount(const char* deviceName, uint32 flags)
fBlockSize = 1UL << fSuperBlock.BlockShift(); fBlockSize = 1UL << fSuperBlock.BlockShift();
fFirstDataBlock = fSuperBlock.FirstDataBlock(); fFirstDataBlock = fSuperBlock.FirstDataBlock();
fFreeBlocks = fSuperBlock.FreeBlocks(); fFreeBlocks = fSuperBlock.FreeBlocks(Has64bitFeature());
fFreeInodes = fSuperBlock.FreeInodes(); fFreeInodes = fSuperBlock.FreeInodes();
uint32 numBlocks = fSuperBlock.NumBlocks() - fFirstDataBlock; off_t numBlocks = fSuperBlock.NumBlocks(Has64bitFeature()) - fFirstDataBlock;
uint32 blocksPerGroup = fSuperBlock.BlocksPerGroup(); uint32 blocksPerGroup = fSuperBlock.BlocksPerGroup();
fNumGroups = numBlocks / blocksPerGroup; fNumGroups = numBlocks / blocksPerGroup;
if (numBlocks % blocksPerGroup != 0) if (numBlocks % blocksPerGroup != 0)
fNumGroups++; fNumGroups++;
fGroupsPerBlock = fBlockSize / sizeof(ext2_block_group); if (Has64bitFeature()) {
fGroupDescriptorSize = fSuperBlock.GroupDescriptorSize();
if (fGroupDescriptorSize < sizeof(ext2_block_group))
return B_ERROR;
} else
fGroupDescriptorSize = EXT2_BLOCK_GROUP_NORMAL_SIZE;
fGroupsPerBlock = fBlockSize / fGroupDescriptorSize;
fNumInodes = fSuperBlock.NumInodes(); fNumInodes = fSuperBlock.NumInodes();
TRACE("block size %ld, num groups %ld, groups per block %ld, first %lu\n", TRACE("block size %ld, num groups %ld, groups per block %ld, first %lu\n",
@@ -320,11 +325,11 @@ Volume::Mount(const char* deviceName, uint32 flags)
uint32 blockCount = (fNumGroups + fGroupsPerBlock - 1) / fGroupsPerBlock; uint32 blockCount = (fNumGroups + fGroupsPerBlock - 1) / fGroupsPerBlock;
fGroupBlocks = (ext2_block_group**)malloc(blockCount * sizeof(void*)); fGroupBlocks = (uint8**)malloc(blockCount * sizeof(uint8*));
if (fGroupBlocks == NULL) if (fGroupBlocks == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
memset(fGroupBlocks, 0, blockCount * sizeof(void*)); memset(fGroupBlocks, 0, blockCount * sizeof(uint8*));
fInodesPerBlock = fBlockSize / InodeSize(); fInodesPerBlock = fBlockSize / InodeSize();
// check if the device size is large enough to hold the file system // check if the device size is large enough to hold the file system
@@ -452,7 +457,7 @@ Volume::Unmount()
status_t status_t
Volume::GetInodeBlock(ino_t id, uint32& block) Volume::GetInodeBlock(ino_t id, off_t& block)
{ {
ext2_block_group* group; ext2_block_group* group;
status_t status = GetBlockGroup((id - 1) / fSuperBlock.InodesPerGroup(), status_t status = GetBlockGroup((id - 1) / fSuperBlock.InodesPerGroup(),
@@ -460,7 +465,7 @@ Volume::GetInodeBlock(ino_t id, uint32& block)
if (status != B_OK) if (status != B_OK)
return status; return status;
block = group->InodeTable() block = group->InodeTable(Has64bitFeature())
+ ((id - 1) % fSuperBlock.InodesPerGroup()) / fInodesPerBlock; + ((id - 1) % fSuperBlock.InodesPerGroup()) / fInodesPerBlock;
return B_OK; return B_OK;
} }
@@ -544,19 +549,18 @@ Volume::GetBlockGroup(int32 index, ext2_block_group** _group)
if (block == NULL) if (block == NULL)
return B_IO_ERROR; return B_IO_ERROR;
ext2_block_group* groupBlock = (ext2_block_group*)malloc(fBlockSize); fGroupBlocks[blockIndex] = (uint8*)malloc(fBlockSize);
if (groupBlock == NULL) if (fGroupBlocks[blockIndex] == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
memcpy((uint8*)groupBlock, block, fBlockSize); memcpy(fGroupBlocks[blockIndex], block, fBlockSize);
fGroupBlocks[blockIndex] = groupBlock;
TRACE("group [%ld]: inode table %ld\n", index, TRACE("group [%ld]: inode table %ld\n", index,
(fGroupBlocks[blockIndex] + index % fGroupsPerBlock)->InodeTable()); (fGroupBlocks[blockIndex] + index % fGroupsPerBlock)->InodeTable());
} }
*_group = fGroupBlocks[blockIndex] + index % fGroupsPerBlock; *_group = (ext2_block_group*)(fGroupBlocks[blockIndex]
+ (index % fGroupsPerBlock) * fGroupDescriptorSize);
return B_OK; return B_OK;
} }
@@ -625,7 +629,7 @@ Volume::RemoveOrphan(Transaction& transaction, ino_t id)
CachedBlock cached(this); CachedBlock cached(this);
uint32 blockNum; off_t blockNum;
status_t status = GetInodeBlock(currentID, blockNum); status_t status = GetInodeBlock(currentID, blockNum);
if (status != B_OK) if (status != B_OK)
return status; return status;
@@ -650,7 +654,7 @@ Volume::RemoveOrphan(Transaction& transaction, ino_t id)
return B_OK; return B_OK;
do { do {
uint32 lastBlockNum = blockNum; off_t lastBlockNum = blockNum;
status = GetInodeBlock(currentID, blockNum); status = GetInodeBlock(currentID, blockNum);
if (status != B_OK) if (status != B_OK)
return status; return status;
@@ -720,7 +724,7 @@ Volume::FreeInode(Transaction& transaction, ino_t id, bool isDirectory)
status_t status_t
Volume::AllocateBlocks(Transaction& transaction, uint32 minimum, uint32 maximum, Volume::AllocateBlocks(Transaction& transaction, uint32 minimum, uint32 maximum,
uint32& blockGroup, uint32& start, uint32& length) uint32& blockGroup, off_t& start, uint32& length)
{ {
TRACE("Volume::AllocateBlocks()\n"); TRACE("Volume::AllocateBlocks()\n");
if (IsReadOnly()) if (IsReadOnly())
@@ -742,9 +746,9 @@ Volume::AllocateBlocks(Transaction& transaction, uint32 minimum, uint32 maximum,
status_t status_t
Volume::FreeBlocks(Transaction& transaction, uint32 start, uint32 length) Volume::FreeBlocks(Transaction& transaction, off_t start, uint32 length)
{ {
TRACE("Volume::FreeBlocks(%lu, %lu)\n", start, length); TRACE("Volume::FreeBlocks(%llu, %lu)\n", start, length);
if (IsReadOnly()) if (IsReadOnly())
return B_READ_ONLY_DEVICE; return B_READ_ONLY_DEVICE;
@@ -776,7 +780,7 @@ Volume::LoadSuperBlock()
else else
memcpy(&fSuperBlock, block, sizeof(fSuperBlock)); memcpy(&fSuperBlock, block, sizeof(fSuperBlock));
fFreeBlocks = fSuperBlock.FreeBlocks(); fFreeBlocks = fSuperBlock.FreeBlocks(Has64bitFeature());
fFreeInodes = fSuperBlock.FreeInodes(); fFreeInodes = fSuperBlock.FreeInodes();
return B_OK; return B_OK;
@@ -787,7 +791,7 @@ status_t
Volume::WriteSuperBlock(Transaction& transaction) Volume::WriteSuperBlock(Transaction& transaction)
{ {
TRACE("Volume::WriteSuperBlock()\n"); TRACE("Volume::WriteSuperBlock()\n");
fSuperBlock.SetFreeBlocks(fFreeBlocks); fSuperBlock.SetFreeBlocks(fFreeBlocks, Has64bitFeature());
fSuperBlock.SetFreeInodes(fFreeInodes); fSuperBlock.SetFreeInodes(fFreeInodes);
// TODO: Rest of fields that can be modified // TODO: Rest of fields that can be modified
+13 -6
View File
@@ -49,7 +49,8 @@ public:
uint32 NumGroups() const uint32 NumGroups() const
{ return fNumGroups; } { return fNumGroups; }
off_t NumBlocks() const off_t NumBlocks() const
{ return fSuperBlock.NumBlocks(); } { return fSuperBlock.NumBlocks(
Has64bitFeature()); }
off_t NumFreeBlocks() const off_t NumFreeBlocks() const
{ return fFreeBlocks; } { return fFreeBlocks; }
uint32 FirstDataBlock() const uint32 FirstDataBlock() const
@@ -65,7 +66,7 @@ public:
{ return fSuperBlock.InodesPerGroup(); } { return fSuperBlock.InodesPerGroup(); }
ext2_super_block& SuperBlock() { return fSuperBlock; } ext2_super_block& SuperBlock() { return fSuperBlock; }
status_t GetInodeBlock(ino_t id, uint32& block); status_t GetInodeBlock(ino_t id, off_t& block);
uint32 InodeBlockIndex(ino_t id) const; uint32 InodeBlockIndex(ino_t id) const;
status_t GetBlockGroup(int32 index, status_t GetBlockGroup(int32 index,
ext2_block_group** _group); ext2_block_group** _group);
@@ -77,6 +78,9 @@ public:
bool IndexedDirectories() const bool IndexedDirectories() const
{ return (fSuperBlock.CompatibleFeatures() { return (fSuperBlock.CompatibleFeatures()
& EXT2_FEATURE_DIRECTORY_INDEX) != 0; } & EXT2_FEATURE_DIRECTORY_INDEX) != 0; }
bool Has64bitFeature() const
{ return (fSuperBlock.CompatibleFeatures()
& EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0; }
uint8 DefaultHashVersion() const uint8 DefaultHashVersion() const
{ return fSuperBlock.default_hash_version; } { return fSuperBlock.default_hash_version; }
bool HugeFiles() const bool HugeFiles() const
@@ -96,10 +100,10 @@ public:
status_t AllocateBlocks(Transaction& transaction, status_t AllocateBlocks(Transaction& transaction,
uint32 minimum, uint32 maximum, uint32 minimum, uint32 maximum,
uint32& blockGroup, uint32& start, uint32& blockGroup, off_t& start,
uint32& length); uint32& length);
status_t FreeBlocks(Transaction& transaction, status_t FreeBlocks(Transaction& transaction,
uint32 start, uint32 length); off_t start, uint32 length);
status_t LoadSuperBlock(); status_t LoadSuperBlock();
status_t WriteSuperBlock(Transaction& transaction); status_t WriteSuperBlock(Transaction& transaction);
@@ -122,6 +126,8 @@ private:
static uint32 _UnsupportedReadOnlyFeatures( static uint32 _UnsupportedReadOnlyFeatures(
ext2_super_block& superBlock); ext2_super_block& superBlock);
uint32 _GroupDescriptorBlock(uint32 blockIndex); uint32 _GroupDescriptorBlock(uint32 blockIndex);
uint16 _GroupDescriptorSize()
{ return fGroupDescriptorSize; }
private: private:
mutex fLock; mutex fLock;
@@ -142,11 +148,12 @@ private:
uint32 fNumInodes; uint32 fNumInodes;
uint32 fNumGroups; uint32 fNumGroups;
uint32 fFreeBlocks; off_t fFreeBlocks;
uint32 fFreeInodes; uint32 fFreeInodes;
uint32 fGroupsPerBlock; uint32 fGroupsPerBlock;
ext2_block_group** fGroupBlocks; uint8** fGroupBlocks;
uint32 fInodesPerBlock; uint32 fInodesPerBlock;
uint16 fGroupDescriptorSize;
void* fBlockCache; void* fBlockCache;
Inode* fRootNode; Inode* fRootNode;
+106 -27
View File
@@ -72,9 +72,9 @@ struct ext2_super_block {
uint32 journal_inode_backup[17]; uint32 journal_inode_backup[17];
// ext4 support // ext4 support
uint32 num_blocks_hi; uint32 num_blocks_high;
uint32 reserved_blocks_hi; uint32 reserved_blocks_high;
uint32 free_blocks_hi; uint32 free_blocks_high;
uint16 min_inode_size; uint16 min_inode_size;
uint16 want_inode_size; uint16 want_inode_size;
uint32 flags; uint32 flags;
@@ -92,9 +92,21 @@ struct ext2_super_block {
uint32 RevisionLevel() const { return B_LENDIAN_TO_HOST_INT16(revision_level); } uint32 RevisionLevel() const { return B_LENDIAN_TO_HOST_INT16(revision_level); }
uint32 BlockShift() const { return B_LENDIAN_TO_HOST_INT32(block_shift) + 10; } uint32 BlockShift() const { return B_LENDIAN_TO_HOST_INT32(block_shift) + 10; }
uint32 NumInodes() const { return B_LENDIAN_TO_HOST_INT32(num_inodes); } uint32 NumInodes() const { return B_LENDIAN_TO_HOST_INT32(num_inodes); }
uint32 NumBlocks() const { return B_LENDIAN_TO_HOST_INT32(num_blocks); } uint64 NumBlocks(bool has64bits) const
{
uint64 blocks = B_LENDIAN_TO_HOST_INT32(num_blocks);
if (has64bits)
blocks |= ((uint64)B_LENDIAN_TO_HOST_INT32(num_blocks_high) << 32);
return blocks;
}
uint32 FreeInodes() const { return B_LENDIAN_TO_HOST_INT32(free_inodes); } uint32 FreeInodes() const { return B_LENDIAN_TO_HOST_INT32(free_inodes); }
uint32 FreeBlocks() const { return B_LENDIAN_TO_HOST_INT32(free_blocks); } uint64 FreeBlocks(bool has64bits) const
{
uint64 blocks = B_LENDIAN_TO_HOST_INT32(free_blocks);
if (has64bits)
blocks |= ((uint64)B_LENDIAN_TO_HOST_INT32(free_blocks_high) << 32);
return blocks;
}
uint16 InodeSize() const { return B_LENDIAN_TO_HOST_INT16(inode_size); } uint16 InodeSize() const { return B_LENDIAN_TO_HOST_INT16(inode_size); }
uint32 FirstDataBlock() const uint32 FirstDataBlock() const
{ return B_LENDIAN_TO_HOST_INT32(first_data_block); } { return B_LENDIAN_TO_HOST_INT32(first_data_block); }
@@ -121,8 +133,12 @@ struct ext2_super_block {
void SetFreeInodes(uint32 freeInodes) void SetFreeInodes(uint32 freeInodes)
{ free_inodes = B_HOST_TO_LENDIAN_INT32(freeInodes); } { free_inodes = B_HOST_TO_LENDIAN_INT32(freeInodes); }
void SetFreeBlocks(uint32 freeBlocks) void SetFreeBlocks(uint64 freeBlocks, bool has64bits)
{ free_blocks = B_HOST_TO_LENDIAN_INT32(freeBlocks); } {
free_blocks = B_HOST_TO_LENDIAN_INT32(freeBlocks & 0xffffffff);
if (has64bits)
free_blocks_high = B_HOST_TO_LENDIAN_INT32(freeBlocks >> 32);
}
void SetLastOrphan(ino_t id) void SetLastOrphan(ino_t id)
{ last_orphan = B_HOST_TO_LENDIAN_INT32((uint32)id); } { last_orphan = B_HOST_TO_LENDIAN_INT32((uint32)id); }
void SetReadOnlyFeatures(uint32 readOnlyFeatures) const void SetReadOnlyFeatures(uint32 readOnlyFeatures) const
@@ -173,6 +189,8 @@ struct ext2_super_block {
#define EXT2_STATE_VALID 0x01 #define EXT2_STATE_VALID 0x01
#define EXT2_STATE_INVALID 0x02 #define EXT2_STATE_INVALID 0x02
#define EXT2_BLOCK_GROUP_NORMAL_SIZE 32
struct ext2_block_group { struct ext2_block_group {
uint32 block_bitmap; uint32 block_bitmap;
uint32 inode_bitmap; uint32 inode_bitmap;
@@ -180,30 +198,91 @@ struct ext2_block_group {
uint16 free_blocks; uint16 free_blocks;
uint16 free_inodes; uint16 free_inodes;
uint16 used_directories; uint16 used_directories;
uint16 _padding; uint16 flags;
uint32 _reserved[3]; uint32 _reserved[2];
uint16 unused_inodes;
uint16 checksum;
// ext4
uint32 block_bitmap_high;
uint32 inode_bitmap_high;
uint32 inode_table_high;
uint16 free_blocks_high;
uint16 free_inodes_high;
uint16 used_directories_high;
uint16 unused_inodes_high;
uint32 _reserved2[3];
uint32 BlockBitmap() const uint64 BlockBitmap(bool has64bits) const
{ return B_LENDIAN_TO_HOST_INT32(block_bitmap); } {
uint32 InodeBitmap() const uint64 block = B_LENDIAN_TO_HOST_INT32(block_bitmap);
{ return B_LENDIAN_TO_HOST_INT32(inode_bitmap); } if (has64bits)
uint32 InodeTable() const block |=
{ return B_LENDIAN_TO_HOST_INT32(inode_table); } ((uint64)B_LENDIAN_TO_HOST_INT32(block_bitmap_high) << 32);
uint16 FreeBlocks() const return block;
{ return B_LENDIAN_TO_HOST_INT16(free_blocks); } }
uint16 FreeInodes() const uint64 InodeBitmap(bool has64bits) const
{ return B_LENDIAN_TO_HOST_INT16(free_inodes); } {
uint16 UsedDirectories() const uint64 bitmap = B_LENDIAN_TO_HOST_INT32(inode_bitmap);
{ return B_LENDIAN_TO_HOST_INT16(used_directories); } if (has64bits)
bitmap |=
((uint64)B_LENDIAN_TO_HOST_INT32(inode_bitmap_high) << 32);
return bitmap;
}
uint64 InodeTable(bool has64bits) const
{
uint64 table = B_LENDIAN_TO_HOST_INT32(inode_table);
if (has64bits)
table |= ((uint64)B_LENDIAN_TO_HOST_INT32(inode_table_high) << 32);
return table;
}
uint32 FreeBlocks(bool has64bits) const
{
uint32 blocks = B_LENDIAN_TO_HOST_INT16(free_blocks);
if (has64bits)
blocks |=
((uint32)B_LENDIAN_TO_HOST_INT16(free_blocks_high) << 16);
return blocks;
}
uint32 FreeInodes(bool has64bits) const
{
uint32 inodes = B_LENDIAN_TO_HOST_INT16(free_inodes);
if (has64bits)
inodes |=
((uint32)B_LENDIAN_TO_HOST_INT16(free_inodes_high) << 16);
return inodes;
}
uint32 UsedDirectories(bool has64bits) const
{
uint32 dirs = B_LENDIAN_TO_HOST_INT16(used_directories);
if (has64bits)
dirs |=
((uint32)B_LENDIAN_TO_HOST_INT16(used_directories_high) << 16);
return dirs;
}
void SetFreeBlocks(uint16 freeBlocks)
{ free_blocks = B_HOST_TO_LENDIAN_INT16(freeBlocks); }
void SetFreeInodes(uint16 freeInodes) void SetFreeBlocks(uint32 freeBlocks, bool has64bits)
{ free_inodes = B_HOST_TO_LENDIAN_INT16(freeInodes); } {
free_blocks = B_HOST_TO_LENDIAN_INT16(freeBlocks) & 0xffff;
if (has64bits)
free_blocks_high = B_HOST_TO_LENDIAN_INT16(freeBlocks >> 16);
}
void SetUsedDirectories(uint16 usedDirectories) void SetFreeInodes(uint32 freeInodes, bool has64bits)
{ used_directories = B_HOST_TO_LENDIAN_INT16(usedDirectories); } {
free_inodes = B_HOST_TO_LENDIAN_INT16(freeInodes) & 0xffff;
if (has64bits)
free_inodes_high = B_HOST_TO_LENDIAN_INT16(freeInodes >> 16);
}
void SetUsedDirectories(uint16 usedDirectories, bool has64bits)
{
used_directories = B_HOST_TO_LENDIAN_INT16(usedDirectories& 0xffff);
if (has64bits)
used_directories_high =
B_HOST_TO_LENDIAN_INT16(usedDirectories >> 16);
}
} _PACKED; } _PACKED;
#define EXT2_DIRECT_BLOCKS 12 #define EXT2_DIRECT_BLOCKS 12
@@ -91,8 +91,10 @@ ext2_scan_partition(int fd, partition_data *partition, void *_cookie)
partition->status = B_PARTITION_VALID; partition->status = B_PARTITION_VALID;
partition->flags |= B_PARTITION_FILE_SYSTEM; partition->flags |= B_PARTITION_FILE_SYSTEM;
partition->content_size = cookie->super_block.NumBlocks() partition->content_size = cookie->super_block.NumBlocks(
<< cookie->super_block.BlockShift(); (cookie->super_block.CompatibleFeatures()
& EXT2_INCOMPATIBLE_FEATURE_64BIT) != 0)
<< cookie->super_block.BlockShift();
partition->block_size = 1UL << cookie->super_block.BlockShift(); partition->block_size = 1UL << cookie->super_block.BlockShift();
partition->content_name = strdup(cookie->super_block.name); partition->content_name = strdup(cookie->super_block.name);
if (partition->content_name == NULL) if (partition->content_name == NULL)
@@ -491,19 +493,19 @@ ext2_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd,
uint32 blocksPerGroup = volume->BlocksPerGroup(); uint32 blocksPerGroup = volume->BlocksPerGroup();
uint32 blockSize = volume->BlockSize(); uint32 blockSize = volume->BlockSize();
uint32 firstBlock = volume->FirstDataBlock(); uint32 firstBlock = volume->FirstDataBlock();
uint32 start = 0; off_t start = 0;
uint32 group = 0; uint32 group = 0;
uint32 length; uint32 length;
TRACE("ioctl: blocks per group: %lu, block size: %lu, " TRACE("ioctl: blocks per group: %lu, block size: %lu, "
"first block: %lu, start: %lu, group: %lu\n", blocksPerGroup, "first block: %lu, start: %llu, group: %lu\n", blocksPerGroup,
blockSize, firstBlock, start, group); blockSize, firstBlock, start, group);
while (volume->AllocateBlocks(transaction, 1, 2048, group, start, while (volume->AllocateBlocks(transaction, 1, 2048, group, start,
length) == B_OK) { length) == B_OK) {
TRACE("ioctl: Allocated blocks in group %lu: %lu-%lu\n", group, TRACE("ioctl: Allocated blocks in group %lu: %llu-%llu\n", group,
start, start + length); start, start + length);
uint32 blockNum = start + group * blocksPerGroup - firstBlock; off_t blockNum = start + group * blocksPerGroup - firstBlock;
for (uint32 i = 0; i < length; ++i) { for (uint32 i = 0; i < length; ++i) {
uint8* block = cached.SetToWritable(transaction, blockNum); uint8* block = cached.SetToWritable(transaction, blockNum);