From a56444e1ade86c99c0fe437c2b1b49b9ea12ea66 Mon Sep 17 00:00:00 2001 From: LoGin Date: Sat, 24 May 2025 23:17:26 +0800 Subject: [PATCH] refactor(vfs): refactor some fs syscalls to syscall-table (#1177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(vfs/syscall): 把sys_open加到调用表 Signed-off-by: longjin * refactor(vfs): 将文件系统相关系统调用拆分为独立模块 将 `close`、`fstat`、`lstat` 和 `stat` 系统调用从 `mod.rs` 中拆分为独立的模块 Signed-off-by: longjin * refactor(vfs): 将ioctl系统调用处理逻辑移至独立模块 将ioctl系统调用的处理逻辑从`mod.rs`中提取到独立的`sys_ioctl.rs`模块中,以提高代码的可维护性和可读性。 Signed-off-by: longjin * refactor(vfs): 重构stat相关系统调用实现 将sys_fstat、sys_lstat和sys_stat的实现统一改为调用Syscall::newfstat,移除重复代码 Signed-off-by: longjin * refactor(vfs): 将do_open函数提取到open_utils模块 将sys_open.rs中的do_open函数提取到新建的open_utils模块,并在多处调用处更新引用路径。 Signed-off-by: longjin --------- Signed-off-by: longjin --- kernel/src/filesystem/vfs/open.rs | 2 +- kernel/src/filesystem/vfs/syscall/mod.rs | 104 +++--------------- .../src/filesystem/vfs/syscall/open_utils.rs | 39 +++++++ .../src/filesystem/vfs/syscall/sys_close.rs | 54 +++++++++ .../src/filesystem/vfs/syscall/sys_fstat.rs | 47 ++++++++ .../src/filesystem/vfs/syscall/sys_ioctl.rs | 77 +++++++++++++ .../src/filesystem/vfs/syscall/sys_lstat.rs | 64 +++++++++++ kernel/src/filesystem/vfs/syscall/sys_open.rs | 57 ++++++++++ kernel/src/filesystem/vfs/syscall/sys_stat.rs | 65 +++++++++++ kernel/src/net/syscall.rs | 11 +- kernel/src/syscall/mod.rs | 37 ------- 11 files changed, 427 insertions(+), 130 deletions(-) create mode 100644 kernel/src/filesystem/vfs/syscall/open_utils.rs create mode 100644 kernel/src/filesystem/vfs/syscall/sys_close.rs create mode 100644 kernel/src/filesystem/vfs/syscall/sys_fstat.rs create mode 100644 kernel/src/filesystem/vfs/syscall/sys_ioctl.rs create mode 100644 kernel/src/filesystem/vfs/syscall/sys_lstat.rs create mode 100644 kernel/src/filesystem/vfs/syscall/sys_open.rs create mode 100644 kernel/src/filesystem/vfs/syscall/sys_stat.rs diff --git a/kernel/src/filesystem/vfs/open.rs b/kernel/src/filesystem/vfs/open.rs index 5b906934..a1b1994f 100644 --- a/kernel/src/filesystem/vfs/open.rs +++ b/kernel/src/filesystem/vfs/open.rs @@ -150,7 +150,7 @@ pub fn ksys_fchown(fd: i32, uid: usize, gid: usize) -> Result Result { - let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? - .into_string() - .map_err(|_| SystemError::EINVAL)?; - - let open_flags: FileMode = FileMode::from_bits(o_flags).ok_or(SystemError::EINVAL)?; - let mode = ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?; - return do_sys_open( - AtFlags::AT_FDCWD.bits(), - &path, - open_flags, - mode, - follow_symlink, - ); - } - pub fn openat( dirfd: i32, path: *const u8, @@ -468,40 +453,6 @@ impl Syscall { return do_sys_open(dirfd, &path, open_flags, mode, follow_symlink); } - /// @brief 关闭文件 - /// - /// @param fd 文件描述符编号 - /// - /// @return 成功返回0,失败返回错误码 - pub fn close(fd: usize) -> Result { - let binding = ProcessManager::current_pcb().fd_table(); - let mut fd_table_guard = binding.write(); - let _file = fd_table_guard.drop_fd(fd as i32)?; - drop(fd_table_guard); - Ok(0) - } - - /// @brief 发送命令到文件描述符对应的设备, - /// - /// @param fd 文件描述符编号 - /// @param cmd 设备相关的请求类型 - /// - /// @return Ok(usize) 成功返回0 - /// @return Err(SystemError) 读取失败,返回posix错误码 - pub fn ioctl(fd: usize, cmd: u32, data: usize) -> Result { - let binding = ProcessManager::current_pcb().fd_table(); - let fd_table_guard = binding.read(); - - let file = fd_table_guard - .get_file_by_fd(fd as i32) - .ok_or(SystemError::EBADF)?; - - // drop guard 以避免无法调度的问题 - drop(fd_table_guard); - let r = file.inode().ioctl(cmd, data, &file.private_data.lock()); - return r; - } - /// @brief 调整文件操作指针的位置 /// /// @param fd 文件描述符编号 @@ -1211,38 +1162,9 @@ impl Syscall { return Err(SystemError::EBADF); } - #[inline(never)] - pub fn fstat(fd: i32, user_stat_ptr: usize) -> Result { - Self::newfstat(fd, user_stat_ptr) - } - - pub fn stat(path: *const u8, user_stat_ptr: usize) -> Result { - let fd = Self::open( - path, - FileMode::O_RDONLY.bits(), - ModeType::empty().bits(), - true, - )?; - let r = Self::fstat(fd as i32, user_stat_ptr); - Self::close(fd).ok(); - return r; - } - - pub fn lstat(path: *const u8, user_stat_ptr: usize) -> Result { - let fd = Self::open( - path, - FileMode::O_RDONLY.bits(), - ModeType::empty().bits(), - false, - )?; - let r = Self::fstat(fd as i32, user_stat_ptr); - Self::close(fd).ok(); - return r; - } - pub fn statfs(path: *const u8, user_statfs: *mut PosixStatfs) -> Result { let mut writer = UserBufferWriter::new(user_statfs, size_of::(), true)?; - let fd = Self::open( + let fd = open_utils::do_open( path, FileMode::O_RDONLY.bits(), ModeType::empty().bits(), diff --git a/kernel/src/filesystem/vfs/syscall/open_utils.rs b/kernel/src/filesystem/vfs/syscall/open_utils.rs new file mode 100644 index 00000000..b887ae47 --- /dev/null +++ b/kernel/src/filesystem/vfs/syscall/open_utils.rs @@ -0,0 +1,39 @@ +use system_error::SystemError; + +use crate::{ + filesystem::vfs::{fcntl::AtFlags, file::FileMode, open::do_sys_open, MAX_PATHLEN}, + syscall::user_access::check_and_clone_cstr, +}; + +use super::ModeType; + +/// Performs the actual file opening operation. +/// +/// # Arguments +/// * `path` - Pointer to the path string +/// * `o_flags` - File opening flags +/// * `mode` - File mode/permissions +/// * `follow_symlink` - Whether to follow symbolic links +/// +/// # Returns +/// File descriptor on success, or error code on failure. +pub(super) fn do_open( + path: *const u8, + o_flags: u32, + mode: u32, + follow_symlink: bool, +) -> Result { + let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))? + .into_string() + .map_err(|_| SystemError::EINVAL)?; + + let open_flags: FileMode = FileMode::from_bits(o_flags).ok_or(SystemError::EINVAL)?; + let mode = ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?; + return do_sys_open( + AtFlags::AT_FDCWD.bits(), + &path, + open_flags, + mode, + follow_symlink, + ); +} diff --git a/kernel/src/filesystem/vfs/syscall/sys_close.rs b/kernel/src/filesystem/vfs/syscall/sys_close.rs new file mode 100644 index 00000000..6c3fd164 --- /dev/null +++ b/kernel/src/filesystem/vfs/syscall/sys_close.rs @@ -0,0 +1,54 @@ +//! System call handler for closing files. + +use alloc::string::ToString; + +use crate::arch::syscall::nr::SYS_CLOSE; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use alloc::vec::Vec; +use system_error::SystemError; + +/// Handler for the `close` system call. +pub struct SysCloseHandle; + +impl Syscall for SysCloseHandle { + /// Returns the number of arguments this syscall takes (1). + fn num_args(&self) -> usize { + 1 + } + + /// Handles the close syscall by extracting arguments and calling `do_close`. + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let fd = Self::fd(args); + do_close(fd) + } + /// Formats the syscall arguments for display/debugging purposes. + fn entry_format(&self, args: &[usize]) -> Vec { + vec![FormattedSyscallParam::new("fd", Self::fd(args).to_string())] + } +} + +impl SysCloseHandle { + /// Extracts the file descriptor (fd) argument from syscall parameters. + fn fd(args: &[usize]) -> i32 { + args[0] as i32 + } +} + +syscall_table_macros::declare_syscall!(SYS_CLOSE, SysCloseHandle); + +/// Close a file descriptor +/// +/// # Arguments +/// - `fd`: The file descriptor to close +/// +/// # Returns +/// Returns Ok(0) on success, or Err(SystemError) on failure +pub(super) fn do_close(fd: i32) -> Result { + let binding = ProcessManager::current_pcb().fd_table(); + let mut fd_table_guard = binding.write(); + let _file = fd_table_guard.drop_fd(fd)?; + drop(fd_table_guard); + Ok(0) +} diff --git a/kernel/src/filesystem/vfs/syscall/sys_fstat.rs b/kernel/src/filesystem/vfs/syscall/sys_fstat.rs new file mode 100644 index 00000000..b6cf6d9a --- /dev/null +++ b/kernel/src/filesystem/vfs/syscall/sys_fstat.rs @@ -0,0 +1,47 @@ +//! System call handler for opening files. + +use system_error::SystemError; + +use crate::arch::syscall::nr::SYS_FSTAT; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; + +use alloc::string::ToString; +use alloc::vec::Vec; + +pub struct SysFstatHandle; + +impl Syscall for SysFstatHandle { + /// Returns the number of arguments this syscall takes. + fn num_args(&self) -> usize { + 2 + } + + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let fd = Self::fd(args); + let usr_kstat = Self::usr_kstat(args); + crate::syscall::Syscall::newfstat(fd, usr_kstat) + } + + /// Formats the syscall arguments for display/debugging purposes. + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("fd", Self::fd(args).to_string()), + FormattedSyscallParam::new("statbuf", format!("{:#x}", Self::usr_kstat(args))), + ] + } +} + +impl SysFstatHandle { + /// Extracts the fd argument from syscall parameters. + fn fd(args: &[usize]) -> i32 { + args[0] as i32 + } + + /// Extracts the usr_kstat argument from syscall parameters. + fn usr_kstat(args: &[usize]) -> usize { + args[1] + } +} + +syscall_table_macros::declare_syscall!(SYS_FSTAT, SysFstatHandle); diff --git a/kernel/src/filesystem/vfs/syscall/sys_ioctl.rs b/kernel/src/filesystem/vfs/syscall/sys_ioctl.rs new file mode 100644 index 00000000..c97de172 --- /dev/null +++ b/kernel/src/filesystem/vfs/syscall/sys_ioctl.rs @@ -0,0 +1,77 @@ +//! System call handler for ioctls. + +use crate::arch::syscall::nr::SYS_IOCTL; +use crate::process::ProcessManager; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; +use system_error::SystemError; + +use alloc::string::ToString; +use alloc::vec::Vec; + +/// Handler for the `ioctl` system call. +pub struct SysIoctlHandle; + +impl Syscall for SysIoctlHandle { + /// Returns the number of arguments this syscall takes (3). + fn num_args(&self) -> usize { + 3 + } + + /// Sends a command to the device corresponding to the file descriptor. + /// + /// # Arguments + /// + /// * `fd` - File descriptor number + /// * `cmd` - Device-dependent request code + /// + /// # Returns + /// + /// * `Ok(usize)` - On success, returns 0 + /// * `Err(SystemError)` - On failure, returns a POSIX error code + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let fd = Self::fd(args); + let cmd = Self::cmd(args); + let data = Self::data(args); + + let binding = ProcessManager::current_pcb().fd_table(); + let fd_table_guard = binding.read(); + + let file = fd_table_guard + .get_file_by_fd(fd as i32) + .ok_or(SystemError::EBADF)?; + + // drop guard 以避免无法调度的问题 + drop(fd_table_guard); + let r = file.inode().ioctl(cmd, data, &file.private_data.lock()); + return r; + } + + /// Formats the syscall arguments for display/debugging purposes. + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("fd", Self::fd(args).to_string()), + FormattedSyscallParam::new("cmd", format!("{:#x}", Self::cmd(args))), + FormattedSyscallParam::new("data", format!("{:#x}", Self::data(args))), + ] + } +} + +impl SysIoctlHandle { + /// Extracts the file descriptor argument from syscall parameters. + fn fd(args: &[usize]) -> usize { + args[0] + } + + /// Extracts the command argument from syscall parameters. + fn cmd(args: &[usize]) -> u32 { + args[1] as u32 + } + + /// Extracts the data argument from syscall parameters. + fn data(args: &[usize]) -> usize { + args[2] + } +} + +syscall_table_macros::declare_syscall!(SYS_IOCTL, SysIoctlHandle); diff --git a/kernel/src/filesystem/vfs/syscall/sys_lstat.rs b/kernel/src/filesystem/vfs/syscall/sys_lstat.rs new file mode 100644 index 00000000..2d345024 --- /dev/null +++ b/kernel/src/filesystem/vfs/syscall/sys_lstat.rs @@ -0,0 +1,64 @@ +//! System call handler for opening files. + +use system_error::SystemError; + +use defer::defer; + +use crate::arch::syscall::nr::SYS_LSTAT; +use crate::filesystem::vfs::file::FileMode; +use crate::filesystem::vfs::syscall::sys_close::do_close; +use crate::filesystem::vfs::ModeType; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; + +use alloc::vec::Vec; + +pub struct SysLstatHandle; + +impl Syscall for SysLstatHandle { + /// Returns the number of arguments this syscall takes. + fn num_args(&self) -> usize { + 2 + } + + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let path = Self::path(args); + let usr_kstat = Self::usr_kstat(args); + + let fd = super::open_utils::do_open( + path, + FileMode::O_RDONLY.bits(), + ModeType::empty().bits(), + false, + )?; + + defer!({ + do_close(fd as i32).ok(); + }); + crate::syscall::Syscall::newfstat(fd as i32, usr_kstat)?; + + return Ok(0); + } + + /// Formats the syscall arguments for display/debugging purposes. + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("path", format!("{:#x}", Self::path(args) as usize)), + FormattedSyscallParam::new("statbuf", format!("{:#x}", Self::usr_kstat(args))), + ] + } +} + +impl SysLstatHandle { + /// Extracts the path argument from syscall parameters. + fn path(args: &[usize]) -> *const u8 { + args[0] as *const u8 + } + + /// Extracts the usr_kstat argument from syscall parameters. + fn usr_kstat(args: &[usize]) -> usize { + args[1] + } +} + +syscall_table_macros::declare_syscall!(SYS_LSTAT, SysLstatHandle); diff --git a/kernel/src/filesystem/vfs/syscall/sys_open.rs b/kernel/src/filesystem/vfs/syscall/sys_open.rs new file mode 100644 index 00000000..68f4ad92 --- /dev/null +++ b/kernel/src/filesystem/vfs/syscall/sys_open.rs @@ -0,0 +1,57 @@ +//! System call handler for opening files. + +use system_error::SystemError; + +use crate::arch::syscall::nr::SYS_OPEN; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; + +use alloc::string::ToString; +use alloc::vec::Vec; + +/// Handler for the `open` system call. +pub struct SysOpenHandle; + +impl Syscall for SysOpenHandle { + /// Returns the number of arguments this syscall takes (3). + fn num_args(&self) -> usize { + 3 + } + + /// Handles the open syscall by extracting arguments and calling `do_open`. + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let path = Self::path(args); + let flags = Self::flags(args); + let mode = Self::mode(args); + + super::open_utils::do_open(path, flags, mode, true) + } + + /// Formats the syscall arguments for display/debugging purposes. + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("path", format!("{:#x}", Self::path(args) as usize)), + FormattedSyscallParam::new("flags", Self::flags(args).to_string()), + FormattedSyscallParam::new("mode", Self::mode(args).to_string()), + ] + } +} + +impl SysOpenHandle { + /// Extracts the path argument from syscall parameters. + fn path(args: &[usize]) -> *const u8 { + args[0] as *const u8 + } + + /// Extracts the flags argument from syscall parameters. + fn flags(args: &[usize]) -> u32 { + args[1] as u32 + } + + /// Extracts the mode argument from syscall parameters. + fn mode(args: &[usize]) -> u32 { + args[2] as u32 + } +} + +syscall_table_macros::declare_syscall!(SYS_OPEN, SysOpenHandle); diff --git a/kernel/src/filesystem/vfs/syscall/sys_stat.rs b/kernel/src/filesystem/vfs/syscall/sys_stat.rs new file mode 100644 index 00000000..71005814 --- /dev/null +++ b/kernel/src/filesystem/vfs/syscall/sys_stat.rs @@ -0,0 +1,65 @@ +//! System call handler for opening files. + +use system_error::SystemError; + +use defer::defer; + +use crate::arch::syscall::nr::SYS_STAT; +use crate::filesystem::vfs::file::FileMode; +use crate::filesystem::vfs::syscall::sys_close::do_close; +use crate::filesystem::vfs::ModeType; +use crate::syscall::table::FormattedSyscallParam; +use crate::syscall::table::Syscall; + +use alloc::vec::Vec; + +pub struct SysStatHandle; + +impl Syscall for SysStatHandle { + /// Returns the number of arguments this syscall takes. + fn num_args(&self) -> usize { + 2 + } + + fn handle(&self, args: &[usize], _from_user: bool) -> Result { + let path = Self::path(args); + let usr_kstat = Self::usr_kstat(args); + + let fd = super::open_utils::do_open( + path, + FileMode::O_RDONLY.bits(), + ModeType::empty().bits(), + true, + )?; + + defer!({ + do_close(fd as i32).ok(); + }); + + crate::syscall::Syscall::newfstat(fd as i32, usr_kstat)?; + + return Ok(0); + } + + /// Formats the syscall arguments for display/debugging purposes. + fn entry_format(&self, args: &[usize]) -> Vec { + vec![ + FormattedSyscallParam::new("path", format!("{:#x}", Self::path(args) as usize)), + FormattedSyscallParam::new("statbuf", format!("{:#x}", Self::usr_kstat(args))), + ] + } +} + +impl SysStatHandle { + /// Extracts the path argument from syscall parameters. + fn path(args: &[usize]) -> *const u8 { + args[0] as *const u8 + } + + /// Extracts the usr_kstat argument from syscall parameters. + fn usr_kstat(args: &[usize]) -> usize { + args[1] + } +} + +syscall_table_macros::declare_syscall!(SYS_STAT, SysStatHandle); diff --git a/kernel/src/net/syscall.rs b/kernel/src/net/syscall.rs index 7f841313..6a9cb92b 100644 --- a/kernel/src/net/syscall.rs +++ b/kernel/src/net/syscall.rs @@ -7,8 +7,11 @@ use system_error::SystemError; use crate::{ filesystem::vfs::{ + fcntl::AtFlags, file::{File, FileMode}, iov::{IoVec, IoVecs}, + open::do_sys_open, + syscall::ModeType, FileType, }, libs::spinlock::SpinLockGuard, @@ -591,7 +594,13 @@ impl SockAddr { .to_str() .map_err(|_| SystemError::EINVAL)?; - let fd = Syscall::open(path.as_ptr(), FileMode::O_RDWR.bits(), 0o755, true)?; + let fd = do_sys_open( + AtFlags::AT_FDCWD.bits(), + path, + FileMode::O_RDWR, + ModeType::S_IWUGO | ModeType::S_IRUGO, + true, + )?; let binding = ProcessManager::current_pcb().fd_table(); let fd_table_guard = binding.read(); diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 079c60c9..a0d85856 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -116,14 +116,6 @@ impl Syscall { SYS_PUT_STRING => { Self::put_string(args[0] as *const u8, args[1] as u32, args[2] as u32) } - #[cfg(target_arch = "x86_64")] - SYS_OPEN => { - let path = args[0] as *const u8; - let flags = args[1] as u32; - let mode = args[2] as u32; - - Self::open(path, flags, mode, true) - } #[cfg(target_arch = "x86_64")] SYS_RENAME => { @@ -164,10 +156,6 @@ impl Syscall { Self::openat(dirfd, path, flags, mode, true) } - SYS_CLOSE => { - let fd = args[0]; - Self::close(fd) - } SYS_LSEEK => { let fd = args[0] as i32; @@ -202,13 +190,6 @@ impl Syscall { Self::pwrite(fd, buf, len, offset) } - SYS_IOCTL => { - let fd = args[0]; - let cmd = args[1]; - let data = args[2]; - Self::ioctl(fd, cmd as u32, data) - } - #[cfg(target_arch = "x86_64")] SYS_FORK => Self::fork(frame), #[cfg(target_arch = "x86_64")] @@ -664,12 +645,6 @@ impl Syscall { SYS_GETPPID => Self::getppid().map(|pid| pid.into()), - #[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))] - SYS_FSTAT => { - let fd = args[0] as i32; - Self::fstat(fd, args[1]) - } - SYS_FCNTL => { let fd = args[0] as i32; let cmd: Option = @@ -767,18 +742,6 @@ impl Syscall { SYS_SET_TID_ADDRESS => Self::set_tid_address(args[0]), - #[cfg(target_arch = "x86_64")] - SYS_LSTAT => { - let path = args[0] as *const u8; - Self::lstat(path, args[1]) - } - - #[cfg(target_arch = "x86_64")] - SYS_STAT => { - let path = args[0] as *const u8; - Self::stat(path, args[1]) - } - SYS_STATFS => { let path = args[0] as *const u8; let statfs = args[1] as *mut PosixStatfs;