summaryrefslogtreecommitdiff
path: root/Kernel/FileSystem
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-07-18 13:47:18 +0200
committerAndreas Kling <kling@serenityos.org>2021-07-18 14:29:27 +0200
commit61e17ed5907c190276b37cfbb7091f76e4506d1e (patch)
treec6a7b7855bb2ad518d10b400af11df12e5f58537 /Kernel/FileSystem
parentb748f11f2dceb81c50192eda2d43b225f05c282a (diff)
downloadserenity-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.cpp47
-rw-r--r--Kernel/FileSystem/TmpFS.h17
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;
};
}