diff --git a/kernel/src/fs/notify/inotify.rs b/kernel/src/fs/notify/inotify.rs index 8729306df..459a4229f 100644 --- a/kernel/src/fs/notify/inotify.rs +++ b/kernel/src/fs/notify/inotify.rs @@ -145,7 +145,7 @@ impl InotifyFile { continue; } - // The subscriber is dead because it's a one-shot subscriber or the inode is dead. + // The subscriber is dead because it's a one-shot subscriber. // The watch is considered removed. let Some(subscriber) = entry.subscriber.upgrade() else { let wd = *wd; @@ -182,7 +182,6 @@ impl InotifyFile { "adding an inotify watch to a deleted inode is not supported yet" ); } - inode.fs().fs_event_subscriber_stats().add_subscriber(); let wd = inotify_subscriber.wd(); let entry = SubscriberEntry { @@ -209,13 +208,10 @@ impl InotifyFile { _ => return_errno_with_message!(Errno::EINVAL, "the inotify watch does not exist"), }; - if inode + inode .fs_event_publisher() .unwrap() - .remove_subscriber(&(subscriber as _)) - { - inode.fs().fs_event_subscriber_stats().remove_subscriber(); - } + .remove_subscriber(&(subscriber as _)); Ok(()) } diff --git a/kernel/src/fs/notify/mod.rs b/kernel/src/fs/notify/mod.rs index 3e5150c3a..8409a5177 100644 --- a/kernel/src/fs/notify/mod.rs +++ b/kernel/src/fs/notify/mod.rs @@ -17,7 +17,7 @@ use crate::{ pub mod inotify; -use super::utils::{Inode, InodeExt, InodeType}; +use super::utils::{FileSystem, Inode, InodeExt, InodeType}; /// Publishes filesystem events to subscribers. /// @@ -25,12 +25,14 @@ use super::utils::{Inode, InodeExt, InodeType}; /// subscribers interested in filesystem events. When an event occurs, the publisher /// notifies all subscribers whose interesting events match the event. pub struct FsEventPublisher { - /// List of FS event subscribers. + /// A list of FS event subscribers. subscribers: RwLock>>, /// All interesting FS event types (aggregated from all subscribers). all_interesting_events: AtomicFsEvents, /// Whether this publisher still accepts new subscribers. accepts_new_subscribers: AtomicBool, + /// A weak reference to the file system. + fs: Weak, } impl Debug for FsEventPublisher { @@ -41,18 +43,13 @@ impl Debug for FsEventPublisher { } } -impl Default for FsEventPublisher { - fn default() -> Self { - Self::new() - } -} - impl FsEventPublisher { - pub fn new() -> Self { + pub fn new(fs: Weak) -> Self { Self { subscribers: RwLock::new(Vec::new()), all_interesting_events: AtomicFsEvents::new(FsEvents::empty()), accepts_new_subscribers: AtomicBool::new(true), + fs, } } @@ -72,6 +69,10 @@ impl FsEventPublisher { subscribers.push(subscriber); + if let Some(fs) = self.fs.upgrade() { + fs.fs_event_subscriber_stats().add_subscriber(); + } + true } @@ -87,6 +88,10 @@ impl FsEventPublisher { subscriber.deliver_event(FsEvents::IN_IGNORED, None); } + if let Some(fs) = self.fs.upgrade() { + fs.fs_event_subscriber_stats().remove_subscriber(); + } + removed } @@ -104,6 +109,11 @@ impl FsEventPublisher { self.all_interesting_events .store(FsEvents::empty(), Ordering::Relaxed); + if let Some(fs) = self.fs.upgrade() { + fs.fs_event_subscriber_stats() + .remove_subscribers(num_subscribers); + } + num_subscribers } diff --git a/kernel/src/fs/utils/inode_ext.rs b/kernel/src/fs/utils/inode_ext.rs index 472b8c78c..c0463473c 100644 --- a/kernel/src/fs/utils/inode_ext.rs +++ b/kernel/src/fs/utils/inode_ext.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -use alloc::boxed::ThinBox; +use alloc::{boxed::ThinBox, sync::Arc}; use super::{FlockList, Inode, RangeLockList}; use crate::fs::notify::FsEventPublisher; @@ -59,7 +59,7 @@ impl InodeExt for dyn Inode { fn fs_event_publisher_or_init(&self) -> &FsEventPublisher { self.extension() .group1() - .call_once(|| ThinBox::new_unsize(FsEventPublisher::new())) + .call_once(|| ThinBox::new_unsize(FsEventPublisher::new(Arc::downgrade(&self.fs())))) .downcast_ref() .unwrap() }