From d8772e0c207a59d026580f29e2390d4030d1bec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sat, 30 Oct 2010 13:45:01 +0000 Subject: [PATCH] * 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 --- .../kernel/file_systems/ext2/Attribute.cpp | 8 +- .../kernel/file_systems/ext2/BitmapBlock.cpp | 73 ++++++--- .../file_systems/ext2/BlockAllocator.cpp | 77 ++++++--- .../kernel/file_systems/ext2/BlockAllocator.h | 6 +- .../kernel/file_systems/ext2/CachedBlock.h | 22 +-- .../kernel/file_systems/ext2/DataStream.cpp | 148 +++++++++++------- .../kernel/file_systems/ext2/DataStream.h | 16 +- .../kernel/file_systems/ext2/Inode.cpp | 77 +++++---- src/add-ons/kernel/file_systems/ext2/Inode.h | 1 - .../file_systems/ext2/InodeAllocator.cpp | 31 ++-- .../kernel/file_systems/ext2/Volume.cpp | 48 +++--- src/add-ons/kernel/file_systems/ext2/Volume.h | 19 ++- src/add-ons/kernel/file_systems/ext2/ext2.h | 133 ++++++++++++---- .../file_systems/ext2/kernel_interface.cpp | 14 +- 14 files changed, 434 insertions(+), 239 deletions(-) diff --git a/src/add-ons/kernel/file_systems/ext2/Attribute.cpp b/src/add-ons/kernel/file_systems/ext2/Attribute.cpp index 036d68954d..e707af3e8b 100644 --- a/src/add-ons/kernel/file_systems/ext2/Attribute.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Attribute.cpp @@ -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(); diff --git a/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp b/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp index 97b443d666..c00a9741e8 100644 --- a/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp +++ b/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp @@ -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"); } diff --git a/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp index 328f475804..34560abe30 100644 --- a/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/ext2/BlockAllocator.h b/src/add-ons/kernel/file_systems/ext2/BlockAllocator.h index d827623f17..e951bfcee3 100644 --- a/src/add-ons/kernel/file_systems/ext2/BlockAllocator.h +++ b/src/add-ons/kernel/file_systems/ext2/BlockAllocator.h @@ -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(); diff --git a/src/add-ons/kernel/file_systems/ext2/CachedBlock.h b/src/add-ons/kernel/file_systems/ext2/CachedBlock.h index 95430f4e9c..37efd9d308 100644 --- a/src/add-ons/kernel/file_systems/ext2/CachedBlock.h +++ b/src/add-ons/kernel/file_systems/ext2/CachedBlock.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/ext2/DataStream.cpp b/src/add-ons/kernel/file_systems/ext2/DataStream.cpp index c76ea70de1..04063c60cd 100644 --- a/src/add-ons/kernel/file_systems/ext2/DataStream.cpp +++ b/src/add-ons/kernel/file_systems/ext2/DataStream.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/ext2/DataStream.h b/src/add-ons/kernel/file_systems/ext2/DataStream.h index eee6a282f4..58ad825ea0 100644 --- a/src/add-ons/kernel/file_systems/ext2/DataStream.h +++ b/src/add-ons/kernel/file_systems/ext2/DataStream.h @@ -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; }; diff --git a/src/add-ons/kernel/file_systems/ext2/Inode.cpp b/src/add-ons/kernel/file_systems/ext2/Inode.cpp index 39bc6be5e3..867cfec970 100644 --- a/src/add-ons/kernel/file_systems/ext2/Inode.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Inode.cpp @@ -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); diff --git a/src/add-ons/kernel/file_systems/ext2/Inode.h b/src/add-ons/kernel/file_systems/ext2/Inode.h index f12ba64ff9..736ab9db03 100644 --- a/src/add-ons/kernel/file_systems/ext2/Inode.h +++ b/src/add-ons/kernel/file_systems/ext2/Inode.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp b/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp index 4fa5fb076e..695f400de8 100644 --- a/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp +++ b/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp @@ -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); } diff --git a/src/add-ons/kernel/file_systems/ext2/Volume.cpp b/src/add-ons/kernel/file_systems/ext2/Volume.cpp index 78949dbbed..e07e850d13 100644 --- a/src/add-ons/kernel/file_systems/ext2/Volume.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Volume.cpp @@ -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 diff --git a/src/add-ons/kernel/file_systems/ext2/Volume.h b/src/add-ons/kernel/file_systems/ext2/Volume.h index d9b4377c86..b9b62b13a4 100644 --- a/src/add-ons/kernel/file_systems/ext2/Volume.h +++ b/src/add-ons/kernel/file_systems/ext2/Volume.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/ext2/ext2.h b/src/add-ons/kernel/file_systems/ext2/ext2.h index 8159f07f2c..ecab1a638c 100644 --- a/src/add-ons/kernel/file_systems/ext2/ext2.h +++ b/src/add-ons/kernel/file_systems/ext2/ext2.h @@ -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 diff --git a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp index 61bf3c8f40..fe6d16655f 100644 --- a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp @@ -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);