mirror of
https://github.com/SerenityOS/serenity
synced 2026-05-09 00:22:43 +02:00
Kernel/Ext2FS: Refactor computing and flushing blocks
This is a large commit, since this is essentially a complete rewrite of the key low-level functions that handle reading/writing blocks. This is, however, a necessary prerequisite of being able to write holes. The previous version of `flush_block_list()` (along with its numerous helper functions) was entirely reliant on all blocks being sequential. In contrast to the previous implementation, the new version of `flush_block_list()` simply writes out the difference between the old block list and the new block list by calculating the correct indirect block(s) to update based on the relevant block's logical index. `compute_block_list()` has also been rewritten, since the estimated amount of meta blocks was incorrectly calculated for files with holes as a result of the estimated amount of blocks being a function of the file size. Since it isn't possible to accurately compute the shape of the block list without traversing it, we no longer try to perform such a computation, and instead simply search through all of the allocated indirect blocks. `compute_block_list_with_meta_blocks()` has also been removed in favor of the new `compute_meta_blocks()`, since meta blocks are fundamentally distinct from data blocks due to there being no mapping between any logical block index and the physical block index.
This commit is contained in:
committed by
Tim Schumacher
parent
176999e20c
commit
180f3f29ab
@@ -159,39 +159,6 @@ bool Ext2FS::find_block_containing_inode(InodeIndex inode, BlockIndex& block_ind
|
||||
return true;
|
||||
}
|
||||
|
||||
Ext2FS::BlockListShape Ext2FS::compute_block_list_shape(unsigned blocks) const
|
||||
{
|
||||
BlockListShape shape;
|
||||
unsigned const entries_per_block = EXT2_ADDR_PER_BLOCK(&super_block());
|
||||
unsigned blocks_remaining = blocks;
|
||||
|
||||
shape.direct_blocks = min((unsigned)EXT2_NDIR_BLOCKS, blocks_remaining);
|
||||
blocks_remaining -= shape.direct_blocks;
|
||||
if (!blocks_remaining)
|
||||
return shape;
|
||||
|
||||
shape.indirect_blocks = min(blocks_remaining, entries_per_block);
|
||||
shape.meta_blocks += 1;
|
||||
blocks_remaining -= shape.indirect_blocks;
|
||||
if (!blocks_remaining)
|
||||
return shape;
|
||||
|
||||
shape.doubly_indirect_blocks = min(blocks_remaining, entries_per_block * entries_per_block);
|
||||
shape.meta_blocks += 1;
|
||||
shape.meta_blocks += ceil_div(shape.doubly_indirect_blocks, entries_per_block);
|
||||
blocks_remaining -= shape.doubly_indirect_blocks;
|
||||
if (!blocks_remaining)
|
||||
return shape;
|
||||
|
||||
shape.triply_indirect_blocks = min(blocks_remaining, entries_per_block * entries_per_block * entries_per_block);
|
||||
shape.meta_blocks += 1;
|
||||
shape.meta_blocks += ceil_div(shape.triply_indirect_blocks, entries_per_block * entries_per_block);
|
||||
shape.meta_blocks += ceil_div(shape.triply_indirect_blocks, entries_per_block);
|
||||
blocks_remaining -= shape.triply_indirect_blocks;
|
||||
VERIFY(blocks_remaining == 0);
|
||||
return shape;
|
||||
}
|
||||
|
||||
u8 Ext2FS::internal_file_type_to_directory_entry_type(DirectoryEntryView const& entry) const
|
||||
{
|
||||
switch (entry.file_type) {
|
||||
@@ -618,11 +585,17 @@ ErrorOr<void> Ext2FS::free_inode(Ext2FSInode& inode)
|
||||
|
||||
// Mark all blocks used by this inode as free.
|
||||
{
|
||||
auto blocks = TRY(inode.compute_block_list_with_meta_blocks());
|
||||
auto blocks = TRY(inode.compute_block_list());
|
||||
for (auto const& [_, block_index] : blocks) {
|
||||
VERIFY(block_index <= super_block().s_blocks_count && block_index != 0);
|
||||
TRY(set_block_allocation_state(block_index, false));
|
||||
}
|
||||
|
||||
auto meta_blocks = TRY(inode.compute_meta_blocks());
|
||||
for (auto const& block : meta_blocks) {
|
||||
VERIFY(block <= super_block().s_blocks_count && block != 0);
|
||||
TRY(set_block_allocation_state(block, false));
|
||||
}
|
||||
}
|
||||
|
||||
// If the inode being freed is a directory, update block group directory counter.
|
||||
|
||||
Reference in New Issue
Block a user