Ext2FS: Don't cache a full Ext2FSInode object for non-existent inodes.

This was a bit silly. We were always creating Ext2FSInode objects when
Ext2FSInode::get_inode() was called. They'd then sit and fatten up the
inode cache forever, despite not representing allocated inodes.

This patch consults the inode bitmap and if get_inode() is called with
an unallocated inode index, we simply cache a nullptr to represent the
fact that this index is unused.

This could be a lot better optimized, it will currently hit the disk for
every new inode index encountered.
This commit is contained in:
Andreas Kling 2019-01-01 03:35:33 +01:00
parent d07b08a287
commit 8f9542174f
Notes: sideshowbarker 2024-07-19 16:06:13 +09:00
2 changed files with 27 additions and 1 deletions

View file

@ -262,6 +262,12 @@ RetainPtr<Inode> Ext2FS::get_inode(InodeIdentifier inode) const
return (*it).value;
}
if (!get_inode_allocation_state(inode.index())) {
LOCKER(m_inode_cache_lock);
m_inode_cache.set(inode.index(), nullptr);
return nullptr;
}
unsigned block_index;
unsigned offset;
auto block = read_block_containing_inode(inode.index(), block_index, offset);
@ -688,6 +694,21 @@ unsigned Ext2FS::group_index_from_inode(unsigned inode) const
return (inode - 1) / inodes_per_group() + 1;
}
bool Ext2FS::get_inode_allocation_state(InodeIndex index) const
{
if (index == 0)
return true;
auto& bgd = group_descriptor(group_index_from_inode(index));
unsigned inodesPerBitmapBlock = blockSize() * 8;
unsigned bitmapBlockIndex = (index - 1) / inodesPerBitmapBlock;
unsigned bitIndex = (index - 1) % inodesPerBitmapBlock;
auto block = readBlock(bgd.bg_inode_bitmap + bitmapBlockIndex);
ASSERT(block);
auto bitmap = Bitmap::wrap(block.pointer(), block.size());
return bitmap.get(bitIndex);
}
bool Ext2FS::set_inode_allocation_state(unsigned inode, bool newState)
{
auto& bgd = group_descriptor(group_index_from_inode(inode));
@ -901,6 +922,11 @@ RetainPtr<Inode> Ext2FS::create_inode(InodeIdentifier parent_id, const String& n
success = write_ext2_inode(inode_id, *e2inode);
ASSERT(success);
{
// We might have cached the fact that this inode didn't exist. Wipe the slate.
LOCKER(m_inode_cache_lock);
m_inode_cache.remove(inode_id);
}
return get_inode({ id(), inode_id });
}
@ -915,7 +941,6 @@ InodeIdentifier Ext2FS::find_parent_of_inode(InodeIdentifier inode_id) const
Vector<RetainPtr<Ext2FSInode>> directories_in_group;
for (unsigned i = 0; i < inodes_per_group(); ++i) {
// FIXME: Consult the inode bitmap to see which inodes to look into.
auto group_member = get_inode({ id(), firstInodeInGroup + i });
if (!group_member)
continue;

View file

@ -100,6 +100,7 @@ private:
bool add_inode_to_directory(InodeIndex parent, InodeIndex child, const String& name, byte fileType, int& error);
bool write_directory_inode(unsigned directoryInode, Vector<DirectoryEntry>&&);
bool get_inode_allocation_state(InodeIndex) const;
bool set_inode_allocation_state(unsigned inode, bool);
bool set_block_allocation_state(GroupIndex, BlockIndex, bool);