* 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
This commit is contained in:
@@ -422,6 +422,7 @@ BitmapBlock::FindNextMarked(uint32& pos)
|
|||||||
index++;
|
index++;
|
||||||
} while (index < maxIndex && data[index] == 0);
|
} while (index < maxIndex && data[index] == 0);
|
||||||
|
|
||||||
|
bits = B_LENDIAN_TO_HOST_INT32(data[index]);
|
||||||
if (index >= maxIndex) {
|
if (index >= maxIndex) {
|
||||||
maxBit = fNumBits & 0x1F;
|
maxBit = fNumBits & 0x1F;
|
||||||
|
|
||||||
@@ -432,10 +433,14 @@ BitmapBlock::FindNextMarked(uint32& pos)
|
|||||||
pos = fNumBits;
|
pos = fNumBits;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
mask = (1 << maxBit) - 1;
|
||||||
|
if ((bits & mask) == 0) {
|
||||||
|
pos = fNumBits;
|
||||||
|
return;
|
||||||
|
}
|
||||||
maxBit++;
|
maxBit++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bits = B_LENDIAN_TO_HOST_INT32(data[index]);
|
|
||||||
bit = 0;
|
bit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,7 +454,7 @@ BitmapBlock::FindNextMarked(uint32& pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
panic("Couldn't find marked bit inside an int32 which is different than "
|
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++;
|
index++;
|
||||||
} while (index < maxIndex && data[index] == 0xFFFFFFFF);
|
} while (index < maxIndex && data[index] == 0xFFFFFFFF);
|
||||||
|
|
||||||
|
bits = B_LENDIAN_TO_HOST_INT32(data[index]);
|
||||||
if (index >= maxIndex) {
|
if (index >= maxIndex) {
|
||||||
maxBit = fNumBits & 0x1F;
|
maxBit = fNumBits & 0x1F;
|
||||||
|
|
||||||
@@ -498,12 +504,17 @@ BitmapBlock::FindNextUnmarked(uint32& pos)
|
|||||||
pos = fNumBits;
|
pos = fNumBits;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
mask = (1 << maxBit) - 1;
|
||||||
|
if ((bits & mask) == mask) {
|
||||||
|
pos = fNumBits;
|
||||||
|
return;
|
||||||
|
}
|
||||||
maxBit++;
|
maxBit++;
|
||||||
}
|
}
|
||||||
bits = B_LENDIAN_TO_HOST_INT32(data[index]);
|
|
||||||
bit = 0;
|
bit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE("BitmapBlock::FindNextUnmarked(): searching bit at pos %lu\n", bit);
|
||||||
for (; bit < maxBit; ++bit) {
|
for (; bit < maxBit; ++bit) {
|
||||||
// Find the unmarked bit
|
// Find the unmarked bit
|
||||||
if ((bits >> bit & 1) == 0) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -93,8 +93,9 @@ ExtentStream::FindBlock(off_t offset, fsblock_t& block, uint32 *_count)
|
|||||||
}
|
}
|
||||||
if (stream->extent_entries[middle].LogicalBlock() > index)
|
if (stream->extent_entries[middle].LogicalBlock() > index)
|
||||||
middle--;
|
middle--;
|
||||||
if (stream->extent_entries[middle].LogicalBlock()
|
fileblock_t diff = index
|
||||||
+ stream->extent_entries[middle].Length() > index) {
|
- stream->extent_entries[middle].LogicalBlock();
|
||||||
|
if (diff > stream->extent_entries[middle].Length()) {
|
||||||
// sparse block
|
// sparse block
|
||||||
TRACE("FindBlock() sparse block index %lld at %ld\n", index,
|
TRACE("FindBlock() sparse block index %lld at %ld\n", index,
|
||||||
stream->extent_entries[middle].LogicalBlock());
|
stream->extent_entries[middle].LogicalBlock());
|
||||||
@@ -102,8 +103,6 @@ ExtentStream::FindBlock(off_t offset, fsblock_t& block, uint32 *_count)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileblock_t diff = index
|
|
||||||
- stream->extent_entries[middle].LogicalBlock();
|
|
||||||
block = stream->extent_entries[middle].PhysicalBlock() + diff;
|
block = stream->extent_entries[middle].PhysicalBlock() + diff;
|
||||||
if (_count)
|
if (_count)
|
||||||
*_count = stream->extent_entries[middle].Length() - diff;
|
*_count = stream->extent_entries[middle].Length() - diff;
|
||||||
|
|||||||
@@ -17,11 +17,14 @@
|
|||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
|
#undef ASSERT
|
||||||
//#define TRACE_EXT2
|
//#define TRACE_EXT2
|
||||||
#ifdef TRACE_EXT2
|
#ifdef TRACE_EXT2
|
||||||
# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
|
# define TRACE(x...) dprintf("\33[34mext2:\33[0m " x)
|
||||||
|
# define ASSERT(x) { if (!(x)) kernel_debugger("ext2: assert failed: " #x "\n"); }
|
||||||
#else
|
#else
|
||||||
# define TRACE(x...) ;
|
# define TRACE(x...) ;
|
||||||
|
# define ASSERT(x) ;
|
||||||
#endif
|
#endif
|
||||||
#define ERROR(x...) dprintf("\33[34mext2:\33[0m " x)
|
#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 (int i = 0; i < 2; ++i) {
|
||||||
for (; blockGroup < lastBlockGroup; ++blockGroup) {
|
for (; blockGroup < lastBlockGroup; ++blockGroup) {
|
||||||
ext2_block_group* group;
|
if (_AllocateInGroup(transaction, blockGroup,
|
||||||
|
isDirectory, id, fVolume->InodesPerGroup()) == B_OK)
|
||||||
status_t status = fVolume->GetBlockGroup(blockGroup, &group);
|
return B_OK;
|
||||||
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 (i == 0) {
|
if (i == 0 && _AllocateInGroup(transaction, blockGroup,
|
||||||
ext2_block_group* group;
|
isDirectory, id, fVolume->NumInodes() - blockGroup
|
||||||
|
* fVolume->InodesPerGroup()) == B_OK)
|
||||||
status_t status = fVolume->GetBlockGroup(blockGroup, &group);
|
return B_OK;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
blockGroup = 0;
|
blockGroup = 0;
|
||||||
lastBlockGroup = preferredBlockGroup;
|
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
|
status_t
|
||||||
InodeAllocator::_MarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock,
|
InodeAllocator::_MarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock,
|
||||||
uint32 blockGroup, uint32 numInodes, ino_t& id)
|
uint32 blockGroup, uint32 numInodes, uint32& pos)
|
||||||
{
|
{
|
||||||
BitmapBlock inodeBitmap(fVolume, numInodes);
|
BitmapBlock inodeBitmap(fVolume, numInodes);
|
||||||
|
|
||||||
@@ -184,7 +182,7 @@ InodeAllocator::_MarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock,
|
|||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 pos = 0;
|
pos = 0;
|
||||||
inodeBitmap.FindNextUnmarked(pos);
|
inodeBitmap.FindNextUnmarked(pos);
|
||||||
|
|
||||||
if (pos == inodeBitmap.NumBits()) {
|
if (pos == inodeBitmap.NumBits()) {
|
||||||
@@ -200,8 +198,6 @@ InodeAllocator::_MarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock,
|
|||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = pos + blockGroup * fVolume->InodesPerGroup() + 1;
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,13 +209,13 @@ InodeAllocator::_UnmarkInBitmap(Transaction& transaction, fsblock_t bitmapBlock,
|
|||||||
BitmapBlock inodeBitmap(fVolume, numInodes);
|
BitmapBlock inodeBitmap(fVolume, numInodes);
|
||||||
|
|
||||||
if (!inodeBitmap.SetToWritable(transaction, bitmapBlock)) {
|
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;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 pos = (id - 1) % fVolume->InodesPerGroup();
|
uint32 pos = (id - 1) % fVolume->InodesPerGroup();
|
||||||
if (!inodeBitmap.Unmark(pos, 1)) {
|
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);
|
bitmapBlock);
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,9 +32,12 @@ private:
|
|||||||
status_t _Allocate(Transaction& transaction,
|
status_t _Allocate(Transaction& transaction,
|
||||||
uint32 preferredBlockGroup, bool isDirectory,
|
uint32 preferredBlockGroup, bool isDirectory,
|
||||||
ino_t& id);
|
ino_t& id);
|
||||||
|
status_t _AllocateInGroup(Transaction& transaction,
|
||||||
|
uint32 blockGroup, bool isDirectory,
|
||||||
|
ino_t& id, uint32 numInodes);
|
||||||
status_t _MarkInBitmap(Transaction& transaction,
|
status_t _MarkInBitmap(Transaction& transaction,
|
||||||
fsblock_t bitmapBlock, uint32 blockGroup,
|
fsblock_t bitmapBlock, uint32 blockGroup,
|
||||||
uint32 numInodes, ino_t& id);
|
uint32 numInodes, uint32& pos);
|
||||||
status_t _UnmarkInBitmap(Transaction& transaction,
|
status_t _UnmarkInBitmap(Transaction& transaction,
|
||||||
fsblock_t bitmapBlock, uint32 numInodes, ino_t id);
|
fsblock_t bitmapBlock, uint32 numInodes, ino_t id);
|
||||||
status_t _InitGroup(Transaction& transaction,
|
status_t _InitGroup(Transaction& transaction,
|
||||||
|
|||||||
@@ -639,8 +639,10 @@ Volume::WriteBlockGroup(Transaction& transaction, int32 index)
|
|||||||
+ blockOffset * fGroupDescriptorSize);
|
+ blockOffset * fGroupDescriptorSize);
|
||||||
|
|
||||||
group->checksum = _GroupCheckSum(group, index);
|
group->checksum = _GroupCheckSum(group, index);
|
||||||
TRACE("Volume::WriteBlockGroup() checksum 0x%x for group %ld\n",
|
TRACE("Volume::WriteBlockGroup() checksum 0x%x for group %ld "
|
||||||
group->checksum, index);
|
"(free inodes %ld, unused %ld)\n", group->checksum, index,
|
||||||
|
group->FreeInodes(Has64bitFeature()),
|
||||||
|
group->UnusedInodes(Has64bitFeature()));
|
||||||
|
|
||||||
CachedBlock cached(this);
|
CachedBlock cached(this);
|
||||||
uint8* block = cached.SetToWritable(transaction,
|
uint8* block = cached.SetToWritable(transaction,
|
||||||
|
|||||||
@@ -273,6 +273,14 @@ struct ext2_block_group {
|
|||||||
return dirs;
|
return dirs;
|
||||||
}
|
}
|
||||||
uint16 Flags() const { return B_LENDIAN_TO_HOST_INT16(flags); }
|
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)
|
void SetFreeBlocks(uint32 freeBlocks, bool has64bits)
|
||||||
@@ -301,6 +309,13 @@ struct ext2_block_group {
|
|||||||
{
|
{
|
||||||
flags = B_HOST_TO_LENDIAN_INT16(newFlags);
|
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;
|
} _PACKED;
|
||||||
|
|
||||||
#define EXT2_DIRECT_BLOCKS 12
|
#define EXT2_DIRECT_BLOCKS 12
|
||||||
|
|||||||
Reference in New Issue
Block a user