From fe5ca6ca276ad452a16215031fb395b4f5bef048 Mon Sep 17 00:00:00 2001 From: sin-ack Date: Wed, 12 May 2021 19:17:51 +0000 Subject: Kernel: Implement multi-watch InodeWatcher :^) This patch modifies InodeWatcher to switch to a one watcher, multiple watches architecture. The following changes have been made: - The watch_file syscall is removed, and in its place the create_iwatcher, iwatcher_add_watch and iwatcher_remove_watch calls have been added. - InodeWatcher now holds multiple WatchDescriptions for each file that is being watched. - The InodeWatcher file descriptor can be read from to receive events on all watched files. Co-authored-by: Gunnar Beutner --- Kernel/FileSystem/Inode.cpp | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'Kernel/FileSystem/Inode.cpp') diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp index 2adef0aa6e..e1fcee8eb2 100644 --- a/Kernel/FileSystem/Inode.cpp +++ b/Kernel/FileSystem/Inode.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, sin-ack * * SPDX-License-Identifier: BSD-2-Clause */ @@ -109,6 +110,10 @@ Inode::~Inode() { ScopedSpinLock all_inodes_lock(s_all_inodes_lock); all_with_lock().remove(this); + + for (auto& watcher : m_watchers) { + watcher->unregister_by_inode({}, identifier()); + } } void Inode::will_be_destroyed() @@ -211,24 +216,47 @@ void Inode::set_metadata_dirty(bool metadata_dirty) // FIXME: Maybe we should hook into modification events somewhere else, I'm not sure where. // We don't always end up on this particular code path, for instance when writing to an ext2fs file. for (auto& watcher : m_watchers) { - watcher->notify_inode_event({}, InodeWatcherEvent::Type::Modified); + watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::MetadataModified); } } } -void Inode::did_add_child(const InodeIdentifier& child_id) +void Inode::did_add_child(InodeIdentifier const&, String const& name) +{ + Locker locker(m_lock); + + for (auto& watcher : m_watchers) { + watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ChildCreated, name); + } +} + +void Inode::did_remove_child(InodeIdentifier const&, String const& name) +{ + Locker locker(m_lock); + + if (name == "." || name == "..") { + // These are just aliases and are not interesting to userspace. + return; + } + + for (auto& watcher : m_watchers) { + watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ChildDeleted, name); + } +} + +void Inode::did_modify_contents() { Locker locker(m_lock); for (auto& watcher : m_watchers) { - watcher->notify_child_added({}, child_id); + watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ContentModified); } } -void Inode::did_remove_child(const InodeIdentifier& child_id) +void Inode::did_delete_self() { Locker locker(m_lock); for (auto& watcher : m_watchers) { - watcher->notify_child_removed({}, child_id); + watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::Deleted); } } -- cgit v1.2.3