diff options
author | Andreas Kling <kling@serenityos.org> | 2021-07-18 13:47:18 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-18 14:29:27 +0200 |
commit | 61e17ed5907c190276b37cfbb7091f76e4506d1e (patch) | |
tree | c6a7b7855bb2ad518d10b400af11df12e5f58537 /Kernel/FileSystem | |
parent | b748f11f2dceb81c50192eda2d43b225f05c282a (diff) | |
download | serenity-61e17ed5907c190276b37cfbb7091f76e4506d1e.zip |
Kernel/TmpFS: Use IntrusiveList and KString for OOM safety
This patch moves TmpFS to using OOM-safe data types for storing
directory children.
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r-- | Kernel/FileSystem/TmpFS.cpp | 47 | ||||
-rw-r--r-- | Kernel/FileSystem/TmpFS.h | 17 |
2 files changed, 43 insertions, 21 deletions
diff --git a/Kernel/FileSystem/TmpFS.cpp b/Kernel/FileSystem/TmpFS.cpp index 8758601dd1..5323ade291 100644 --- a/Kernel/FileSystem/TmpFS.cpp +++ b/Kernel/FileSystem/TmpFS.cpp @@ -119,9 +119,8 @@ KResult TmpFSInode::traverse_as_directory(Function<bool(FileSystem::DirectoryEnt callback({ ".", identifier(), 0 }); callback({ "..", m_parent, 0 }); - for (auto& it : m_children) { - auto& entry = it.value; - callback({ entry.name, entry.inode->identifier(), 0 }); + for (auto& child : m_children) { + callback({ child.name->view(), child.inode->identifier(), 0 }); } return KSuccess; } @@ -205,10 +204,19 @@ RefPtr<Inode> TmpFSInode::lookup(StringView name) if (name == "..") return fs().get_inode(m_parent); - auto it = m_children.find(name); - if (it == m_children.end()) + auto* child = find_child_by_name(name); + if (!child) return {}; - return fs().get_inode(it->value.inode->identifier()); + return child->inode; +} + +TmpFSInode::Child* TmpFSInode::find_child_by_name(StringView name) +{ + for (auto& child : m_children) { + if (child.name->view() == name) + return &child; + } + return nullptr; } void TmpFSInode::notify_watchers() @@ -273,21 +281,29 @@ KResultOr<NonnullRefPtr<Inode>> TmpFSInode::create_child(StringView name, mode_t return child.release_nonnull(); } -KResult TmpFSInode::add_child(Inode& child, const StringView& name, mode_t) +KResult TmpFSInode::add_child(Inode& child, StringView const& name, mode_t) { - MutexLocker locker(m_inode_lock); VERIFY(is_directory()); VERIFY(child.fsid() == fsid()); if (name.length() > NAME_MAX) return ENAMETOOLONG; - m_children.set(name, { name, static_cast<TmpFSInode&>(child) }); + auto name_kstring = KString::try_create(name); + if (!name_kstring) + return ENOMEM; + + auto* child_entry = new (nothrow) Child { name_kstring.release_nonnull(), static_cast<TmpFSInode&>(child) }; + if (!child_entry) + return ENOMEM; + + MutexLocker locker(m_inode_lock); + m_children.append(*child_entry); did_add_child(child.identifier(), name); return KSuccess; } -KResult TmpFSInode::remove_child(const StringView& name) +KResult TmpFSInode::remove_child(StringView const& name) { MutexLocker locker(m_inode_lock); VERIFY(is_directory()); @@ -295,12 +311,13 @@ KResult TmpFSInode::remove_child(const StringView& name) if (name == "." || name == "..") return KSuccess; - auto it = m_children.find(name); - if (it == m_children.end()) + auto* child = find_child_by_name(name); + if (!child) return ENOENT; - auto child_id = it->value.inode->identifier(); - it->value.inode->did_delete_self(); - m_children.remove(it); + + auto child_id = child->inode->identifier(); + child->inode->did_delete_self(); + m_children.remove(*child); did_remove_child(child_id, name); return KSuccess; } diff --git a/Kernel/FileSystem/TmpFS.h b/Kernel/FileSystem/TmpFS.h index c57a5e23ec..20e2ca51d2 100644 --- a/Kernel/FileSystem/TmpFS.h +++ b/Kernel/FileSystem/TmpFS.h @@ -75,18 +75,23 @@ private: TmpFSInode(TmpFS& fs, InodeMetadata metadata, InodeIdentifier parent); static RefPtr<TmpFSInode> create(TmpFS&, InodeMetadata metadata, InodeIdentifier parent); static RefPtr<TmpFSInode> create_root(TmpFS&); - void notify_watchers(); + struct Child { + NonnullOwnPtr<KString> name; + NonnullRefPtr<TmpFSInode> inode; + IntrusiveListNode<Child> list_node {}; + using List = IntrusiveList<Child, RawPtr<Child>, &Child::list_node>; + }; + + Child* find_child_by_name(StringView); + InodeMetadata m_metadata; InodeIdentifier m_parent; OwnPtr<KBuffer> m_content; - struct Child { - String name; - NonnullRefPtr<TmpFSInode> inode; - }; - HashMap<String, Child> m_children; + + Child::List m_children; }; } |