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:
parent
ea17d2d3da
commit
0d577ab781
6 changed files with 47 additions and 3 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue