From 583f39e94d4065be3e621924661b98d231f29b10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 31 Oct 2010 17:16:02 +0000 Subject: [PATCH] * switched more uint32 to off_t for 64bit support * added error messages in InodeAllocator, Inode * if BlockAllocator can't initialize, don't fail completely but switch to readonly * fixed a bug in FindNextMarked() for bitmaps with a length non multiple of 32 * Inode::FindBlock() now returns an optional block_run length, useful for get_file_map() * added flag for Inode for extents git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39234 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/file_systems/ext2/BitmapBlock.cpp | 19 ++++--- .../file_systems/ext2/BlockAllocator.cpp | 2 +- .../file_systems/ext2/DirectoryIterator.cpp | 2 +- .../file_systems/ext2/DirectoryIterator.h | 2 +- .../kernel/file_systems/ext2/HTree.cpp | 4 +- .../file_systems/ext2/HTreeEntryIterator.cpp | 8 +-- .../file_systems/ext2/HTreeEntryIterator.h | 2 +- .../kernel/file_systems/ext2/Inode.cpp | 56 +++++++++++++++---- src/add-ons/kernel/file_systems/ext2/Inode.h | 3 +- .../file_systems/ext2/InodeAllocator.cpp | 29 ++++++---- .../kernel/file_systems/ext2/InodeAllocator.h | 4 +- .../kernel/file_systems/ext2/InodeJournal.cpp | 2 +- .../kernel/file_systems/ext2/InodeJournal.h | 2 +- .../kernel/file_systems/ext2/Journal.cpp | 52 ++++++++--------- .../kernel/file_systems/ext2/Journal.h | 2 +- .../kernel/file_systems/ext2/Volume.cpp | 8 ++- src/add-ons/kernel/file_systems/ext2/ext2.h | 1 + .../file_systems/ext2/kernel_interface.cpp | 23 ++++---- 18 files changed, 140 insertions(+), 81 deletions(-) diff --git a/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp b/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp index c00a9741e8..8336889654 100644 --- a/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp +++ b/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp @@ -463,6 +463,7 @@ BitmapBlock::FindNextUnmarked(uint32& pos) "bits: %lX\n", index, bit, mask, bits); bits &= ~mask; + uint32 maxBit = 32; if (bits == ~mask) { // Find an block of 32 bits that has a unmarked bit @@ -474,18 +475,22 @@ BitmapBlock::FindNextUnmarked(uint32& pos) } while (index < maxIndex && data[index] == 0xFFFFFFFF); if (index >= maxIndex) { - // Not found - TRACE("BitmapBlock::FindNextUnmarked(): reached end of block, num " - "bits: %lu\n", fNumBits); - pos = fNumBits; - return; - } + maxBit = fNumBits & 0x1F; + if (maxBit == 0) { + // Not found + TRACE("BitmapBlock::FindNextUnmarked(): reached end of block, " + "num bits: %lu\n", fNumBits); + pos = fNumBits; + return; + } + maxBit++; + } bits = B_LENDIAN_TO_HOST_INT32(data[index]); bit = 0; } - for (; bit < 32; ++bit) { + for (; bit < maxBit; ++bit) { // Find the unmarked bit if ((bits >> bit & 1) == 0) { pos = index << 5 | bit; diff --git a/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp index 34560abe30..d00840fa89 100644 --- a/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp @@ -131,7 +131,7 @@ AllocationBlockGroup::Initialize(Volume* volume, uint32 blockGroup, status = ScanFreeRanges(); if (fGroupDescriptor->FreeBlocks(fVolume->Has64bitFeature()) != fFreeBits) { - TRACE("AllocationBlockGroup::Initialize(): Mismatch between counted " + ERROR("AllocationBlockGroup::Initialize(): Mismatch between counted " "free blocks (%lu) and what is set on the group descriptor " "(%lu)\n", fFreeBits, fGroupDescriptor->FreeBlocks(fVolume->Has64bitFeature())); diff --git a/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp b/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp index 6ac4e200e7..0d6f6f7e3f 100644 --- a/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp +++ b/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp @@ -502,7 +502,7 @@ DirectoryIterator::_SplitIndexedBlock(Transaction& transaction, return B_NO_MEMORY; ArrayDeleter bufferDeleter(buffer); - uint32 firstPhysicalBlock = 0; + off_t firstPhysicalBlock = 0; // Prepare block to hold the first half of the entries and fill the buffer CachedBlock cachedFirst(fVolume); diff --git a/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h b/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h index b65cb05777..7652ceff9f 100644 --- a/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h +++ b/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h @@ -66,7 +66,7 @@ protected: uint32 fNumBlocks; uint32 fLogicalBlock; - uint32 fPhysicalBlock; + off_t fPhysicalBlock; uint32 fDisplacement; uint32 fPreviousDisplacement; diff --git a/src/add-ons/kernel/file_systems/ext2/HTree.cpp b/src/add-ons/kernel/file_systems/ext2/HTree.cpp index deb824451e..9399cdca2e 100644 --- a/src/add-ons/kernel/file_systems/ext2/HTree.cpp +++ b/src/add-ons/kernel/file_systems/ext2/HTree.cpp @@ -84,7 +84,7 @@ HTree::~HTree() status_t HTree::PrepareForHash() { - uint32 blockNum; + off_t blockNum; status_t status = fDirectory->FindBlock(0, blockNum); if (status != B_OK) return status; @@ -115,7 +115,7 @@ HTree::Lookup(const char* name, DirectoryIterator** iterator) return _FallbackToLinearIteration(iterator); } - uint32 blockNum; + off_t blockNum; status_t status = fDirectory->FindBlock(0, blockNum); if (status != B_OK) return _FallbackToLinearIteration(iterator); diff --git a/src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.cpp b/src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.cpp index d47a2b2c27..1693496511 100644 --- a/src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.cpp +++ b/src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.cpp @@ -41,7 +41,7 @@ HTreeEntryIterator::HTreeEntryIterator(off_t offset, Inode* directory) fCurrentEntry = fFirstEntry; } - TRACE("HTreeEntryIterator::HTreeEntryIterator(): created %p, block %lu, " + TRACE("HTreeEntryIterator::HTreeEntryIterator(): created %p, block %llu, " "entry no. %lu, parent: %p\n", this, fBlockNum, (uint32)fCurrentEntry, fParent); } @@ -100,7 +100,7 @@ HTreeEntryIterator::Init() if (fLimit != fBlockSize / sizeof(HTreeEntry) - fFirstEntry) { ERROR("HTreeEntryIterator::Init() bad fLimit %lu should be %lu " - "at block %lu\n", (uint32)fLimit, fBlockSize / sizeof(HTreeEntry) + "at block %llu\n", (uint32)fLimit, fBlockSize / sizeof(HTreeEntry) - fFirstEntry, fBlockNum); fCount = fLimit = 0; return B_ERROR; @@ -189,7 +189,7 @@ HTreeEntryIterator::Lookup(uint32 hash, int indirections, TRACE("HTreeEntryIterator::Lookup(): Creating a HTree entry iterator " "starting at block: %lu, hash: 0x%lX\n", start->Block(), start->Hash()); - uint32 blockNum; + off_t blockNum; status_t status = fDirectory->FindBlock(start->Block() * fBlockSize, blockNum); if (status != B_OK) @@ -322,7 +322,7 @@ HTreeEntryIterator::InsertEntry(Transaction& transaction, uint32 hash, panic("Splitting a HTree node required, but isn't yet fully " "supported\n"); - uint32 physicalBlock; + off_t physicalBlock; status_t status = fDirectory->FindBlock(newBlocksPos, physicalBlock); if (status != B_OK) return status; diff --git a/src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.h b/src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.h index f9f432a932..13508222a2 100644 --- a/src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.h +++ b/src/add-ons/kernel/file_systems/ext2/HTreeEntryIterator.h @@ -53,7 +53,7 @@ private: uint16 fCurrentEntry; uint32 fBlockSize; - uint32 fBlockNum; + off_t fBlockNum; HTreeEntryIterator* fParent; HTreeEntryIterator* fChild; diff --git a/src/add-ons/kernel/file_systems/ext2/Inode.cpp b/src/add-ons/kernel/file_systems/ext2/Inode.cpp index 867cfec970..be9994cbe1 100644 --- a/src/add-ons/kernel/file_systems/ext2/Inode.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Inode.cpp @@ -217,7 +217,7 @@ Inode::CheckPermissions(int accessMode) const status_t -Inode::FindBlock(off_t offset, uint32& block) +Inode::FindBlock(off_t offset, off_t& block, uint32 *_count) { uint32 perBlock = fVolume->BlockSize() / 4; uint32 perIndirectBlock = perBlock * perBlock; @@ -235,6 +235,13 @@ Inode::FindBlock(off_t offset, uint32& block) // direct blocks block = B_LENDIAN_TO_HOST_INT32(Node().stream.direct[index]); ASSERT(block != 0); + if (_count) { + *_count = 1; + uint32 nextBlock = block; + while (++index < EXT2_DIRECT_BLOCKS + && Node().stream.direct[index] == ++nextBlock) + (*_count)++; + } } else if ((index -= EXT2_DIRECT_BLOCKS) < perBlock) { // indirect blocks CachedBlock cached(fVolume); @@ -245,6 +252,13 @@ Inode::FindBlock(off_t offset, uint32& block) block = B_LENDIAN_TO_HOST_INT32(indirectBlocks[index]); ASSERT(block != 0); + if (_count) { + *_count = 1; + uint32 nextBlock = block; + while (++index < perBlock + && indirectBlocks[index] == ++nextBlock) + (*_count)++; + } } else if ((index -= perBlock) < perIndirectBlock) { // double indirect blocks CachedBlock cached(fVolume); @@ -265,6 +279,13 @@ Inode::FindBlock(off_t offset, uint32& block) block = B_LENDIAN_TO_HOST_INT32( indirectBlocks[index & (perBlock - 1)]); + if (_count) { + *_count = 1; + uint32 nextBlock = block; + while (((++index & (perBlock - 1)) != 0) + && indirectBlocks[index & (perBlock - 1)] == ++nextBlock) + (*_count)++; + } } ASSERT(block != 0); } else if ((index -= perIndirectBlock) / perBlock < perIndirectBlock) { @@ -297,6 +318,14 @@ Inode::FindBlock(off_t offset, uint32& block) block = B_LENDIAN_TO_HOST_INT32( indirectBlocks[index & (perBlock - 1)]); + if (_count) { + *_count = 1; + uint32 nextBlock = block; + while (((++index & (perBlock - 1)) != 0) + && indirectBlocks[index & (perBlock - 1)] + == ++nextBlock) + (*_count)++; + } } } ASSERT(block != 0); @@ -306,7 +335,8 @@ Inode::FindBlock(off_t offset, uint32& block) return B_ERROR; } - TRACE("inode %Ld: FindBlock(offset %lld): %lu\n", ID(), offset, block); + TRACE("inode %Ld: FindBlock(offset %lld): %lld %ld\n", ID(), offset, block, + _count != NULL ? *_count : 1); return B_OK; } @@ -398,7 +428,7 @@ Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer, return B_OK; } - TRACE("Inode::WriteAt(): Performing write: %p, %ld, %p, %ld\n", + TRACE("Inode::WriteAt(): Performing write: %p, %lld, %p, %ld\n", FileCache(), pos, buffer, *_length); status_t status = file_cache_write(FileCache(), NULL, pos, buffer, _length); @@ -424,7 +454,7 @@ Inode::FillGapWithZeros(off_t start, off_t end) size = end - start; TRACE("Inode::FillGapWithZeros(): Calling file_cache_write(%p, NULL, " - "%lld, NULL, &(%lld) = %p)\n", fCache, start, size, &size); + "%lld, NULL, &(%ld) = %p)\n", fCache, start, size, &size); status_t status = file_cache_write(fCache, NULL, start, NULL, &size); if (status != B_OK) @@ -485,7 +515,7 @@ Inode::InitDirectory(Transaction& transaction, Inode* parent) if (status != B_OK) return status; - uint32 blockNum; + off_t blockNum; status = FindBlock(0, blockNum); if (status != B_OK) return status; @@ -657,14 +687,18 @@ Inode::Create(Transaction& transaction, Inode* parent, const char* name, TRACE("Inode::Create(): Allocating inode\n"); ino_t id; status = volume->AllocateInode(transaction, parent, mode, id); - if (status != B_OK) + if (status != B_OK) { + ERROR("Inode::Create(): AllocateInode() failed\n"); return status; + } if (entries != NULL) { size_t nameLength = strlen(name); status = entries->AddEntry(transaction, name, nameLength, id, type); - if (status != B_OK) + if (status != B_OK) { + ERROR("Inode::Create(): AddEntry() failed\n"); return status; + } } TRACE("Inode::Create(): Creating inode\n"); @@ -696,8 +730,10 @@ Inode::Create(Transaction& transaction, Inode* parent, const char* name, if (inode->IsDirectory()) { TRACE("Inode::Create(): Initializing directory\n"); status = inode->InitDirectory(transaction, parent); - if (status != B_OK) + if (status != B_OK) { + ERROR("Inode::Create(): InitDirectory() failed\n"); return status; + } } // TODO: Maybe it can be better @@ -776,13 +812,13 @@ Inode::EnableFileCache() return B_OK; } - TRACE("Inode::EnableFileCache(): Creating file cache: %ld, %ld, %lld\n", + TRACE("Inode::EnableFileCache(): Creating file cache: %ld, %lld, %lld\n", fVolume->ID(), ID(), Size()); fCache = file_cache_create(fVolume->ID(), ID(), Size()); fMap = file_map_create(fVolume->ID(), ID(), Size()); if (fCache == NULL) { - TRACE("Inode::EnableFileCache(): Failed to create file cache\n"); + ERROR("Inode::EnableFileCache(): Failed to create file cache\n"); fCached = false; return B_ERROR; } diff --git a/src/add-ons/kernel/file_systems/ext2/Inode.h b/src/add-ons/kernel/file_systems/ext2/Inode.h index 736ab9db03..0655ef821c 100644 --- a/src/add-ons/kernel/file_systems/ext2/Inode.h +++ b/src/add-ons/kernel/file_systems/ext2/Inode.h @@ -79,7 +79,8 @@ public: //::Volume* _Volume() const { return fVolume; } Volume* GetVolume() const { return fVolume; } - status_t FindBlock(off_t offset, uint32& block); + status_t FindBlock(off_t offset, off_t& block, + uint32 *_count = NULL); status_t ReadAt(off_t pos, uint8 *buffer, size_t *length); status_t WriteAt(Transaction& transaction, off_t pos, const uint8* buffer, size_t* length); diff --git a/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp b/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp index 695f400de8..e0f5d5be5f 100644 --- a/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp +++ b/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp @@ -22,6 +22,7 @@ #else # define TRACE(x...) ; #endif +#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x) InodeAllocator::InodeAllocator(Volume* volume) @@ -98,11 +99,15 @@ InodeAllocator::_Allocate(Transaction& transaction, uint32 preferredBlockGroup, ext2_block_group* group; status_t status = fVolume->GetBlockGroup(blockGroup, &group); - if (status != B_OK) + if (status != B_OK) { + ERROR("InodeAllocator::_Allocate() GetBlockGroup() failed\n"); return status; + } uint32 freeInodes = group->FreeInodes(fVolume->Has64bitFeature()); if (freeInodes != 0) { + TRACE("InodeAllocator::_Allocate() freeInodes %ld bitmap %lld\n", + freeInodes, group->InodeBitmap(fVolume->Has64bitFeature())); group->SetFreeInodes(freeInodes - 1, fVolume->Has64bitFeature()); if (isDirectory) group->SetUsedDirectories(group->UsedDirectories( @@ -123,11 +128,14 @@ InodeAllocator::_Allocate(Transaction& transaction, uint32 preferredBlockGroup, ext2_block_group* group; status_t status = fVolume->GetBlockGroup(blockGroup, &group); - if (status != B_OK) + if (status != B_OK) { + ERROR("InodeAllocator::_Allocate() GetBlockGroup() failed\n"); return status; + } uint32 freeInodes = group->FreeInodes(fVolume->Has64bitFeature()); if (freeInodes != 0) { + TRACE("InodeAllocator::_Allocate() freeInodes %ld\n", freeInodes); group->SetFreeInodes(freeInodes - 1, fVolume->Has64bitFeature()); @@ -142,18 +150,19 @@ InodeAllocator::_Allocate(Transaction& transaction, uint32 preferredBlockGroup, lastBlockGroup = preferredBlockGroup; } + ERROR("InodeAllocator::_Allocate() device is full\n"); return B_DEVICE_FULL; } status_t -InodeAllocator::_MarkInBitmap(Transaction& transaction, uint32 bitmapBlock, +InodeAllocator::_MarkInBitmap(Transaction& transaction, off_t bitmapBlock, uint32 blockGroup, uint32 numInodes, ino_t& id) { BitmapBlock inodeBitmap(fVolume, numInodes); if (!inodeBitmap.SetToWritable(transaction, bitmapBlock)) { - TRACE("Unable to open inode bitmap (block number: %lu) for block group " + ERROR("Unable to open inode bitmap (block number: %llu) for block group " "%lu\n", bitmapBlock, blockGroup); return B_IO_ERROR; } @@ -162,14 +171,14 @@ InodeAllocator::_MarkInBitmap(Transaction& transaction, uint32 bitmapBlock, inodeBitmap.FindNextUnmarked(pos); if (pos == inodeBitmap.NumBits()) { - TRACE("Even though the block group %lu indicates there are free " + ERROR("Even though the block group %lu indicates there are free " "inodes, no unmarked bit was found in the inode bitmap at block " - "%lu.", blockGroup, bitmapBlock); + "%llu (numInodes %lu).\n", blockGroup, bitmapBlock, numInodes); return B_ERROR; } if (!inodeBitmap.Mark(pos, 1)) { - TRACE("Failed to mark bit %lu at bitmap block %lu\n", pos, + ERROR("Failed to mark bit %lu at bitmap block %llu\n", pos, bitmapBlock); return B_BAD_DATA; } @@ -181,19 +190,19 @@ InodeAllocator::_MarkInBitmap(Transaction& transaction, uint32 bitmapBlock, status_t -InodeAllocator::_UnmarkInBitmap(Transaction& transaction, uint32 bitmapBlock, +InodeAllocator::_UnmarkInBitmap(Transaction& transaction, off_t bitmapBlock, uint32 numInodes, ino_t id) { BitmapBlock inodeBitmap(fVolume, numInodes); if (!inodeBitmap.SetToWritable(transaction, bitmapBlock)) { - TRACE("Unable to open inode bitmap at block %lu\n", bitmapBlock); + TRACE("Unable to open inode bitmap at block %llu\n", bitmapBlock); return B_IO_ERROR; } uint32 pos = (id - 1) % fVolume->InodesPerGroup(); if (!inodeBitmap.Unmark(pos, 1)) { - TRACE("Unable to unmark bit %lu in inode bitmap block %lu\n", pos, + TRACE("Unable to unmark bit %lu in inode bitmap block %llu\n", pos, bitmapBlock); return B_BAD_DATA; } diff --git a/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h b/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h index 160cd69bd2..e50e6f6a25 100644 --- a/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h +++ b/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h @@ -32,10 +32,10 @@ private: uint32 prefferedBlockGroup, bool isDirectory, ino_t& id); status_t _MarkInBitmap(Transaction& transaction, - uint32 bitmapBlock, uint32 blockGroup, + off_t bitmapBlock, uint32 blockGroup, uint32 numInodes, ino_t& id); status_t _UnmarkInBitmap(Transaction& transaction, - uint32 bitmapBlock, uint32 numInodes, ino_t id); + off_t bitmapBlock, uint32 numInodes, ino_t id); Volume* fVolume; diff --git a/src/add-ons/kernel/file_systems/ext2/InodeJournal.cpp b/src/add-ons/kernel/file_systems/ext2/InodeJournal.cpp index 657d3d2d33..b919ee6c06 100644 --- a/src/add-ons/kernel/file_systems/ext2/InodeJournal.cpp +++ b/src/add-ons/kernel/file_systems/ext2/InodeJournal.cpp @@ -84,7 +84,7 @@ InodeJournal::InitCheck() status_t -InodeJournal::MapBlock(uint32 logical, uint32& physical) +InodeJournal::MapBlock(off_t logical, off_t& physical) { TRACE("InodeJournal::MapBlock()\n"); return fInode->FindBlock(logical * fBlockSize, physical); diff --git a/src/add-ons/kernel/file_systems/ext2/InodeJournal.h b/src/add-ons/kernel/file_systems/ext2/InodeJournal.h index a2abb05abb..2486f78ef3 100644 --- a/src/add-ons/kernel/file_systems/ext2/InodeJournal.h +++ b/src/add-ons/kernel/file_systems/ext2/InodeJournal.h @@ -20,7 +20,7 @@ public: status_t InitCheck(); - status_t MapBlock(uint32 logical, uint32& physical); + status_t MapBlock(off_t logical, off_t& physical); private: Inode* fInode; status_t fInitStatus; diff --git a/src/add-ons/kernel/file_systems/ext2/Journal.cpp b/src/add-ons/kernel/file_systems/ext2/Journal.cpp index b169b5a8d4..9f7f573b31 100644 --- a/src/add-ons/kernel/file_systems/ext2/Journal.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Journal.cpp @@ -26,6 +26,7 @@ #else # define TRACE(x...) ; #endif +#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x) class LogEntry : public DoublyLinkedListLinkImpl { @@ -296,7 +297,7 @@ Journal::Unlock(Transaction* owner, bool success) status_t -Journal::MapBlock(uint32 logical, uint32& physical) +Journal::MapBlock(off_t logical, off_t& physical) { TRACE("Journal::MapBlock()\n"); physical = logical; @@ -394,7 +395,7 @@ Journal::_WritePartialTransactionToLog(JournalHeader* descriptorBlock, logBlock = _WrapAroundLog(logBlock + 1); - uint32 physicalBlock; + off_t physicalBlock; status = MapBlock(logBlock, physicalBlock); if (status != B_OK) return status; @@ -402,7 +403,7 @@ Journal::_WritePartialTransactionToLog(JournalHeader* descriptorBlock, off_t logOffset = physicalBlock * fBlockSize; TRACE("Journal::_WritePartialTransactionToLog(): Writing from memory: " - "%p, to disk: %ld\n", finalData, (long)logOffset); + "%p, to disk: %llu\n", finalData, logOffset); size_t written = write_pos(fJournalVolume->Device(), logOffset, finalData, fBlockSize); if (written != fBlockSize) { @@ -426,15 +427,15 @@ Journal::_WritePartialTransactionToLog(JournalHeader* descriptorBlock, --tag; tag->SetLastTagFlag(); - uint32 physicalBlock; + off_t physicalBlock; status = MapBlock(descriptorBlockPos, physicalBlock); if (status != B_OK) return status; off_t descriptorBlockOffset = physicalBlock * fBlockSize; - TRACE("Journal::_WritePartialTransactionToLog(): Writing to: %ld\n", - (long)descriptorBlockOffset); + TRACE("Journal::_WritePartialTransactionToLog(): Writing to: %lld\n", + descriptorBlockOffset); size_t written = write_pos(fJournalVolume->Device(), descriptorBlockOffset, descriptorBlock, fBlockSize); if (written != fBlockSize) { @@ -569,7 +570,7 @@ Journal::_WriteTransactionToLog() // written. When it recovery reaches where the first commit should be // and doesn't find it, it considers it found the end of the log. - uint32 physicalBlock; + off_t physicalBlock; status = MapBlock(logBlock, physicalBlock); if (status != B_OK) return status; @@ -577,7 +578,7 @@ Journal::_WriteTransactionToLog() off_t logOffset = physicalBlock * fBlockSize; TRACE("Journal::_WriteTransactionToLog(): Writting commit block to " - "%ld\n", (long)logOffset); + "%lld\n", logOffset); off_t written = write_pos(fJournalVolume->Device(), logOffset, commitBlock, fBlockSize); if (written != fBlockSize) { @@ -592,15 +593,14 @@ Journal::_WriteTransactionToLog() } // Transaction will enter the Commit state - uint32 physicalBlock; + off_t physicalBlock; status = MapBlock(commitBlockPos, physicalBlock); if (status != B_OK) return status; off_t logOffset = physicalBlock * fBlockSize; - TRACE("Journal::_WriteTansactionToLog(): Writing to: %ld\n", - (long)logOffset); + TRACE("Journal::_WriteTransactionToLog(): Writing to: %lld\n", logOffset); off_t written = write_pos(fJournalVolume->Device(), logOffset, commitBlock, fBlockSize); if (written != fBlockSize) { @@ -634,8 +634,8 @@ Journal::_WriteTransactionToLog() if (status == B_OK && _FullTransactionSize() > fLogSize) { // If the transaction is too large after writing, there is no way to // recover, so let this transaction fail. - dprintf("transaction too large (%d blocks, log size %d)!\n", - (int)_FullTransactionSize(), (int)fLogSize); + ERROR("transaction too large (%ld blocks, log size %ld)!\n", + _FullTransactionSize(), fLogSize); return B_BUFFER_OVERFLOW; } } else { @@ -652,7 +652,7 @@ status_t Journal::_SaveSuperBlock() { TRACE("Journal::_SaveSuperBlock()\n"); - uint32 physicalBlock; + off_t physicalBlock; status_t status = MapBlock(0, physicalBlock); if (status != B_OK) return status; @@ -669,7 +669,7 @@ Journal::_SaveSuperBlock() superblock.SetFirstCommitID(fFirstCommitID); superblock.SetLogStart(fLogStart); - TRACE("Journal::SaveSuperBlock(): Write to %ld\n", (long)superblockPos); + TRACE("Journal::SaveSuperBlock(): Write to %lld\n", superblockPos); size_t bytesWritten = write_pos(fJournalVolume->Device(), superblockPos, &superblock, sizeof(superblock)); @@ -686,13 +686,13 @@ status_t Journal::_LoadSuperBlock() { TRACE("Journal::_LoadSuperBlock()\n"); - uint32 superblockPos; + off_t superblockPos; status_t status = MapBlock(0, superblockPos); if (status != B_OK) return status; - TRACE("Journal::_LoadSuperBlock(): super block physical block: %lu\n", + TRACE("Journal::_LoadSuperBlock(): super block physical block: %llu\n", superblockPos); JournalSuperBlock superblock; @@ -700,12 +700,12 @@ Journal::_LoadSuperBlock() * fJournalVolume->BlockSize(), &superblock, sizeof(superblock)); if (bytesRead != sizeof(superblock)) { - TRACE("Journal::_LoadSuperBlock(): failed to read superblock\n"); + ERROR("Journal::_LoadSuperBlock(): failed to read superblock\n"); return B_IO_ERROR; } if (!superblock.header.CheckMagic()) { - TRACE("Journal::_LoadSuperBlock(): Invalid superblock magic %lX\n", + ERROR("Journal::_LoadSuperBlock(): Invalid superblock magic %lX\n", superblock.header.Magic()); return B_BAD_VALUE; } @@ -717,7 +717,7 @@ Journal::_LoadSuperBlock() TRACE("Journal::_LoadSuperBlock(): Journal superblock version 2\n"); fVersion = 2; } else { - TRACE("Journal::_LoadSuperBlock(): Invalid superblock version\n"); + ERROR("Journal::_LoadSuperBlock(): Invalid superblock version\n"); return B_BAD_VALUE; } @@ -725,7 +725,7 @@ Journal::_LoadSuperBlock() status = _CheckFeatures(&superblock); if (status != B_OK) { - TRACE("Journal::_LoadSuperBlock(): Unsupported features\n"); + ERROR("Journal::_LoadSuperBlock(): Unsupported features\n"); return status; } } @@ -833,7 +833,7 @@ Journal::_RecoverPassScan(uint32& lastCommitID) JournalHeader* header; uint32 nextCommitID = fFirstCommitID; uint32 nextBlock = fLogStart; - uint32 nextBlockPos; + off_t nextBlockPos; status_t status = MapBlock(nextBlock, nextBlockPos); if (status != B_OK) @@ -889,7 +889,7 @@ Journal::_RecoverPassRevoke(uint32 lastCommitID) JournalHeader* header; uint32 nextCommitID = fFirstCommitID; uint32 nextBlock = fLogStart; - uint32 nextBlockPos; + off_t nextBlockPos; status_t status = MapBlock(nextBlock, nextBlockPos); if (status != B_OK) @@ -951,7 +951,7 @@ Journal::_RecoverPassReplay(uint32 lastCommitID) uint32 nextCommitID = fFirstCommitID; uint32 nextBlock = fLogStart; - uint32 nextBlockPos; + off_t nextBlockPos; status_t status = MapBlock(nextBlock, nextBlockPos); if (status != B_OK) @@ -973,8 +973,8 @@ Journal::_RecoverPassReplay(uint32 lastCommitID) while (nextCommitID < lastCommitID) { if (!header->CheckMagic() || header->Sequence() != nextCommitID) { - // Somehow the log is different than the expexted - TRACE("Journal::_RecoverPassReplay(): Wierd problem with block\n"); + // Somehow the log is different than the expected + ERROR("Journal::_RecoverPassReplay(): Weird problem with block\n"); return B_ERROR; } diff --git a/src/add-ons/kernel/file_systems/ext2/Journal.h b/src/add-ons/kernel/file_systems/ext2/Journal.h index f449095fcf..23ded822da 100644 --- a/src/add-ons/kernel/file_systems/ext2/Journal.h +++ b/src/add-ons/kernel/file_systems/ext2/Journal.h @@ -173,7 +173,7 @@ public: bool separateSubTransactions); virtual status_t Unlock(Transaction* owner, bool success); - virtual status_t MapBlock(uint32 logical, uint32& physical); + virtual status_t MapBlock(off_t logical, off_t& physical); inline uint32 FreeLogBlocks() const; status_t FlushLogAndBlocks(); diff --git a/src/add-ons/kernel/file_systems/ext2/Volume.cpp b/src/add-ons/kernel/file_systems/ext2/Volume.cpp index e07e850d13..a727f3cedf 100644 --- a/src/add-ons/kernel/file_systems/ext2/Volume.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Volume.cpp @@ -400,8 +400,12 @@ Volume::Mount(const char* deviceName, uint32 flags) TRACE("Volume::Mount(): Initialize block allocator\n"); status = fBlockAllocator.Initialize(); if (status != B_OK) { - FATAL("could not initialize block allocator!\n"); - return status; + FATAL("could not initialize block allocator, going read-only!\n"); + fFlags |= VOLUME_READ_ONLY; + fJournal->Uninit(); + delete fJournal; + delete fJournalInode; + fJournal = new(std::nothrow) NoJournal(this); } // ready diff --git a/src/add-ons/kernel/file_systems/ext2/ext2.h b/src/add-ons/kernel/file_systems/ext2/ext2.h index ecab1a638c..24887581df 100644 --- a/src/add-ons/kernel/file_systems/ext2/ext2.h +++ b/src/add-ons/kernel/file_systems/ext2/ext2.h @@ -547,6 +547,7 @@ struct ext2_inode { #define EXT2_INODE_BTREE 0x00001000 #define EXT2_INODE_INDEXED 0x00001000 #define EXT2_INODE_HUGE_FILE 0x00040000 +#define EXT2_INODE_EXTENTS 0x00080000 #define EXT2_NAME_LENGTH 255 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 fe6d16655f..e8fe552579 100644 --- a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp @@ -186,8 +186,8 @@ ext2_get_vnode(fs_volume* _volume, ino_t id, fs_vnode* _node, int* _type, Volume* volume = (Volume*)_volume->private_volume; if (id < 2 || id > volume->NumInodes()) { - dprintf("ext2: inode at %Ld requested!\n", id); - return B_ERROR; + dprintf("ext2: invalid inode id %lld requested!\n", id); + return B_BAD_VALUE; } Inode* inode = new Inode(volume, id); @@ -397,15 +397,17 @@ ext2_get_file_map(fs_volume* _volume, fs_vnode* _node, off_t offset, size_t index = 0, max = *_count; while (true) { - uint32 block; - status_t status = inode->FindBlock(offset, block); + off_t block; + uint32 count = 1; + status_t status = inode->FindBlock(offset, block, &count); if (status != B_OK) return status; - off_t blockOffset = (off_t)block << volume->BlockShift(); - uint32 blockLength = volume->BlockSize(); + off_t blockOffset = block << volume->BlockShift(); + uint32 blockLength = volume->BlockSize() * count; - if (index > 0 && (vecs[index - 1].offset == blockOffset - blockLength + if (index > 0 && (vecs[index - 1].offset + == blockOffset - vecs[index - 1].length || (vecs[index - 1].offset == -1 && block == 0))) { vecs[index - 1].length += blockLength; } else { @@ -426,11 +428,12 @@ ext2_get_file_map(fs_volume* _volume, fs_vnode* _node, off_t offset, } offset += blockLength; + size -= blockLength; if (size <= vecs[index - 1].length || offset >= inode->Size()) { // We're done! *_count = index; - TRACE("ext2_get_file_map for inode %ld\n", (long)inode->ID()); + TRACE("ext2_get_file_map for inode %lld\n", inode->ID()); return B_OK; } } @@ -750,7 +753,7 @@ ext2_create_symlink(fs_volume* _volume, fs_vnode* _directory, const char* name, ino_t id; status = Inode::Create(transaction, directory, name, S_SYMLINK | 0777, 0, (uint8)EXT2_TYPE_SYMLINK, NULL, &id, &link); - if (status < B_OK) + if (status != B_OK) return status; // TODO: We have to prepare the link before publishing? @@ -925,7 +928,7 @@ ext2_rename(fs_volume* _volume, fs_vnode* _oldDir, const char* oldName, if (status != B_OK) return B_IO_ERROR; - uint32 blockNum; + off_t blockNum; status = parent->FindBlock(0, blockNum); if (status != B_OK) return status;