diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp index aa4b08eb415..616092689e4 100644 --- a/Kernel/FileSystem/Ext2FileSystem.cpp +++ b/Kernel/FileSystem/Ext2FileSystem.cpp @@ -981,6 +981,8 @@ KResult Ext2FSInode::add_child(Inode& child, const StringView& name, mode_t mode bool success = write_directory(entries); if (success) m_lookup_cache.set(name, child.index()); + + did_add_child(name); return KSuccess; } @@ -1022,6 +1024,8 @@ KResult Ext2FSInode::remove_child(const StringView& name) auto child_inode = fs().get_inode(child_id); child_inode->decrement_link_count(); + + did_remove_child(name); return KSuccess; } diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index 8befec53639..aa1c97b4fa2 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -215,6 +215,22 @@ void Inode::set_metadata_dirty(bool metadata_dirty) } } +void Inode::did_add_child(const String& name) +{ + LOCKER(m_lock); + for (auto& watcher : m_watchers) { + watcher->notify_child_added({}, name); + } +} + +void Inode::did_remove_child(const String& name) +{ + LOCKER(m_lock); + for (auto& watcher : m_watchers) { + watcher->notify_child_removed({}, name); + } +} + KResult Inode::prepare_to_write_data() { // FIXME: It's a poor design that filesystems are expected to call this before writing out data. diff --git a/Kernel/FileSystem/Inode.h b/Kernel/FileSystem/Inode.h index 60c5c5fc521..ff15682fbcc 100644 --- a/Kernel/FileSystem/Inode.h +++ b/Kernel/FileSystem/Inode.h @@ -122,6 +122,9 @@ protected: void inode_size_changed(size_t old_size, size_t new_size); KResult prepare_to_write_data(); + void did_add_child(const String& name); + void did_remove_child(const String& name); + mutable Lock m_lock { "Inode" }; private: diff --git a/Kernel/FileSystem/InodeWatcher.cpp b/Kernel/FileSystem/InodeWatcher.cpp index 85a6e751bcc..5d18a7ec997 100644 --- a/Kernel/FileSystem/InodeWatcher.cpp +++ b/Kernel/FileSystem/InodeWatcher.cpp @@ -59,6 +59,7 @@ bool InodeWatcher::can_write(const FileDescription&, size_t) const ssize_t InodeWatcher::read(FileDescription&, size_t, u8* buffer, ssize_t buffer_size) { + LOCKER(m_lock); ASSERT(!m_queue.is_empty() || !m_inode); if (!m_inode) @@ -85,7 +86,20 @@ String InodeWatcher::absolute_path(const FileDescription&) const void InodeWatcher::notify_inode_event(Badge, Event::Type event_type) { - m_queue.enqueue({ event_type }); + LOCKER(m_lock); + m_queue.enqueue({ event_type, {} }); +} + +void InodeWatcher::notify_child_added(Badge, const String& child_name) +{ + LOCKER(m_lock); + m_queue.enqueue({ Event::Type::ChildAdded, child_name }); +} + +void InodeWatcher::notify_child_removed(Badge, const String& child_name) +{ + LOCKER(m_lock); + m_queue.enqueue({ Event::Type::ChildRemoved, child_name }); } } diff --git a/Kernel/FileSystem/InodeWatcher.h b/Kernel/FileSystem/InodeWatcher.h index 399de2b42db..626f190d56e 100644 --- a/Kernel/FileSystem/InodeWatcher.h +++ b/Kernel/FileSystem/InodeWatcher.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace Kernel { @@ -44,9 +45,12 @@ public: enum class Type { Invalid = 0, Modified, + ChildAdded, + ChildRemoved, }; Type type { Type::Invalid }; + String string; }; virtual bool can_read(const FileDescription&, size_t) const override; @@ -57,10 +61,13 @@ public: virtual const char* class_name() const override { return "InodeWatcher"; }; void notify_inode_event(Badge, Event::Type); + void notify_child_added(Badge, const String& child_name); + void notify_child_removed(Badge, const String& child_name); private: explicit InodeWatcher(Inode&); + Lock m_lock; WeakPtr m_inode; CircularQueue m_queue; }; diff --git a/Kernel/FileSystem/TmpFS.cpp b/Kernel/FileSystem/TmpFS.cpp index 66dec6e272f..6cd82b14060 100644 --- a/Kernel/FileSystem/TmpFS.cpp +++ b/Kernel/FileSystem/TmpFS.cpp @@ -297,7 +297,7 @@ KResult TmpFSInode::add_child(Inode& child, const StringView& name, mode_t) FS::DirectoryEntry entry = { owned_name.characters(), owned_name.length(), child.identifier(), 0 }; m_children.set(owned_name, { entry, static_cast(child) }); - notify_watchers(); + did_add_child(name); return KSuccess; } @@ -313,7 +313,7 @@ KResult TmpFSInode::remove_child(const StringView& name) if (it == m_children.end()) return KResult(-ENOENT); m_children.remove(it); - notify_watchers(); + did_remove_child(name); return KSuccess; }