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