Add the fsnotify hook function to the VFS layer

Signed-off-by: Zhenchen Wang <m202372036@hust.edu.cn>
This commit is contained in:
Zhenchen Wang 2025-11-17 23:25:33 +08:00 committed by Tate, Hongliang Tian
parent 09665a7692
commit 156eeb1835
20 changed files with 110 additions and 19 deletions

View File

@ -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(())
}

View File

@ -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<SyscallRetur
let mut file_table = ctx.thread_local.borrow_file_table_mut();
let file = get_file_fast!(&mut file_table, fd);
file.inode().set_mode(InodeMode::from_bits_truncate(mode))?;
if let Some(path) = file.path() {
fs::notify::on_attr_change(path);
}
Ok(SyscallReturn::Return(0))
}
@ -46,9 +50,11 @@ pub fn sys_fchmodat(
.read()
.lookup_inode(&fs_path)?
};
path_or_inode
.inode()
.set_mode(InodeMode::from_bits_truncate(mode))?;
if let Some(path) = path_or_inode.into_path() {
fs::notify::on_attr_change(&path);
}
Ok(SyscallReturn::Return(0))
}

View File

@ -4,6 +4,7 @@ use bitflags::bitflags;
use super::SyscallReturn;
use crate::{
fs,
fs::file_table::{FdFlags, FileDesc},
prelude::*,
process::ContextUnshareAdminApi,
@ -26,6 +27,8 @@ pub fn sys_close(fd: FileDesc, ctx: &Context) -> Result<SyscallReturn> {
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,

View File

@ -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))
}

View File

@ -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 _))
}

View File

@ -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))
}

View File

@ -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))
}

View File

@ -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<dyn FileLike> = 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(

View File

@ -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 _))
}

View File

@ -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)
}

View File

@ -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 _))
}

View File

@ -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)
}

View File

@ -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 _))
}

View File

@ -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),
}
}

View File

@ -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 _))
}

View File

@ -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.

View File

@ -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))
}

View File

@ -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<SyscallR
let mut file_table = ctx.thread_local.borrow_file_table_mut();
let file = get_file_fast!(&mut file_table, fd);
file.resize(len as usize)?;
if let Some(path) = file.path() {
fs::notify::on_change(path);
}
Ok(SyscallReturn::Return(0))
}
@ -38,6 +42,7 @@ pub fn sys_truncate(path_ptr: Vaddr, len: isize, ctx: &Context) -> Result<Syscal
.lookup(&fs_path)?
};
dir_path.resize(len as usize)?;
fs::notify::on_change(&dir_path);
Ok(SyscallReturn::Return(0))
}

View File

@ -4,6 +4,7 @@ use core::time::Duration;
use super::{constants::MAX_FILENAME_LEN, SyscallReturn};
use crate::{
fs,
fs::{
file_table::FileDesc,
fs_resolver::{FsPath, AT_FDCWD},
@ -142,7 +143,7 @@ fn vfs_utimes(path: &Path, times: Option<TimeSpecPair>) -> Result<SyscallReturn>
path.set_atime(atime);
path.set_mtime(mtime);
path.set_ctime(ctime);
fs::notify::on_attr_change(path);
Ok(SyscallReturn::Return(0))
}

View File

@ -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 _))
}