1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:27:45 +00:00

Kernel: Protect Inode's list of watchers with spinlock instead of mutex

This commit is contained in:
Andreas Kling 2022-02-03 01:39:49 +01:00
parent 210689281f
commit e0d9472ced
2 changed files with 28 additions and 27 deletions

View file

@ -93,9 +93,9 @@ Inode::Inode(FileSystem& fs, InodeIndex index)
Inode::~Inode() Inode::~Inode()
{ {
for (auto& watcher : m_watchers) { m_watchers.for_each([&](auto& watcher) {
watcher->unregister_by_inode({}, identifier()); watcher->unregister_by_inode({}, identifier());
} });
} }
void Inode::will_be_destroyed() void Inode::will_be_destroyed()
@ -156,17 +156,19 @@ bool Inode::unbind_socket()
ErrorOr<void> Inode::register_watcher(Badge<InodeWatcher>, InodeWatcher& watcher) ErrorOr<void> Inode::register_watcher(Badge<InodeWatcher>, InodeWatcher& watcher)
{ {
MutexLocker locker(m_inode_lock); return m_watchers.with([&](auto& watchers) -> ErrorOr<void> {
VERIFY(!m_watchers.contains(&watcher)); VERIFY(!watchers.contains(&watcher));
TRY(m_watchers.try_set(&watcher)); TRY(watchers.try_set(&watcher));
return {}; return {};
});
} }
void Inode::unregister_watcher(Badge<InodeWatcher>, InodeWatcher& watcher) void Inode::unregister_watcher(Badge<InodeWatcher>, InodeWatcher& watcher)
{ {
MutexLocker locker(m_inode_lock); m_watchers.with([&](auto& watchers) {
VERIFY(m_watchers.contains(&watcher)); VERIFY(watchers.contains(&watcher));
m_watchers.remove(&watcher); watchers.remove(&watcher);
});
} }
ErrorOr<NonnullRefPtr<FIFO>> Inode::fifo() ErrorOr<NonnullRefPtr<FIFO>> Inode::fifo()
@ -197,49 +199,43 @@ void Inode::set_metadata_dirty(bool metadata_dirty)
if (m_metadata_dirty) { if (m_metadata_dirty) {
// FIXME: Maybe we should hook into modification events somewhere else, I'm not sure where. // 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. // We don't always end up on this particular code path, for instance when writing to an ext2fs file.
for (auto& watcher : m_watchers) { m_watchers.for_each([&](auto& watcher) {
watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::MetadataModified); watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::MetadataModified);
} });
} }
} }
void Inode::did_add_child(InodeIdentifier, StringView name) void Inode::did_add_child(InodeIdentifier, StringView name)
{ {
MutexLocker locker(m_inode_lock); m_watchers.for_each([&](auto& watcher) {
for (auto& watcher : m_watchers) {
watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ChildCreated, name); watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ChildCreated, name);
} });
} }
void Inode::did_remove_child(InodeIdentifier, StringView name) void Inode::did_remove_child(InodeIdentifier, StringView name)
{ {
MutexLocker locker(m_inode_lock);
if (name == "." || name == "..") { if (name == "." || name == "..") {
// These are just aliases and are not interesting to userspace. // These are just aliases and are not interesting to userspace.
return; return;
} }
for (auto& watcher : m_watchers) { m_watchers.for_each([&](auto& watcher) {
watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ChildDeleted, name); watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ChildDeleted, name);
} });
} }
void Inode::did_modify_contents() void Inode::did_modify_contents()
{ {
MutexLocker locker(m_inode_lock); m_watchers.for_each([&](auto& watcher) {
for (auto& watcher : m_watchers) {
watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ContentModified); watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ContentModified);
} });
} }
void Inode::did_delete_self() void Inode::did_delete_self()
{ {
MutexLocker locker(m_inode_lock); m_watchers.for_each([&](auto& watcher) {
for (auto& watcher : m_watchers) {
watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::Deleted); watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::Deleted);
} });
} }
ErrorOr<void> Inode::prepare_to_write_data() ErrorOr<void> Inode::prepare_to_write_data()
@ -370,4 +366,9 @@ void Inode::remove_flocks_for_description(OpenFileDescription const& description
m_flocks.remove(i--); m_flocks.remove(i--);
} }
} }
bool Inode::has_watchers() const
{
return !m_watchers.with([&](auto& watchers) { return watchers.is_empty(); });
}
} }

View file

@ -89,7 +89,7 @@ public:
static void sync_all(); static void sync_all();
void sync(); void sync();
bool has_watchers() const { return !m_watchers.is_empty(); } bool has_watchers() const;
ErrorOr<void> register_watcher(Badge<InodeWatcher>, InodeWatcher&); ErrorOr<void> register_watcher(Badge<InodeWatcher>, InodeWatcher&);
void unregister_watcher(Badge<InodeWatcher>, InodeWatcher&); void unregister_watcher(Badge<InodeWatcher>, InodeWatcher&);
@ -118,7 +118,7 @@ private:
InodeIndex m_index { 0 }; InodeIndex m_index { 0 };
WeakPtr<Memory::SharedInodeVMObject> m_shared_vmobject; WeakPtr<Memory::SharedInodeVMObject> m_shared_vmobject;
RefPtr<LocalSocket> m_socket; RefPtr<LocalSocket> m_socket;
HashTable<InodeWatcher*> m_watchers; SpinlockProtected<HashTable<InodeWatcher*>> m_watchers;
bool m_metadata_dirty { false }; bool m_metadata_dirty { false };
RefPtr<FIFO> m_fifo; RefPtr<FIFO> m_fifo;
IntrusiveListNode<Inode> m_inode_list_node; IntrusiveListNode<Inode> m_inode_list_node;