From 8f9542174fc52ba108566d9c50b5a2509b5e8f5d Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 1 Jan 2019 03:35:33 +0100 Subject: [PATCH] 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. --- VirtualFileSystem/Ext2FileSystem.cpp | 27 ++++++++++++++++++++++++++- VirtualFileSystem/Ext2FileSystem.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/VirtualFileSystem/Ext2FileSystem.cpp b/VirtualFileSystem/Ext2FileSystem.cpp index e5506d30c5..74f1ebd8a6 100644 --- a/VirtualFileSystem/Ext2FileSystem.cpp +++ b/VirtualFileSystem/Ext2FileSystem.cpp @@ -262,6 +262,12 @@ RetainPtr 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 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> 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; diff --git a/VirtualFileSystem/Ext2FileSystem.h b/VirtualFileSystem/Ext2FileSystem.h index ecdca6486b..d531231b96 100644 --- a/VirtualFileSystem/Ext2FileSystem.h +++ b/VirtualFileSystem/Ext2FileSystem.h @@ -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&&); + bool get_inode_allocation_state(InodeIndex) const; bool set_inode_allocation_state(unsigned inode, bool); bool set_block_allocation_state(GroupIndex, BlockIndex, bool);