mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 13:27:35 +00:00
Ext2FS: Factor out block list generation and writing into functions.
This commit is contained in:
parent
6fb4033709
commit
29dfb4ae13
3 changed files with 89 additions and 6 deletions
|
@ -43,7 +43,7 @@ public:
|
||||||
m_buffer[m_offset++] = value[i];
|
m_buffer[m_offset++] = value[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillToEnd(byte ch)
|
void fill_to_end(byte ch)
|
||||||
{
|
{
|
||||||
while (m_offset < m_buffer.size())
|
while (m_offset < m_buffer.size())
|
||||||
m_buffer[m_offset++] = ch;
|
m_buffer[m_offset++] = ch;
|
||||||
|
|
|
@ -151,6 +151,80 @@ ByteBuffer Ext2FS::read_block_containing_inode(unsigned inode, unsigned& blockIn
|
||||||
return readBlock(blockIndex);
|
return readBlock(blockIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ext2FS::BlockListShape Ext2FS::compute_block_list_shape(unsigned blocks)
|
||||||
|
{
|
||||||
|
BlockListShape shape;
|
||||||
|
const unsigned 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);
|
||||||
|
blocks_remaining -= shape.indirect_blocks;
|
||||||
|
shape.meta_blocks += 1;
|
||||||
|
if (!blocks_remaining)
|
||||||
|
return shape;
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
// FIXME: Support dind/tind blocks.
|
||||||
|
shape.doubly_indirect_blocks = min(blocks_remaining, entries_per_block * 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);
|
||||||
|
blocks_remaining -= shape.triply_indirect_blocks;
|
||||||
|
// FIXME: What do we do for files >= 16GB?
|
||||||
|
ASSERT(!blocks_remaining);
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2inode, Vector<BlockIndex>&& blocks)
|
||||||
|
{
|
||||||
|
dbgprintf("Ext2FS: writing %u block(s) to i_block array\n", min((size_t)EXT2_NDIR_BLOCKS, blocks.size()));
|
||||||
|
|
||||||
|
auto old_shape = compute_block_list_shape(e2inode.i_blocks / (2 << super_block().s_log_block_size));
|
||||||
|
auto new_shape = compute_block_list_shape(blocks.size());
|
||||||
|
|
||||||
|
Vector<BlockIndex> new_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned output_block_index = 0;
|
||||||
|
unsigned remaining_blocks = blocks.size();
|
||||||
|
for (unsigned i = 0; i < new_shape.direct_blocks; ++i) {
|
||||||
|
e2inode.i_block[i] = blocks[output_block_index++];
|
||||||
|
--remaining_blocks;
|
||||||
|
}
|
||||||
|
write_ext2_inode(inode_index, e2inode);
|
||||||
|
|
||||||
|
if (!remaining_blocks)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!e2inode.i_block[EXT2_IND_BLOCK]) {
|
||||||
|
e2inode.i_block[EXT2_IND_BLOCK] = new_meta_blocks.take_last();
|
||||||
|
write_ext2_inode(inode_index, e2inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto block_contents = ByteBuffer::create_uninitialized(blockSize());
|
||||||
|
BufferStream stream(block_contents);
|
||||||
|
ASSERT(new_shape.indirect_blocks <= EXT2_ADDR_PER_BLOCK(&super_block()));
|
||||||
|
for (unsigned i = 0; i < new_shape.indirect_blocks; ++i) {
|
||||||
|
stream << blocks[output_block_index++];
|
||||||
|
--remaining_blocks;
|
||||||
|
}
|
||||||
|
stream.fill_to_end(0);
|
||||||
|
writeBlock(e2inode.i_block[EXT2_IND_BLOCK], block_contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!remaining_blocks)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// FIXME: Implement!
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
Vector<unsigned> Ext2FS::block_list_for_inode(const ext2_inode& e2inode, bool include_block_list_blocks) const
|
Vector<unsigned> Ext2FS::block_list_for_inode(const ext2_inode& e2inode, bool include_block_list_blocks) const
|
||||||
{
|
{
|
||||||
unsigned entriesPerBlock = EXT2_ADDR_PER_BLOCK(&super_block());
|
unsigned entriesPerBlock = EXT2_ADDR_PER_BLOCK(&super_block());
|
||||||
|
@ -558,7 +632,7 @@ bool Ext2FS::write_directory_inode(unsigned directoryInode, Vector<DirectoryEntr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.fillToEnd(0);
|
stream.fill_to_end(0);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
kprintf("data to write (%u):\n", directoryData.size());
|
kprintf("data to write (%u):\n", directoryData.size());
|
||||||
|
@ -986,10 +1060,8 @@ RetainPtr<Inode> Ext2FS::create_inode(InodeIdentifier parent_id, const String& n
|
||||||
// FIXME: Implement writing out indirect blocks!
|
// FIXME: Implement writing out indirect blocks!
|
||||||
ASSERT(blocks.size() < EXT2_NDIR_BLOCKS);
|
ASSERT(blocks.size() < EXT2_NDIR_BLOCKS);
|
||||||
|
|
||||||
dbgprintf("Ext2FS: writing %u blocks to i_block array\n", min((size_t)EXT2_NDIR_BLOCKS, blocks.size()));
|
success = write_block_list_for_inode(inode_id, *e2inode, move(blocks));
|
||||||
for (unsigned i = 0; i < min((size_t)EXT2_NDIR_BLOCKS, blocks.size()); ++i) {
|
ASSERT(success);
|
||||||
e2inode->i_block[i] = blocks[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
dbgprintf("Ext2FS: writing initial metadata for inode %u\n", inode_id);
|
dbgprintf("Ext2FS: writing initial metadata for inode %u\n", inode_id);
|
||||||
e2inode->i_flags = 0;
|
e2inode->i_flags = 0;
|
||||||
|
|
|
@ -93,6 +93,7 @@ private:
|
||||||
unsigned group_index_from_inode(unsigned) const;
|
unsigned group_index_from_inode(unsigned) 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&, Vector<BlockIndex>&&);
|
||||||
|
|
||||||
void dump_block_bitmap(unsigned groupIndex) const;
|
void dump_block_bitmap(unsigned groupIndex) const;
|
||||||
void dump_inode_bitmap(unsigned groupIndex) const;
|
void dump_inode_bitmap(unsigned groupIndex) const;
|
||||||
|
@ -109,6 +110,16 @@ private:
|
||||||
void uncache_inode(InodeIndex);
|
void uncache_inode(InodeIndex);
|
||||||
void free_inode(Ext2FSInode&);
|
void free_inode(Ext2FSInode&);
|
||||||
|
|
||||||
|
struct BlockListShape {
|
||||||
|
unsigned direct_blocks { 0 };
|
||||||
|
unsigned indirect_blocks { 0 };
|
||||||
|
unsigned doubly_indirect_blocks { 0 };
|
||||||
|
unsigned triply_indirect_blocks { 0 };
|
||||||
|
unsigned meta_blocks { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
BlockListShape compute_block_list_shape(unsigned blocks);
|
||||||
|
|
||||||
unsigned m_blockGroupCount { 0 };
|
unsigned m_blockGroupCount { 0 };
|
||||||
|
|
||||||
mutable ByteBuffer m_cached_super_block;
|
mutable ByteBuffer m_cached_super_block;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue