1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-23 18:55:08 +00:00

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.
This commit is contained in:
Andreas Kling 2020-07-04 13:36:55 +02:00
parent ea17d2d3da
commit 0d577ab781
6 changed files with 47 additions and 3 deletions

View file

@ -981,6 +981,8 @@ KResult Ext2FSInode::add_child(Inode& child, const StringView& name, mode_t mode
bool success = write_directory(entries); bool success = write_directory(entries);
if (success) if (success)
m_lookup_cache.set(name, child.index()); m_lookup_cache.set(name, child.index());
did_add_child(name);
return KSuccess; return KSuccess;
} }
@ -1022,6 +1024,8 @@ KResult Ext2FSInode::remove_child(const StringView& name)
auto child_inode = fs().get_inode(child_id); auto child_inode = fs().get_inode(child_id);
child_inode->decrement_link_count(); child_inode->decrement_link_count();
did_remove_child(name);
return KSuccess; return KSuccess;
} }

View file

@ -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() KResult Inode::prepare_to_write_data()
{ {
// FIXME: It's a poor design that filesystems are expected to call this before writing out data. // FIXME: It's a poor design that filesystems are expected to call this before writing out data.

View file

@ -122,6 +122,9 @@ protected:
void inode_size_changed(size_t old_size, size_t new_size); void inode_size_changed(size_t old_size, size_t new_size);
KResult prepare_to_write_data(); KResult prepare_to_write_data();
void did_add_child(const String& name);
void did_remove_child(const String& name);
mutable Lock m_lock { "Inode" }; mutable Lock m_lock { "Inode" };
private: private:

View file

@ -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) ssize_t InodeWatcher::read(FileDescription&, size_t, u8* buffer, ssize_t buffer_size)
{ {
LOCKER(m_lock);
ASSERT(!m_queue.is_empty() || !m_inode); ASSERT(!m_queue.is_empty() || !m_inode);
if (!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) 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 });
} }
} }

View file

@ -30,6 +30,7 @@
#include <AK/CircularQueue.h> #include <AK/CircularQueue.h>
#include <AK/WeakPtr.h> #include <AK/WeakPtr.h>
#include <Kernel/FileSystem/File.h> #include <Kernel/FileSystem/File.h>
#include <Kernel/Lock.h>
namespace Kernel { namespace Kernel {
@ -44,9 +45,12 @@ public:
enum class Type { enum class Type {
Invalid = 0, Invalid = 0,
Modified, Modified,
ChildAdded,
ChildRemoved,
}; };
Type type { Type::Invalid }; Type type { Type::Invalid };
String string;
}; };
virtual bool can_read(const FileDescription&, size_t) const override; virtual bool can_read(const FileDescription&, size_t) const override;
@ -57,10 +61,13 @@ public:
virtual const char* class_name() const override { return "InodeWatcher"; }; virtual const char* class_name() const override { return "InodeWatcher"; };
void notify_inode_event(Badge<Inode>, Event::Type); 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: private:
explicit InodeWatcher(Inode&); explicit InodeWatcher(Inode&);
Lock m_lock;
WeakPtr<Inode> m_inode; WeakPtr<Inode> m_inode;
CircularQueue<Event, 32> m_queue; CircularQueue<Event, 32> m_queue;
}; };

View file

@ -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 }; FS::DirectoryEntry entry = { owned_name.characters(), owned_name.length(), child.identifier(), 0 };
m_children.set(owned_name, { entry, static_cast<TmpFSInode&>(child) }); m_children.set(owned_name, { entry, static_cast<TmpFSInode&>(child) });
notify_watchers(); did_add_child(name);
return KSuccess; return KSuccess;
} }
@ -313,7 +313,7 @@ KResult TmpFSInode::remove_child(const StringView& name)
if (it == m_children.end()) if (it == m_children.end())
return KResult(-ENOENT); return KResult(-ENOENT);
m_children.remove(it); m_children.remove(it);
notify_watchers(); did_remove_child(name);
return KSuccess; return KSuccess;
} }