Bladeren bron

Kernel: Add "child added" and "child removed" InodeWatcher events

The child name is not yet accessible to userspace, but will be in a
future patch.
Andreas Kling 5 jaren geleden
bovenliggende
commit
0d577ab781

+ 4 - 0
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;
 }
 

+ 16 - 0
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.

+ 3 - 0
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:

+ 15 - 1
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<Inode>, Event::Type event_type)
 {
-    m_queue.enqueue({ event_type });
+    LOCKER(m_lock);
+    m_queue.enqueue({ event_type, {} });
+}
+
+void InodeWatcher::notify_child_added(Badge<Inode>, const String& child_name)
+{
+    LOCKER(m_lock);
+    m_queue.enqueue({ Event::Type::ChildAdded, child_name });
+}
+
+void InodeWatcher::notify_child_removed(Badge<Inode>, const String& child_name)
+{
+    LOCKER(m_lock);
+    m_queue.enqueue({ Event::Type::ChildRemoved, child_name });
 }
 
 }

+ 7 - 0
Kernel/FileSystem/InodeWatcher.h

@@ -30,6 +30,7 @@
 #include <AK/CircularQueue.h>
 #include <AK/WeakPtr.h>
 #include <Kernel/FileSystem/File.h>
+#include <Kernel/Lock.h>
 
 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<Inode>, Event::Type);
+    void notify_child_added(Badge<Inode>, const String& child_name);
+    void notify_child_removed(Badge<Inode>, const String& child_name);
 
 private:
     explicit InodeWatcher(Inode&);
 
+    Lock m_lock;
     WeakPtr<Inode> m_inode;
     CircularQueue<Event, 32> m_queue;
 };

+ 2 - 2
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<TmpFSInode&>(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;
 }