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);
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;
}

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()
{
// 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);
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:

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)
{
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 });
}
}

View file

@ -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;
};

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 };
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;
}