diff options
Diffstat (limited to 'Kernel/FileSystem/InodeWatcher.h')
-rw-r--r-- | Kernel/FileSystem/InodeWatcher.h | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/Kernel/FileSystem/InodeWatcher.h b/Kernel/FileSystem/InodeWatcher.h index 1c55104a8f..f429e17ab4 100644 --- a/Kernel/FileSystem/InodeWatcher.h +++ b/Kernel/FileSystem/InodeWatcher.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,38 +8,76 @@ #pragma once #include <AK/Badge.h> +#include <AK/Checked.h> #include <AK/CircularQueue.h> -#include <AK/WeakPtr.h> +#include <AK/HashMap.h> +#include <AK/NonnullOwnPtr.h> #include <Kernel/API/InodeWatcherEvent.h> #include <Kernel/FileSystem/File.h> -#include <Kernel/Lock.h> namespace Kernel { class Inode; +// A specific description of a watch. +struct WatchDescription { + int wd; + Inode& inode; + unsigned event_mask; + + static NonnullOwnPtr<WatchDescription> create(int wd, Inode& inode, unsigned event_mask) + { + return adopt_own(*new WatchDescription(wd, inode, event_mask)); + } + +private: + WatchDescription(int wd, Inode& inode, unsigned event_mask) + : wd(wd) + , inode(inode) + , event_mask(event_mask) + { + } +}; + class InodeWatcher final : public File { public: - static NonnullRefPtr<InodeWatcher> create(Inode&); + static NonnullRefPtr<InodeWatcher> create(); virtual ~InodeWatcher() override; virtual bool can_read(const FileDescription&, size_t) const override; - virtual bool can_write(const FileDescription&, size_t) const override; virtual KResultOr<size_t> read(FileDescription&, u64, UserOrKernelBuffer&, size_t) override; - virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override; + // Can't write to an inode watcher. + virtual bool can_write(const FileDescription&, size_t) const override { return true; } + virtual KResultOr<size_t> write(FileDescription&, u64, const UserOrKernelBuffer&, size_t) override { return EIO; } + virtual KResult close() override; + virtual String absolute_path(const FileDescription&) const override; virtual const char* class_name() const override { return "InodeWatcher"; }; + virtual bool is_inode_watcher() const override { return true; } + + void notify_inode_event(Badge<Inode>, InodeIdentifier, InodeWatcherEvent::Type, String const& name = {}); - void notify_inode_event(Badge<Inode>, InodeWatcherEvent::Type); - void notify_child_added(Badge<Inode>, const InodeIdentifier& child_id); - void notify_child_removed(Badge<Inode>, const InodeIdentifier& child_id); + KResultOr<int> register_inode(Inode&, unsigned event_mask); + KResult unregister_by_wd(int); + void unregister_by_inode(Badge<Inode>, InodeIdentifier); private: - explicit InodeWatcher(Inode&); + explicit InodeWatcher() { } + + mutable Lock m_lock; + + struct Event { + int wd { 0 }; + InodeWatcherEvent::Type type { InodeWatcherEvent::Type::Invalid }; + String path; + }; + CircularQueue<Event, 32> m_queue; + Checked<int> m_wd_counter { 1 }; - Lock m_lock; - WeakPtr<Inode> m_inode; - CircularQueue<InodeWatcherEvent, 32> m_queue; + // NOTE: These two hashmaps provide two different ways of reaching the same + // watch description, so they will overlap. + HashMap<int, NonnullOwnPtr<WatchDescription>> m_wd_to_watches; + HashMap<InodeIdentifier, WatchDescription*> m_inode_to_watches; }; } |