From 79de91c19b619ef149482aee4ef30e7f301abd09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Fri, 7 Jan 2011 19:00:23 +0000 Subject: [PATCH] * manages blockgroups unused_inodes when the feature is available. * BitmapBlock::FindMarked/FindUnmarked() tried to find a free bit at the end of a full bitmap. This fixes #7069. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40143 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/file_systems/ext2/BitmapBlock.cpp | 20 ++- .../kernel/file_systems/ext2/ExtentStream.cpp | 7 +- .../file_systems/ext2/InodeAllocator.cpp | 126 +++++++++--------- .../kernel/file_systems/ext2/InodeAllocator.h | 5 +- .../kernel/file_systems/ext2/Volume.cpp | 6 +- src/add-ons/kernel/file_systems/ext2/ext2.h | 15 +++ 6 files changed, 103 insertions(+), 76 deletions(-) diff --git a/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp b/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp index 1db1251cde..0c3219e700 100644 --- a/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp +++ b/src/add-ons/kernel/file_systems/ext2/BitmapBlock.cpp @@ -422,6 +422,7 @@ BitmapBlock::FindNextMarked(uint32& pos) index++; } while (index < maxIndex && data[index] == 0); + bits = B_LENDIAN_TO_HOST_INT32(data[index]); if (index >= maxIndex) { maxBit = fNumBits & 0x1F; @@ -432,10 +433,14 @@ BitmapBlock::FindNextMarked(uint32& pos) pos = fNumBits; return; } + mask = (1 << maxBit) - 1; + if ((bits & mask) == 0) { + pos = fNumBits; + return; + } maxBit++; } - bits = B_LENDIAN_TO_HOST_INT32(data[index]); bit = 0; } @@ -449,7 +454,7 @@ BitmapBlock::FindNextMarked(uint32& pos) } panic("Couldn't find marked bit inside an int32 which is different than " - "zero!?\n"); + "zero!? (%lx)\n", bits); } @@ -488,6 +493,7 @@ BitmapBlock::FindNextUnmarked(uint32& pos) index++; } while (index < maxIndex && data[index] == 0xFFFFFFFF); + bits = B_LENDIAN_TO_HOST_INT32(data[index]); if (index >= maxIndex) { maxBit = fNumBits & 0x1F; @@ -498,12 +504,17 @@ BitmapBlock::FindNextUnmarked(uint32& pos) pos = fNumBits; return; } + mask = (1 << maxBit) - 1; + if ((bits & mask) == mask) { + pos = fNumBits; + return; + } maxBit++; } - bits = B_LENDIAN_TO_HOST_INT32(data[index]); bit = 0; } + TRACE("BitmapBlock::FindNextUnmarked(): searching bit at pos %lu\n", bit); for (; bit < maxBit; ++bit) { // Find the unmarked bit if ((bits >> bit & 1) == 0) { @@ -513,7 +524,8 @@ BitmapBlock::FindNextUnmarked(uint32& pos) } } - panic("Couldn't find unmarked bit inside an int32 with value zero!?\n"); + panic("Couldn't find unmarked bit inside an int32 with value zero!?" + " (0x%lx)\n", bits); } diff --git a/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp b/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp index 8727c16ff4..6b0ff308ba 100644 --- a/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp +++ b/src/add-ons/kernel/file_systems/ext2/ExtentStream.cpp @@ -93,8 +93,9 @@ ExtentStream::FindBlock(off_t offset, fsblock_t& block, uint32 *_count) } if (stream->extent_entries[middle].LogicalBlock() > index) middle--; - if (stream->extent_entries[middle].LogicalBlock() - + stream->extent_entries[middle].Length() > index) { + fileblock_t diff = index + - stream->extent_entries[middle].LogicalBlock(); + if (diff > stream->extent_entries[middle].Length()) { // sparse block TRACE("FindBlock() sparse block index %lld at %ld\n", index, stream->extent_entries[middle].LogicalBlock()); @@ -102,8 +103,6 @@ ExtentStream::FindBlock(off_t offset, fsblock_t& block, uint32 *_count) return B_OK; } - fileblock_t diff = index - - stream->extent_entries[middle].LogicalBlock(); block = stream->extent_entries[middle].PhysicalBlock() + diff; if (_count) *_count = stream->extent_entries[middle].Length() - diff; diff --git a/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp b/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp index 6a13ff1d92..9ac91ee79a 100644 --- a/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp +++ b/src/add-ons/kernel/file_systems/ext2/InodeAllocator.cpp @@ -17,11 +17,14 @@ #include "Volume.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) @@ -101,67 +104,15 @@ InodeAllocator::_Allocate(Transaction& transaction, uint32 preferredBlockGroup, for (int i = 0; i < 2; ++i) { for (; blockGroup < lastBlockGroup; ++blockGroup) { - ext2_block_group* group; - - status_t status = fVolume->GetBlockGroup(blockGroup, &group); - if (status != B_OK) { - ERROR("InodeAllocator::_Allocate() GetBlockGroup() failed\n"); - return status; - } - - fsblock_t block = group->InodeBitmap(fVolume->Has64bitFeature()); - _InitGroup(transaction, group, block, fVolume->InodesPerGroup()); - 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( - fVolume->Has64bitFeature()) + 1, - fVolume->Has64bitFeature()); - - status = fVolume->WriteBlockGroup(transaction, blockGroup); - if (status != B_OK) - return status; - - return _MarkInBitmap(transaction, block, - blockGroup, fVolume->InodesPerGroup(), id); - } + if (_AllocateInGroup(transaction, blockGroup, + isDirectory, id, fVolume->InodesPerGroup()) == B_OK) + return B_OK; } - if (i == 0) { - ext2_block_group* group; - - status_t status = fVolume->GetBlockGroup(blockGroup, &group); - if (status != B_OK) { - ERROR("InodeAllocator::_Allocate() GetBlockGroup() failed\n"); - return status; - } - - uint32 numInodes = fVolume->NumInodes() - - blockGroup * fVolume->InodesPerGroup(); - fsblock_t block = group->InodeBitmap(fVolume->Has64bitFeature()); - _InitGroup(transaction, group, block, numInodes); - uint32 freeInodes = group->FreeInodes(fVolume->Has64bitFeature()); - if (freeInodes != 0) { - TRACE("InodeAllocator::_Allocate() freeInodes %ld\n", freeInodes); - group->SetFreeInodes(freeInodes - 1, - fVolume->Has64bitFeature()); - if (isDirectory) { - group->SetUsedDirectories(group->UsedDirectories( - fVolume->Has64bitFeature()) + 1, - fVolume->Has64bitFeature()); - } - - status = fVolume->WriteBlockGroup(transaction, blockGroup); - if (status != B_OK) - return status; - - return _MarkInBitmap(transaction, block, - blockGroup, numInodes, id); - } - } + if (i == 0 && _AllocateInGroup(transaction, blockGroup, + isDirectory, id, fVolume->NumInodes() - blockGroup + * fVolume->InodesPerGroup()) == B_OK) + return B_OK; blockGroup = 0; lastBlockGroup = preferredBlockGroup; @@ -172,9 +123,56 @@ InodeAllocator::_Allocate(Transaction& transaction, uint32 preferredBlockGroup, } +status_t +InodeAllocator::_AllocateInGroup(Transaction& transaction, uint32 blockGroup, + bool isDirectory, ino_t& id, uint32 numInodes) +{ + ext2_block_group* group; + status_t status = fVolume->GetBlockGroup(blockGroup, &group); + if (status != B_OK) { + ERROR("InodeAllocator::_Allocate() GetBlockGroup() failed\n"); + return status; + } + + fsblock_t block = group->InodeBitmap(fVolume->Has64bitFeature()); + _InitGroup(transaction, group, block, fVolume->InodesPerGroup()); + uint32 freeInodes = group->FreeInodes(fVolume->Has64bitFeature()); + if (freeInodes == 0) + return B_DEVICE_FULL; + TRACE("InodeAllocator::_Allocate() freeInodes %ld\n", + freeInodes); + group->SetFreeInodes(freeInodes - 1, fVolume->Has64bitFeature()); + if (isDirectory) { + group->SetUsedDirectories(group->UsedDirectories( + fVolume->Has64bitFeature()) + 1, + fVolume->Has64bitFeature()); + } + + uint32 pos = 0; + status = _MarkInBitmap(transaction, block, blockGroup, + fVolume->InodesPerGroup(), pos); + if (status != B_OK) + return status; + + if (fVolume->HasChecksumFeature() && pos > (fVolume->InodesPerGroup() - 1 + - group->UnusedInodes(fVolume->Has64bitFeature()))) { + group->SetUnusedInodes(fVolume->InodesPerGroup() - 1 - pos, + fVolume->Has64bitFeature()); + } + + status = fVolume->WriteBlockGroup(transaction, blockGroup); + if (status != B_OK) + return status; + + id = pos + blockGroup * fVolume->InodesPerGroup() + 1; + + return status; +} + + status_t InodeAllocator::_MarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock, - uint32 blockGroup, uint32 numInodes, ino_t& id) + uint32 blockGroup, uint32 numInodes, uint32& pos) { BitmapBlock inodeBitmap(fVolume, numInodes); @@ -184,7 +182,7 @@ InodeAllocator::_MarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock, return B_IO_ERROR; } - uint32 pos = 0; + pos = 0; inodeBitmap.FindNextUnmarked(pos); if (pos == inodeBitmap.NumBits()) { @@ -200,8 +198,6 @@ InodeAllocator::_MarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock, return B_BAD_DATA; } - id = pos + blockGroup * fVolume->InodesPerGroup() + 1; - return B_OK; } @@ -213,13 +209,13 @@ InodeAllocator::_UnmarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock, BitmapBlock inodeBitmap(fVolume, numInodes); if (!inodeBitmap.SetToWritable(transaction, bitmapBlock)) { - TRACE("Unable to open inode bitmap at block %llu\n", bitmapBlock); + ERROR("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 %llu\n", pos, + ERROR("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 e5816f16b5..75ae7adffc 100644 --- a/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h +++ b/src/add-ons/kernel/file_systems/ext2/InodeAllocator.h @@ -32,9 +32,12 @@ private: status_t _Allocate(Transaction& transaction, uint32 preferredBlockGroup, bool isDirectory, ino_t& id); + status_t _AllocateInGroup(Transaction& transaction, + uint32 blockGroup, bool isDirectory, + ino_t& id, uint32 numInodes); status_t _MarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock, uint32 blockGroup, - uint32 numInodes, ino_t& id); + uint32 numInodes, uint32& pos); status_t _UnmarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock, uint32 numInodes, ino_t id); status_t _InitGroup(Transaction& transaction, diff --git a/src/add-ons/kernel/file_systems/ext2/Volume.cpp b/src/add-ons/kernel/file_systems/ext2/Volume.cpp index 70a2ca41af..0c6010bd90 100644 --- a/src/add-ons/kernel/file_systems/ext2/Volume.cpp +++ b/src/add-ons/kernel/file_systems/ext2/Volume.cpp @@ -639,8 +639,10 @@ Volume::WriteBlockGroup(Transaction& transaction, int32 index) + blockOffset * fGroupDescriptorSize); group->checksum = _GroupCheckSum(group, index); - TRACE("Volume::WriteBlockGroup() checksum 0x%x for group %ld\n", - group->checksum, index); + TRACE("Volume::WriteBlockGroup() checksum 0x%x for group %ld " + "(free inodes %ld, unused %ld)\n", group->checksum, index, + group->FreeInodes(Has64bitFeature()), + group->UnusedInodes(Has64bitFeature())); CachedBlock cached(this); uint8* block = cached.SetToWritable(transaction, diff --git a/src/add-ons/kernel/file_systems/ext2/ext2.h b/src/add-ons/kernel/file_systems/ext2/ext2.h index c2058f4e61..43ffc92519 100644 --- a/src/add-ons/kernel/file_systems/ext2/ext2.h +++ b/src/add-ons/kernel/file_systems/ext2/ext2.h @@ -273,6 +273,14 @@ struct ext2_block_group { return dirs; } uint16 Flags() const { return B_LENDIAN_TO_HOST_INT16(flags); } + uint32 UnusedInodes(bool has64bits) const + { + uint32 inodes = B_LENDIAN_TO_HOST_INT16(unused_inodes); + if (has64bits) + inodes |= + ((uint32)B_LENDIAN_TO_HOST_INT16(unused_inodes_high) << 16); + return inodes; + } void SetFreeBlocks(uint32 freeBlocks, bool has64bits) @@ -301,6 +309,13 @@ struct ext2_block_group { { flags = B_HOST_TO_LENDIAN_INT16(newFlags); } + + void SetUnusedInodes(uint32 unusedInodes, bool has64bits) + { + unused_inodes = B_HOST_TO_LENDIAN_INT16(unusedInodes) & 0xffff; + if (has64bits) + unused_inodes_high = B_HOST_TO_LENDIAN_INT16(unusedInodes >> 16); + } } _PACKED; #define EXT2_DIRECT_BLOCKS 12