mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:28:10 +00:00
Ext2FS: Fix various bugs in inode and block allocation.
I had the wrong idea about how group indices work, so using a larger fs with more than one group caused all kinds of mess.
This commit is contained in:
parent
cbfd416279
commit
749db8237c
2 changed files with 40 additions and 24 deletions
|
@ -190,8 +190,8 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in
|
||||||
Vector<BlockIndex> new_meta_blocks;
|
Vector<BlockIndex> new_meta_blocks;
|
||||||
if (new_shape.meta_blocks > old_shape.meta_blocks) {
|
if (new_shape.meta_blocks > old_shape.meta_blocks) {
|
||||||
new_meta_blocks = allocate_blocks(group_index_from_inode(inode_index), new_shape.meta_blocks - old_shape.meta_blocks);
|
new_meta_blocks = allocate_blocks(group_index_from_inode(inode_index), new_shape.meta_blocks - old_shape.meta_blocks);
|
||||||
for (auto bi : new_meta_blocks)
|
for (auto block_index : new_meta_blocks)
|
||||||
set_block_allocation_state(group_index_from_inode(inode_index), bi, true);
|
set_block_allocation_state(block_index, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
e2inode.i_blocks = (blocks.size() + new_shape.meta_blocks) * (block_size() / 512);
|
e2inode.i_blocks = (blocks.size() + new_shape.meta_blocks) * (block_size() / 512);
|
||||||
|
@ -311,9 +311,8 @@ void Ext2FS::free_inode(Ext2FSInode& inode)
|
||||||
|
|
||||||
auto block_list = block_list_for_inode(inode.m_raw_inode, true);
|
auto block_list = block_list_for_inode(inode.m_raw_inode, true);
|
||||||
|
|
||||||
auto group_index = group_index_from_inode(inode.index());
|
|
||||||
for (auto block_index : block_list)
|
for (auto block_index : block_list)
|
||||||
set_block_allocation_state(group_index, block_index, false);
|
set_block_allocation_state(block_index, false);
|
||||||
|
|
||||||
set_inode_allocation_state(inode.index(), false);
|
set_inode_allocation_state(inode.index(), false);
|
||||||
|
|
||||||
|
@ -497,7 +496,7 @@ ssize_t Ext2FSInode::write_bytes(off_t offset, size_t count, const byte* data, F
|
||||||
if (blocks_needed_after > blocks_needed_before) {
|
if (blocks_needed_after > blocks_needed_before) {
|
||||||
auto new_blocks = fs().allocate_blocks(fs().group_index_from_inode(index()), blocks_needed_after - blocks_needed_before);
|
auto new_blocks = fs().allocate_blocks(fs().group_index_from_inode(index()), blocks_needed_after - blocks_needed_before);
|
||||||
for (auto new_block_index : new_blocks)
|
for (auto new_block_index : new_blocks)
|
||||||
fs().set_block_allocation_state(fs().group_index_from_inode(index()), new_block_index, true);
|
fs().set_block_allocation_state(new_block_index, true);
|
||||||
block_list.append(move(new_blocks));
|
block_list.append(move(new_blocks));
|
||||||
} else if (blocks_needed_after < blocks_needed_before) {
|
} else if (blocks_needed_after < blocks_needed_before) {
|
||||||
// FIXME: Implement block list shrinking!
|
// FIXME: Implement block list shrinking!
|
||||||
|
@ -787,36 +786,40 @@ void Ext2FS::dump_inode_bitmap(unsigned groupIndex) const
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void Ext2FS::traverse_inode_bitmap(unsigned groupIndex, F callback) const
|
void Ext2FS::traverse_inode_bitmap(unsigned group_index, F callback) const
|
||||||
{
|
{
|
||||||
ASSERT(groupIndex <= m_block_group_count);
|
ASSERT(group_index <= m_block_group_count);
|
||||||
auto& bgd = group_descriptor(groupIndex);
|
auto& bgd = group_descriptor(group_index);
|
||||||
|
|
||||||
unsigned inodes_in_group = min(inodes_per_group(), super_block().s_inodes_count);
|
unsigned inodes_in_group = min(inodes_per_group(), super_block().s_inodes_count);
|
||||||
unsigned block_count = ceil_div(inodes_in_group, 8u);
|
unsigned block_count = ceil_div(inodes_in_group, 8u);
|
||||||
|
unsigned first_inode_in_group = (group_index - 1) * inodes_per_group();
|
||||||
|
unsigned bits_per_block = block_size() * 8;
|
||||||
|
|
||||||
for (unsigned i = 0; i < block_count; ++i) {
|
for (unsigned i = 0; i < block_count; ++i) {
|
||||||
auto block = read_block(bgd.bg_inode_bitmap + i);
|
auto block = read_block(bgd.bg_inode_bitmap + i);
|
||||||
ASSERT(block);
|
ASSERT(block);
|
||||||
bool should_continue = callback(i * (block_size() / 8) + 1, Bitmap::wrap(block.pointer(), inodes_in_group));
|
bool should_continue = callback(first_inode_in_group + i * (i * bits_per_block) + 1, Bitmap::wrap(block.pointer(), inodes_in_group));
|
||||||
if (!should_continue)
|
if (!should_continue)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void Ext2FS::traverse_block_bitmap(unsigned groupIndex, F callback) const
|
void Ext2FS::traverse_block_bitmap(unsigned group_index, F callback) const
|
||||||
{
|
{
|
||||||
ASSERT(groupIndex <= m_block_group_count);
|
ASSERT(group_index <= m_block_group_count);
|
||||||
auto& bgd = group_descriptor(groupIndex);
|
auto& bgd = group_descriptor(group_index);
|
||||||
|
|
||||||
unsigned blocks_in_group = min(blocks_per_group(), super_block().s_blocks_count);
|
unsigned blocks_in_group = min(blocks_per_group(), super_block().s_blocks_count);
|
||||||
unsigned block_count = ceil_div(blocks_in_group, 8u);
|
unsigned block_count = ceil_div(blocks_in_group, 8u);
|
||||||
|
unsigned first_block_in_group = (group_index - 1) * blocks_per_group();
|
||||||
|
unsigned bits_per_block = block_size() * 8;
|
||||||
|
|
||||||
for (unsigned i = 0; i < block_count; ++i) {
|
for (unsigned i = 0; i < block_count; ++i) {
|
||||||
auto block = read_block(bgd.bg_block_bitmap + i);
|
auto block = read_block(bgd.bg_block_bitmap + i);
|
||||||
ASSERT(block);
|
ASSERT(block);
|
||||||
bool should_continue = callback(i * (block_size() / 8) + 1, Bitmap::wrap(block.pointer(), blocks_in_group));
|
bool should_continue = callback(first_block_in_group + (i * bits_per_block) + 1, Bitmap::wrap(block.pointer(), blocks_in_group));
|
||||||
if (!should_continue)
|
if (!should_continue)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -917,11 +920,20 @@ unsigned Ext2FS::allocate_inode(unsigned preferred_group, unsigned expected_size
|
||||||
unsigned inode = firstFreeInodeInGroup;
|
unsigned inode = firstFreeInodeInGroup;
|
||||||
dbgprintf("Ext2FS: found suitable inode %u\n", inode);
|
dbgprintf("Ext2FS: found suitable inode %u\n", inode);
|
||||||
|
|
||||||
|
ASSERT(get_inode_allocation_state(inode) == false);
|
||||||
|
|
||||||
// FIXME: allocate blocks if needed!
|
// FIXME: allocate blocks if needed!
|
||||||
|
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ext2FS::GroupIndex Ext2FS::group_index_from_block_index(BlockIndex block_index) const
|
||||||
|
{
|
||||||
|
if (!block_index)
|
||||||
|
return 0;
|
||||||
|
return (block_index - 1) / blocks_per_group() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned Ext2FS::group_index_from_inode(unsigned inode) const
|
unsigned Ext2FS::group_index_from_inode(unsigned inode) const
|
||||||
{
|
{
|
||||||
if (!inode)
|
if (!inode)
|
||||||
|
@ -987,22 +999,25 @@ bool Ext2FS::set_inode_allocation_state(unsigned index, bool newState)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ext2FS::set_block_allocation_state(GroupIndex group, BlockIndex bi, bool new_state)
|
bool Ext2FS::set_block_allocation_state(BlockIndex block_index, bool new_state)
|
||||||
{
|
{
|
||||||
dbgprintf("Ext2FS: set_block_allocation_state(group=%u, block=%u, state=%u)\n", group, bi, new_state);
|
dbgprintf("Ext2FS: set_block_allocation_state(block=%u, state=%u)\n", block_index, new_state);
|
||||||
auto& bgd = group_descriptor(group);
|
unsigned group_index = group_index_from_block_index(block_index);
|
||||||
|
auto& bgd = group_descriptor(group_index);
|
||||||
BlockIndex index_in_group = bi - ((group - 1) * blocks_per_group());
|
BlockIndex index_in_group = block_index - ((group_index - 1) * blocks_per_group());
|
||||||
|
|
||||||
// Update block bitmap
|
|
||||||
unsigned blocks_per_bitmap_block = block_size() * 8;
|
unsigned blocks_per_bitmap_block = block_size() * 8;
|
||||||
unsigned bitmap_block_index = (index_in_group - 1) / blocks_per_bitmap_block;
|
unsigned bitmap_block_index = (index_in_group - 1) / blocks_per_bitmap_block;
|
||||||
unsigned bit_index = (index_in_group - 1) % blocks_per_bitmap_block;
|
unsigned bit_index = (index_in_group - 1) % blocks_per_bitmap_block;
|
||||||
|
dbgprintf(" index_in_group: %u\n", index_in_group);
|
||||||
|
dbgprintf(" blocks_per_bitmap_block: %u\n", blocks_per_bitmap_block);
|
||||||
|
dbgprintf(" bitmap_block_index: %u\n", bitmap_block_index);
|
||||||
|
dbgprintf(" bit_index: %u\n", bit_index);
|
||||||
|
dbgprintf(" read_block(%u + %u = %u)\n", bgd.bg_block_bitmap, bitmap_block_index, bgd.bg_block_bitmap + bitmap_block_index);
|
||||||
auto block = read_block(bgd.bg_block_bitmap + bitmap_block_index);
|
auto block = read_block(bgd.bg_block_bitmap + bitmap_block_index);
|
||||||
ASSERT(block);
|
ASSERT(block);
|
||||||
auto bitmap = Bitmap::wrap(block.pointer(), blocks_per_bitmap_block);
|
auto bitmap = Bitmap::wrap(block.pointer(), blocks_per_bitmap_block);
|
||||||
bool current_state = bitmap.get(bit_index);
|
bool current_state = bitmap.get(bit_index);
|
||||||
dbgprintf("Ext2FS: block %u state: %u -> %u\n", bi, current_state, new_state);
|
dbgprintf("Ext2FS: block %u state: %u -> %u\n", block_index, current_state, new_state);
|
||||||
|
|
||||||
if (current_state == new_state)
|
if (current_state == new_state)
|
||||||
return true;
|
return true;
|
||||||
|
@ -1119,8 +1134,8 @@ RetainPtr<Inode> Ext2FS::create_inode(InodeIdentifier parent_id, const String& n
|
||||||
success = set_inode_allocation_state(inode_id, true);
|
success = set_inode_allocation_state(inode_id, true);
|
||||||
ASSERT(success);
|
ASSERT(success);
|
||||||
|
|
||||||
for (auto bi : blocks) {
|
for (auto block_index : blocks) {
|
||||||
success = set_block_allocation_state(group_index_from_inode(inode_id), bi, true);
|
success = set_block_allocation_state(block_index, true);
|
||||||
ASSERT(success);
|
ASSERT(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,7 @@ private:
|
||||||
unsigned allocate_inode(unsigned preferredGroup, unsigned expectedSize);
|
unsigned allocate_inode(unsigned preferredGroup, unsigned expectedSize);
|
||||||
Vector<BlockIndex> allocate_blocks(unsigned group, unsigned count);
|
Vector<BlockIndex> allocate_blocks(unsigned group, unsigned count);
|
||||||
unsigned group_index_from_inode(unsigned) const;
|
unsigned group_index_from_inode(unsigned) const;
|
||||||
|
GroupIndex group_index_from_block_index(BlockIndex) const;
|
||||||
|
|
||||||
Vector<unsigned> block_list_for_inode(const ext2_inode&, bool include_block_list_blocks = false) const;
|
Vector<unsigned> block_list_for_inode(const ext2_inode&, bool include_block_list_blocks = false) const;
|
||||||
bool write_block_list_for_inode(InodeIndex, ext2_inode&, const Vector<BlockIndex>&);
|
bool write_block_list_for_inode(InodeIndex, ext2_inode&, const Vector<BlockIndex>&);
|
||||||
|
@ -106,7 +107,7 @@ private:
|
||||||
bool write_directory_inode(unsigned directoryInode, Vector<DirectoryEntry>&&);
|
bool write_directory_inode(unsigned directoryInode, Vector<DirectoryEntry>&&);
|
||||||
bool get_inode_allocation_state(InodeIndex) const;
|
bool get_inode_allocation_state(InodeIndex) const;
|
||||||
bool set_inode_allocation_state(unsigned inode, bool);
|
bool set_inode_allocation_state(unsigned inode, bool);
|
||||||
bool set_block_allocation_state(GroupIndex, BlockIndex, bool);
|
bool set_block_allocation_state(BlockIndex, bool);
|
||||||
|
|
||||||
void uncache_inode(InodeIndex);
|
void uncache_inode(InodeIndex);
|
||||||
void free_inode(Ext2FSInode&);
|
void free_inode(Ext2FSInode&);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue