From 743344e3fc448f6540503532d1fbc43d12ae3b51 Mon Sep 17 00:00:00 2001 From: LI Qing Date: Mon, 3 Jul 2023 13:29:02 +0800 Subject: [PATCH] Add support for statfs and fstatfs --- regression/syscall_test/Makefile | 2 +- .../syscall_test/blocklists/statfs_test | 4 + services/libs/jinux-std/src/fs/fs_resolver.rs | 4 +- services/libs/jinux-std/src/fs/procfs/mod.rs | 2 +- services/libs/jinux-std/src/fs/ramfs/fs.rs | 2 +- services/libs/jinux-std/src/fs/ramfs/mod.rs | 3 +- .../jinux-std/src/fs/utils/dentry_cache.rs | 7 +- services/libs/jinux-std/src/fs/utils/fs.rs | 10 +- services/libs/jinux-std/src/fs/utils/vnode.rs | 8 +- services/libs/jinux-std/src/syscall/chdir.rs | 2 +- .../libs/jinux-std/src/syscall/getdents64.rs | 2 +- services/libs/jinux-std/src/syscall/mod.rs | 6 ++ services/libs/jinux-std/src/syscall/statfs.rs | 93 +++++++++++++++++++ 13 files changed, 128 insertions(+), 17 deletions(-) create mode 100644 regression/syscall_test/blocklists/statfs_test create mode 100644 services/libs/jinux-std/src/syscall/statfs.rs diff --git a/regression/syscall_test/Makefile b/regression/syscall_test/Makefile index 4b13e9ca..280d4e2e 100644 --- a/regression/syscall_test/Makefile +++ b/regression/syscall_test/Makefile @@ -1,4 +1,4 @@ -TESTS ?= open_test read_test +TESTS ?= open_test read_test statfs_test MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) CUR_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) diff --git a/regression/syscall_test/blocklists/statfs_test b/regression/syscall_test/blocklists/statfs_test new file mode 100644 index 00000000..1734cd55 --- /dev/null +++ b/regression/syscall_test/blocklists/statfs_test @@ -0,0 +1,4 @@ +StatfsTest.InternalTmpfs +StatfsTest.InternalDevShm +FstatfsTest.InternalTmpfs +FstatfsTest.InternalDevShm \ No newline at end of file diff --git a/services/libs/jinux-std/src/fs/fs_resolver.rs b/services/libs/jinux-std/src/fs/fs_resolver.rs index 59f1c43e..388f0080 100644 --- a/services/libs/jinux-std/src/fs/fs_resolver.rs +++ b/services/libs/jinux-std/src/fs/fs_resolver.rs @@ -262,7 +262,7 @@ impl FsResolver { let inode_handle = file_table .get_file(fd)? .downcast_ref::() - .ok_or(Error::with_message(Errno::EBADE, "not inode"))?; + .ok_or(Error::with_message(Errno::EBADF, "not inode"))?; Ok(inode_handle.dentry().clone()) } @@ -381,7 +381,7 @@ impl<'a> FsPath<'a> { FsPathInner::CwdRelative(path) } } else { - return_errno_with_message!(Errno::EINVAL, "invalid dirfd number"); + return_errno_with_message!(Errno::EBADF, "invalid dirfd number"); }; Ok(Self { diff --git a/services/libs/jinux-std/src/fs/procfs/mod.rs b/services/libs/jinux-std/src/fs/procfs/mod.rs index b4caf417..8fdd7281 100644 --- a/services/libs/jinux-std/src/fs/procfs/mod.rs +++ b/services/libs/jinux-std/src/fs/procfs/mod.rs @@ -14,7 +14,7 @@ mod self_; mod template; /// Magic number. -const PROC_MAGIC: usize = 0x9fa0; +const PROC_MAGIC: u64 = 0x9fa0; /// Root Inode ID. const PROC_ROOT_INO: usize = 1; /// Block size. diff --git a/services/libs/jinux-std/src/fs/ramfs/fs.rs b/services/libs/jinux-std/src/fs/ramfs/fs.rs index fe3d763a..28a7a90b 100644 --- a/services/libs/jinux-std/src/fs/ramfs/fs.rs +++ b/services/libs/jinux-std/src/fs/ramfs/fs.rs @@ -11,7 +11,7 @@ use super::*; use crate::fs::device::Device; use crate::fs::utils::{ DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata, - Poller, SuperBlock, + Poller, SuperBlock, NAME_MAX, }; /// A volatile file system whose data and metadata exists only in memory. diff --git a/services/libs/jinux-std/src/fs/ramfs/mod.rs b/services/libs/jinux-std/src/fs/ramfs/mod.rs index 18a8e77e..9760fd5f 100644 --- a/services/libs/jinux-std/src/fs/ramfs/mod.rs +++ b/services/libs/jinux-std/src/fs/ramfs/mod.rs @@ -4,7 +4,6 @@ pub use fs::RamFS; mod fs; -const RAMFS_MAGIC: usize = 0x0102_1994; +const RAMFS_MAGIC: u64 = 0x0102_1994; const BLOCK_SIZE: usize = 4096; -const NAME_MAX: usize = 255; const ROOT_INO: usize = 1; diff --git a/services/libs/jinux-std/src/fs/utils/dentry_cache.rs b/services/libs/jinux-std/src/fs/utils/dentry_cache.rs index afdfb6f3..e140a840 100644 --- a/services/libs/jinux-std/src/fs/utils/dentry_cache.rs +++ b/services/libs/jinux-std/src/fs/utils/dentry_cache.rs @@ -4,7 +4,7 @@ use crate::prelude::*; use alloc::string::String; use core::time::Duration; -use super::{InodeMode, InodeType, Metadata, Vnode, NAME_MAX}; +use super::{FileSystem, InodeMode, InodeType, Metadata, Vnode, NAME_MAX}; lazy_static! { static ref DCACHE: Mutex>> = Mutex::new(BTreeMap::new()); @@ -233,6 +233,11 @@ impl Dentry { Ok(()) } + /// Get the filesystem the inode belongs to + pub fn fs(&self) -> Arc { + self.vnode.fs() + } + /// Get the inode metadata pub fn inode_metadata(&self) -> Metadata { self.vnode.metadata() diff --git a/services/libs/jinux-std/src/fs/utils/fs.rs b/services/libs/jinux-std/src/fs/utils/fs.rs index c2c2bd2b..1eb5f056 100644 --- a/services/libs/jinux-std/src/fs/utils/fs.rs +++ b/services/libs/jinux-std/src/fs/utils/fs.rs @@ -7,21 +7,21 @@ use crate::prelude::*; #[derive(Debug, Clone)] pub struct SuperBlock { - pub magic: usize, + pub magic: u64, pub bsize: usize, pub blocks: usize, pub bfree: usize, pub bavail: usize, pub files: usize, pub ffree: usize, - pub fsid: usize, + pub fsid: u64, pub namelen: usize, pub frsize: usize, - pub flags: usize, + pub flags: u64, } impl SuperBlock { - pub fn new(magic: usize, block_size: usize, name_len: usize) -> Self { + pub fn new(magic: u64, block_size: usize, name_max_len: usize) -> Self { Self { magic, bsize: block_size, @@ -31,7 +31,7 @@ impl SuperBlock { files: 0, ffree: 0, fsid: 0, - namelen: 255, + namelen: name_max_len, frsize: block_size, flags: 0, } diff --git a/services/libs/jinux-std/src/fs/utils/vnode.rs b/services/libs/jinux-std/src/fs/utils/vnode.rs index 8a75d8c1..643f26cc 100644 --- a/services/libs/jinux-std/src/fs/utils/vnode.rs +++ b/services/libs/jinux-std/src/fs/utils/vnode.rs @@ -1,6 +1,6 @@ use super::{ - DirentVisitor, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata, PageCache, - Poller, + DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata, + PageCache, Poller, }; use crate::fs::device::Device; use crate::prelude::*; @@ -202,6 +202,10 @@ impl Vnode { self.inner.read().inode.ioctl(cmd, arg) } + pub fn fs(&self) -> Arc { + self.inner.read().inode.fs() + } + pub fn metadata(&self) -> Metadata { self.inner.read().inode.metadata() } diff --git a/services/libs/jinux-std/src/syscall/chdir.rs b/services/libs/jinux-std/src/syscall/chdir.rs index 31d1e0dc..fffaa12a 100644 --- a/services/libs/jinux-std/src/syscall/chdir.rs +++ b/services/libs/jinux-std/src/syscall/chdir.rs @@ -41,7 +41,7 @@ pub fn sys_fchdir(fd: FileDescripter) -> Result { let file = file_table.get_file(fd)?; let inode_handle = file .downcast_ref::() - .ok_or(Error::with_message(Errno::EBADE, "not inode"))?; + .ok_or(Error::with_message(Errno::EBADF, "not inode"))?; inode_handle.dentry().clone() }; if dentry.inode_type() != InodeType::Dir { diff --git a/services/libs/jinux-std/src/syscall/getdents64.rs b/services/libs/jinux-std/src/syscall/getdents64.rs index cf9e2c78..c959e33e 100644 --- a/services/libs/jinux-std/src/syscall/getdents64.rs +++ b/services/libs/jinux-std/src/syscall/getdents64.rs @@ -29,7 +29,7 @@ pub fn sys_getdents64( }; let inode_handle = file .downcast_ref::() - .ok_or(Error::with_message(Errno::EBADE, "not inode"))?; + .ok_or(Error::with_message(Errno::EBADF, "not inode"))?; if inode_handle.dentry().inode_type() != InodeType::Dir { return_errno!(Errno::ENOTDIR); } diff --git a/services/libs/jinux-std/src/syscall/mod.rs b/services/libs/jinux-std/src/syscall/mod.rs index ed8f17b5..ce2f46f5 100644 --- a/services/libs/jinux-std/src/syscall/mod.rs +++ b/services/libs/jinux-std/src/syscall/mod.rs @@ -56,6 +56,7 @@ use crate::syscall::set_robust_list::sys_set_robust_list; use crate::syscall::set_tid_address::sys_set_tid_address; use crate::syscall::setpgid::sys_setpgid; use crate::syscall::stat::{sys_fstat, sys_fstatat, sys_lstat, sys_stat}; +use crate::syscall::statfs::{sys_fstatfs, sys_statfs}; use crate::syscall::symlink::{sys_symlink, sys_symlinkat}; use crate::syscall::tgkill::sys_tgkill; use crate::syscall::time::sys_time; @@ -150,6 +151,7 @@ mod setsockopt; mod shutdown; mod socket; mod stat; +mod statfs; mod symlink; mod tgkill; mod time; @@ -259,6 +261,8 @@ define_syscall_nums!( SYS_SETPGID = 109, SYS_GETPPID = 110, SYS_GETPGRP = 111, + SYS_STATFS = 137, + SYS_FSTATFS = 138, SYS_PRCTL = 157, SYS_ARCH_PRCTL = 158, SYS_GETTID = 186, @@ -411,6 +415,8 @@ pub fn syscall_dispatch( SYS_SETPGID => syscall_handler!(2, sys_setpgid, args), SYS_GETPPID => syscall_handler!(0, sys_getppid), SYS_GETPGRP => syscall_handler!(0, sys_getpgrp), + SYS_STATFS => syscall_handler!(2, sys_statfs, args), + SYS_FSTATFS => syscall_handler!(2, sys_fstatfs, args), SYS_PRCTL => syscall_handler!(5, sys_prctl, args), SYS_ARCH_PRCTL => syscall_handler!(2, sys_arch_prctl, args, context), SYS_GETTID => syscall_handler!(0, sys_gettid), diff --git a/services/libs/jinux-std/src/syscall/statfs.rs b/services/libs/jinux-std/src/syscall/statfs.rs new file mode 100644 index 00000000..dbaa1324 --- /dev/null +++ b/services/libs/jinux-std/src/syscall/statfs.rs @@ -0,0 +1,93 @@ +use crate::fs::{ + file_table::FileDescripter, + fs_resolver::FsPath, + inode_handle::InodeHandle, + utils::{SuperBlock, PATH_MAX}, +}; +use crate::log_syscall_entry; +use crate::prelude::*; +use crate::util::{read_cstring_from_user, write_val_to_user}; + +use super::SyscallReturn; +use super::{SYS_FSTATFS, SYS_STATFS}; + +pub fn sys_statfs(path_ptr: Vaddr, statfs_buf_ptr: Vaddr) -> Result { + log_syscall_entry!(SYS_STATFS); + let path = read_cstring_from_user(path_ptr, PATH_MAX)?; + debug!("path = {:?}, statfs_buf_ptr = 0x{:x}", path, statfs_buf_ptr,); + + let current = current!(); + let dentry = { + let path = path.to_string_lossy(); + let fs_path = FsPath::try_from(path.as_ref())?; + current.fs().read().lookup(&fs_path)? + }; + let statfs = Statfs::from(dentry.fs().sb()); + write_val_to_user(statfs_buf_ptr, &statfs)?; + Ok(SyscallReturn::Return(0)) +} + +pub fn sys_fstatfs(fd: FileDescripter, statfs_buf_ptr: Vaddr) -> Result { + log_syscall_entry!(SYS_FSTATFS); + debug!("fd = {}, statfs_buf_addr = 0x{:x}", fd, statfs_buf_ptr); + + let current = current!(); + let file_table = current.file_table().lock(); + let file = file_table.get_file(fd)?; + let inode_handle = file + .downcast_ref::() + .ok_or(Error::with_message(Errno::EBADF, "not inode"))?; + let dentry = inode_handle.dentry(); + let statfs = Statfs::from(dentry.fs().sb()); + write_val_to_user(statfs_buf_ptr, &statfs)?; + Ok(SyscallReturn::Return(0)) +} + +/// FS Stat +#[derive(Debug, Clone, Copy, Pod, Default)] +#[repr(C)] +struct Statfs { + /// Type of filesystem + f_type: u64, + /// Optimal transfer block size + f_bsize: usize, + /// Total data blocks in filesystem + f_blocks: usize, + /// Free blocks in filesystem + f_bfree: usize, + /// Free blocks available to unprivileged user + f_bavail: usize, + /// Total inodes in filesystem + f_files: usize, + /// Free inodes in filesystem + f_ffree: usize, + /// Filesystem ID + f_fsid: u64, + /// Maximum length of filenames + f_namelen: usize, + /// Fragment size + f_frsize: usize, + /// Mount flags of filesystem + f_flags: u64, + /// Padding bytes reserved for future use + f_spare: [u64; 4], +} + +impl From for Statfs { + fn from(sb: SuperBlock) -> Self { + Self { + f_type: sb.magic, + f_bsize: sb.bsize, + f_blocks: sb.blocks, + f_bfree: sb.bfree, + f_bavail: sb.bavail, + f_files: sb.files, + f_ffree: sb.ffree, + f_fsid: sb.fsid, + f_namelen: sb.namelen, + f_frsize: sb.frsize, + f_flags: sb.flags, + f_spare: [0u64; 4], + } + } +}