Kernel: Ensure Ext2FSInode's lookup is populated before using it
This fixes #8133. Ext2FSInode::remove_child() searches the lookup cache, so if it's not initialized, removing the child fails. If the child was a directory, this led to it being corrupted and having 0 children. I also added populate_lookup_cache to add_child. I hadn't seen any bugs there, but if the cache wasn't populated before, adding that one entry would make it think it was populated, so that would cause bugs later.
This commit is contained in:
parent
f1ac0b6a5a
commit
ab7023dbe5
Notes:
sideshowbarker
2024-07-18 11:55:11 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/LadybirdBrowser/ladybird/commit/ab7023dbe55
2 changed files with 15 additions and 9 deletions
|
@ -1209,6 +1209,9 @@ KResult Ext2FSInode::add_child(Inode& child, const StringView& name, mode_t mode
|
|||
if (result.is_error())
|
||||
return result;
|
||||
|
||||
if (auto populate_result = populate_lookup_cache(); populate_result.is_error())
|
||||
return populate_result;
|
||||
|
||||
m_lookup_cache.set(name, child.index());
|
||||
did_add_child(child.identifier(), name);
|
||||
return KSuccess;
|
||||
|
@ -1220,6 +1223,9 @@ KResult Ext2FSInode::remove_child(const StringView& name)
|
|||
dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::remove_child(): Removing '{}'", identifier(), name);
|
||||
VERIFY(is_directory());
|
||||
|
||||
if (auto populate_result = populate_lookup_cache(); populate_result.is_error())
|
||||
return populate_result;
|
||||
|
||||
auto it = m_lookup_cache.find(name);
|
||||
if (it == m_lookup_cache.end())
|
||||
return ENOENT;
|
||||
|
@ -1591,11 +1597,11 @@ KResultOr<NonnullRefPtr<Inode>> Ext2FS::create_inode(Ext2FSInode& parent_inode,
|
|||
return new_inode.release_nonnull();
|
||||
}
|
||||
|
||||
bool Ext2FSInode::populate_lookup_cache() const
|
||||
KResult Ext2FSInode::populate_lookup_cache() const
|
||||
{
|
||||
Locker locker(m_lock);
|
||||
if (!m_lookup_cache.is_empty())
|
||||
return true;
|
||||
return KSuccess;
|
||||
HashMap<String, InodeIndex> children;
|
||||
|
||||
KResult result = traverse_as_directory([&children](auto& entry) {
|
||||
|
@ -1604,19 +1610,18 @@ bool Ext2FSInode::populate_lookup_cache() const
|
|||
});
|
||||
|
||||
if (!result.is_success())
|
||||
return false;
|
||||
return result;
|
||||
|
||||
if (!m_lookup_cache.is_empty())
|
||||
return false;
|
||||
VERIFY(m_lookup_cache.is_empty());
|
||||
m_lookup_cache = move(children);
|
||||
return true;
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
RefPtr<Inode> Ext2FSInode::lookup(StringView name)
|
||||
{
|
||||
VERIFY(is_directory());
|
||||
dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]:lookup(): Looking up '{}'", identifier(), name);
|
||||
if (!populate_lookup_cache())
|
||||
if (populate_lookup_cache().is_error())
|
||||
return {};
|
||||
Locker locker(m_lock);
|
||||
auto it = m_lookup_cache.find(name.hash(), [&](auto& entry) { return entry.key == name; });
|
||||
|
@ -1702,7 +1707,8 @@ KResultOr<size_t> Ext2FSInode::directory_entry_count() const
|
|||
{
|
||||
VERIFY(is_directory());
|
||||
Locker locker(m_lock);
|
||||
populate_lookup_cache();
|
||||
if (auto result = populate_lookup_cache(); result.is_error())
|
||||
return KResultOr<size_t>(result);
|
||||
return m_lookup_cache.size();
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ private:
|
|||
virtual KResultOr<int> get_block_address(int) override;
|
||||
|
||||
KResult write_directory(Vector<Ext2FSDirectoryEntry>&);
|
||||
bool populate_lookup_cache() const;
|
||||
KResult populate_lookup_cache() const;
|
||||
KResult resize(u64);
|
||||
KResult write_indirect_block(BlockBasedFS::BlockIndex, Span<BlockBasedFS::BlockIndex>);
|
||||
KResult grow_doubly_indirect_block(BlockBasedFS::BlockIndex, size_t, Span<BlockBasedFS::BlockIndex>, Vector<BlockBasedFS::BlockIndex>&, unsigned&);
|
||||
|
|
Loading…
Add table
Reference in a new issue