From 156eeb183522453e79f9bfe86f796d967cb1bac5 Mon Sep 17 00:00:00 2001 From: Zhenchen Wang Date: Mon, 17 Nov 2025 23:25:33 +0800 Subject: [PATCH] Add the fsnotify hook function to the VFS layer Signed-off-by: Zhenchen Wang --- kernel/src/fs/path/dentry.rs | 32 +++++++++++++++++++++---------- kernel/src/syscall/chmod.rs | 8 +++++++- kernel/src/syscall/close.rs | 3 +++ kernel/src/syscall/fallocate.rs | 2 ++ kernel/src/syscall/getdents64.rs | 3 +++ kernel/src/syscall/mkdir.rs | 4 +++- kernel/src/syscall/mknod.rs | 3 ++- kernel/src/syscall/open.rs | 7 +++++-- kernel/src/syscall/pread64.rs | 5 +++++ kernel/src/syscall/preadv.rs | 9 +++++++++ kernel/src/syscall/pwrite64.rs | 6 ++++++ kernel/src/syscall/pwritev.rs | 9 +++++++++ kernel/src/syscall/read.rs | 4 ++++ kernel/src/syscall/removexattr.rs | 11 +++++++++-- kernel/src/syscall/sendfile.rs | 4 ++++ kernel/src/syscall/setxattr.rs | 5 ++++- kernel/src/syscall/symlink.rs | 2 ++ kernel/src/syscall/truncate.rs | 5 +++++ kernel/src/syscall/utimens.rs | 3 ++- kernel/src/syscall/write.rs | 4 ++++ 20 files changed, 110 insertions(+), 19 deletions(-) diff --git a/kernel/src/fs/path/dentry.rs b/kernel/src/fs/path/dentry.rs index e84aa50b8..73338605b 100644 --- a/kernel/src/fs/path/dentry.rs +++ b/kernel/src/fs/path/dentry.rs @@ -265,16 +265,22 @@ impl Dentry { }; self.inode.unlink(name)?; + + let nlinks = child_inode.metadata().nlinks; fs::notify::on_link_count(&child_inode); - if child_inode.metadata().nlinks == 0 { + if nlinks == 0 { fs::notify::on_inode_removed(&child_inode); - let deleted_watches = child_inode.fsnotify_publisher().remove_all_subscribers(); + } + fs::notify::on_delete(self.inode(), &child_inode, || name.to_string()); + if nlinks == 0 { + let publisher = child_inode.fs_event_publisher(); + publisher.disable_new_subscribers(); + let removed_nr_subscribers = publisher.remove_all_subscribers(); child_inode .fs() - .fsnotify_info() - .remove_subscribers(deleted_watches); + .fs_event_subscriber_stats() + .remove_subscribers(removed_nr_subscribers); } - fs::notify::on_delete(self.inode(), &child_inode, String::from(name)); Ok(()) } @@ -310,15 +316,21 @@ impl Dentry { }; self.inode.rmdir(name)?; - if child_inode.metadata().nlinks == 0 { + + let nlinks = child_inode.metadata().nlinks; + if nlinks == 0 { fs::notify::on_inode_removed(&child_inode); - let deleted_watches = child_inode.fsnotify_publisher().remove_all_subscribers(); + } + fs::notify::on_delete(self.inode(), &child_inode, || name.to_string()); + if nlinks == 0 { + let publisher = child_inode.fs_event_publisher(); + publisher.disable_new_subscribers(); + let removed_nr_subscribers = publisher.remove_all_subscribers(); child_inode .fs() - .fsnotify_info() - .remove_subscribers(deleted_watches); + .fs_event_subscriber_stats() + .remove_subscribers(removed_nr_subscribers); } - fs::notify::on_delete(self.inode(), &child_inode, String::from(name)); Ok(()) } diff --git a/kernel/src/syscall/chmod.rs b/kernel/src/syscall/chmod.rs index b210587be..39a888b17 100644 --- a/kernel/src/syscall/chmod.rs +++ b/kernel/src/syscall/chmod.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::{ file_table::{get_file_fast, FileDesc}, fs_resolver::{FsPath, AT_FDCWD}, @@ -16,6 +17,9 @@ pub fn sys_fchmod(fd: FileDesc, mode: u16, ctx: &Context) -> Result Result { file_table_locked.close_file(fd).unwrap() }; + fs::notify::on_close(&file); + // Cleanup work needs to be done in the `Drop` impl. // // We don't mind the races between closing the file descriptor and using the file descriptor, diff --git a/kernel/src/syscall/fallocate.rs b/kernel/src/syscall/fallocate.rs index a67257753..e8264d5db 100644 --- a/kernel/src/syscall/fallocate.rs +++ b/kernel/src/syscall/fallocate.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::{ file_table::{get_file_fast, FileDesc}, utils::FallocMode, @@ -33,6 +34,7 @@ pub fn sys_fallocate( )?; file.fallocate(falloc_mode, offset as usize, len as usize)?; + fs::notify::on_modify(&file); Ok(SyscallReturn::Return(0)) } diff --git a/kernel/src/syscall/getdents64.rs b/kernel/src/syscall/getdents64.rs index 1353695a4..118e51f1c 100644 --- a/kernel/src/syscall/getdents64.rs +++ b/kernel/src/syscall/getdents64.rs @@ -4,6 +4,7 @@ use core::marker::PhantomData; use super::SyscallReturn; use crate::{ + fs, fs::{ file_table::{get_file_fast, FileDesc}, utils::{DirentVisitor, InodeType}, @@ -34,6 +35,7 @@ pub fn sys_getdents( let read_len = reader.read_len(); ctx.user_space() .write_bytes(buf_addr, &mut VmReader::from(&buffer[..read_len]))?; + fs::notify::on_access(&file); Ok(SyscallReturn::Return(read_len as _)) } @@ -60,6 +62,7 @@ pub fn sys_getdents64( let read_len = reader.read_len(); ctx.user_space() .write_bytes(buf_addr, &mut VmReader::from(&buffer[..read_len]))?; + fs::notify::on_access(&file); Ok(SyscallReturn::Return(read_len as _)) } diff --git a/kernel/src/syscall/mkdir.rs b/kernel/src/syscall/mkdir.rs index 76ca2db96..1475ad41a 100644 --- a/kernel/src/syscall/mkdir.rs +++ b/kernel/src/syscall/mkdir.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::{ file_table::FileDesc, fs_resolver::{FsPath, AT_FDCWD}, @@ -35,7 +36,8 @@ pub fn sys_mkdirat( let mask_mode = mode & !fs_ref.umask().get(); InodeMode::from_bits_truncate(mask_mode) }; - let _ = dir_path.new_fs_child(&name, InodeType::Dir, inode_mode)?; + dir_path.new_fs_child(&name, InodeType::Dir, inode_mode)?; + fs::notify::on_mkdir(&dir_path, name); Ok(SyscallReturn::Return(0)) } diff --git a/kernel/src/syscall/mknod.rs b/kernel/src/syscall/mknod.rs index b9964e241..16d2d3bef 100644 --- a/kernel/src/syscall/mknod.rs +++ b/kernel/src/syscall/mknod.rs @@ -5,6 +5,7 @@ use device_id::DeviceId; use super::SyscallReturn; use crate::{ device::get_device, + fs, fs::{ file_table::FileDesc, fs_resolver::{FsPath, AT_FDCWD}, @@ -59,7 +60,7 @@ pub fn sys_mknodat( } _ => return_errno_with_message!(Errno::EPERM, "unimplemented file types"), } - + fs::notify::on_create(&dir_path, name); Ok(SyscallReturn::Return(0)) } diff --git a/kernel/src/syscall/open.rs b/kernel/src/syscall/open.rs index 6b126e162..2b97e626c 100644 --- a/kernel/src/syscall/open.rs +++ b/kernel/src/syscall/open.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::{ file_handle::FileLike, file_table::{FdFlags, FileDesc}, @@ -56,9 +57,10 @@ pub fn sys_openat( } else { FdFlags::empty() }; - file_table_locked.insert(file_handle, fd_flags) + file_table_locked.insert(file_handle.clone(), fd_flags) }; - + let file_like: Arc = file_handle; + fs::notify::on_open(&file_like); Ok(SyscallReturn::Return(fd as _)) } @@ -122,6 +124,7 @@ fn do_open( let (parent, tail_name) = result.into_parent_and_basename(); let new_path = parent.new_fs_child(&tail_name, InodeType::File, open_args.inode_mode)?; + fs::notify::on_create(&parent, tail_name.clone()); // Don't check access mode for newly created file. Arc::new(InodeHandle::new_unchecked_access( diff --git a/kernel/src/syscall/pread64.rs b/kernel/src/syscall/pread64.rs index 3d669a0c8..4f130d6ae 100644 --- a/kernel/src/syscall/pread64.rs +++ b/kernel/src/syscall/pread64.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::file_table::{get_file_fast, FileDesc}, prelude::*, }; @@ -39,5 +40,9 @@ pub fn sys_pread64( file.read_at(offset as usize, &mut writer)? }; + if read_len > 0 { + fs::notify::on_access(&file); + } + Ok(SyscallReturn::Return(read_len as _)) } diff --git a/kernel/src/syscall/preadv.rs b/kernel/src/syscall/preadv.rs index 8369db498..b114622cc 100644 --- a/kernel/src/syscall/preadv.rs +++ b/kernel/src/syscall/preadv.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::file_table::{get_file_fast, FileDesc}, prelude::*, util::VmWriterArray, @@ -110,6 +111,10 @@ fn do_sys_preadv( } } + if total_len > 0 { + fs::notify::on_access(&file); + } + Ok(total_len) } @@ -155,6 +160,10 @@ fn do_sys_readv( } } + if total_len > 0 { + fs::notify::on_access(&file); + } + Ok(total_len) } diff --git a/kernel/src/syscall/pwrite64.rs b/kernel/src/syscall/pwrite64.rs index add082d8e..7ad5462de 100644 --- a/kernel/src/syscall/pwrite64.rs +++ b/kernel/src/syscall/pwrite64.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::file_table::{get_file_fast, FileDesc}, prelude::*, }; @@ -36,5 +37,10 @@ pub fn sys_pwrite64( let user_space = ctx.user_space(); let mut reader = user_space.reader(user_buf_ptr, user_buf_len)?; let write_len = file.write_at(offset as _, &mut reader)?; + + if write_len > 0 { + fs::notify::on_modify(&file); + } + Ok(SyscallReturn::Return(write_len as _)) } diff --git a/kernel/src/syscall/pwritev.rs b/kernel/src/syscall/pwritev.rs index 8bf2e28b0..9dfc8a329 100644 --- a/kernel/src/syscall/pwritev.rs +++ b/kernel/src/syscall/pwritev.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::file_table::{get_file_fast, FileDesc}, prelude::*, util::VmReaderArray, @@ -111,6 +112,10 @@ fn do_sys_pwritev( break; } } + if total_len > 0 { + fs::notify::on_modify(&file); + } + Ok(total_len) } @@ -151,6 +156,10 @@ fn do_sys_writev( break; } } + if total_len > 0 { + fs::notify::on_modify(&file); + } + Ok(total_len) } diff --git a/kernel/src/syscall/read.rs b/kernel/src/syscall/read.rs index 19c48fa8e..62cc01c0d 100644 --- a/kernel/src/syscall/read.rs +++ b/kernel/src/syscall/read.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::file_table::{get_file_fast, FileDesc}, prelude::*, }; @@ -37,5 +38,8 @@ pub fn sys_read( _ => err, })?; + if read_len > 0 { + fs::notify::on_access(&file); + } Ok(SyscallReturn::Return(read_len as _)) } diff --git a/kernel/src/syscall/removexattr.rs b/kernel/src/syscall/removexattr.rs index 199dec2d6..d41940e6c 100644 --- a/kernel/src/syscall/removexattr.rs +++ b/kernel/src/syscall/removexattr.rs @@ -8,6 +8,7 @@ use super::{ SyscallReturn, }; use crate::{ + fs, fs::file_table::{get_file_fast, FileDesc}, prelude::*, syscall::constants::MAX_FILENAME_LEN, @@ -52,6 +53,12 @@ fn removexattr( let xattr_name = parse_xattr_name(name_str.as_ref())?; check_xattr_namespace(xattr_name.namespace(), ctx)?; - let path = lookup_path_for_xattr(&file_ctx, ctx)?; - path.remove_xattr(xattr_name) + match lookup_path_for_xattr(&file_ctx, ctx) { + Ok(path) => { + path.remove_xattr(xattr_name)?; + fs::notify::on_attr_change(&path); + Ok(()) + } + Err(e) => Err(e), + } } diff --git a/kernel/src/syscall/sendfile.rs b/kernel/src/syscall/sendfile.rs index ac0f2c7dd..1025c2a4e 100644 --- a/kernel/src/syscall/sendfile.rs +++ b/kernel/src/syscall/sendfile.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::file_table::{FileDesc, WithFileTable}, prelude::*, }; @@ -117,5 +118,8 @@ pub fn sys_sendfile( ctx.user_space().write_val(offset_ptr, &(offset as isize))?; } + fs::notify::on_access(&in_file); + fs::notify::on_modify(&out_file); + Ok(SyscallReturn::Return(total_len as _)) } diff --git a/kernel/src/syscall/setxattr.rs b/kernel/src/syscall/setxattr.rs index a135b6baa..38ef8cd5a 100644 --- a/kernel/src/syscall/setxattr.rs +++ b/kernel/src/syscall/setxattr.rs @@ -4,6 +4,7 @@ use alloc::borrow::Cow; use super::SyscallReturn; use crate::{ + fs, fs::{ file_handle::FileLike, file_table::{get_file_fast, FileDesc}, @@ -114,7 +115,9 @@ fn setxattr( let mut value_reader = user_space.reader(value_ptr, value_len)?; let path = lookup_path_for_xattr(&file_ctx, ctx)?; - path.set_xattr(xattr_name, &mut value_reader, flags) + path.set_xattr(xattr_name, &mut value_reader, flags)?; + fs::notify::on_attr_change(&path); + Ok(()) } /// The context to describe the target file for xattr operations. diff --git a/kernel/src/syscall/symlink.rs b/kernel/src/syscall/symlink.rs index 13a8b82ff..f552838ad 100644 --- a/kernel/src/syscall/symlink.rs +++ b/kernel/src/syscall/symlink.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::{ file_table::FileDesc, fs_resolver::{FsPath, AT_FDCWD}, @@ -43,6 +44,7 @@ pub fn sys_symlinkat( let new_path = dir_path.new_fs_child(&link_name, InodeType::SymLink, mkmod!(a+rwx))?; new_path.inode().write_link(&target)?; + fs::notify::on_create(&dir_path, link_name); Ok(SyscallReturn::Return(0)) } diff --git a/kernel/src/syscall/truncate.rs b/kernel/src/syscall/truncate.rs index 3f70b78d4..80aa747fa 100644 --- a/kernel/src/syscall/truncate.rs +++ b/kernel/src/syscall/truncate.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::{ file_table::{get_file_fast, FileDesc}, fs_resolver::{FsPath, AT_FDCWD}, @@ -19,6 +20,9 @@ pub fn sys_ftruncate(fd: FileDesc, len: isize, ctx: &Context) -> Result Result) -> Result path.set_atime(atime); path.set_mtime(mtime); path.set_ctime(ctime); - + fs::notify::on_attr_change(path); Ok(SyscallReturn::Return(0)) } diff --git a/kernel/src/syscall/write.rs b/kernel/src/syscall/write.rs index b34b5a615..66d36e83d 100644 --- a/kernel/src/syscall/write.rs +++ b/kernel/src/syscall/write.rs @@ -2,6 +2,7 @@ use super::SyscallReturn; use crate::{ + fs, fs::file_table::{get_file_fast, FileDesc}, prelude::*, }; @@ -37,5 +38,8 @@ pub fn sys_write( _ => err, })?; + if write_len > 0 { + fs::notify::on_modify(&file); + } Ok(SyscallReturn::Return(write_len as _)) }