Add support for statfs and fstatfs

This commit is contained in:
LI Qing 2023-07-03 13:29:02 +08:00 committed by Tate, Hongliang Tian
parent 9f1680d0f3
commit 743344e3fc
13 changed files with 128 additions and 17 deletions

View File

@ -1,4 +1,4 @@
TESTS ?= open_test read_test TESTS ?= open_test read_test statfs_test
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
CUR_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH))) CUR_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH)))

View File

@ -0,0 +1,4 @@
StatfsTest.InternalTmpfs
StatfsTest.InternalDevShm
FstatfsTest.InternalTmpfs
FstatfsTest.InternalDevShm

View File

@ -262,7 +262,7 @@ impl FsResolver {
let inode_handle = file_table let inode_handle = file_table
.get_file(fd)? .get_file(fd)?
.downcast_ref::<InodeHandle>() .downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EBADE, "not inode"))?; .ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
Ok(inode_handle.dentry().clone()) Ok(inode_handle.dentry().clone())
} }
@ -381,7 +381,7 @@ impl<'a> FsPath<'a> {
FsPathInner::CwdRelative(path) FsPathInner::CwdRelative(path)
} }
} else { } else {
return_errno_with_message!(Errno::EINVAL, "invalid dirfd number"); return_errno_with_message!(Errno::EBADF, "invalid dirfd number");
}; };
Ok(Self { Ok(Self {

View File

@ -14,7 +14,7 @@ mod self_;
mod template; mod template;
/// Magic number. /// Magic number.
const PROC_MAGIC: usize = 0x9fa0; const PROC_MAGIC: u64 = 0x9fa0;
/// Root Inode ID. /// Root Inode ID.
const PROC_ROOT_INO: usize = 1; const PROC_ROOT_INO: usize = 1;
/// Block size. /// Block size.

View File

@ -11,7 +11,7 @@ use super::*;
use crate::fs::device::Device; use crate::fs::device::Device;
use crate::fs::utils::{ use crate::fs::utils::{
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata, 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. /// A volatile file system whose data and metadata exists only in memory.

View File

@ -4,7 +4,6 @@ pub use fs::RamFS;
mod fs; mod fs;
const RAMFS_MAGIC: usize = 0x0102_1994; const RAMFS_MAGIC: u64 = 0x0102_1994;
const BLOCK_SIZE: usize = 4096; const BLOCK_SIZE: usize = 4096;
const NAME_MAX: usize = 255;
const ROOT_INO: usize = 1; const ROOT_INO: usize = 1;

View File

@ -4,7 +4,7 @@ use crate::prelude::*;
use alloc::string::String; use alloc::string::String;
use core::time::Duration; use core::time::Duration;
use super::{InodeMode, InodeType, Metadata, Vnode, NAME_MAX}; use super::{FileSystem, InodeMode, InodeType, Metadata, Vnode, NAME_MAX};
lazy_static! { lazy_static! {
static ref DCACHE: Mutex<BTreeMap<DentryKey, Arc<Dentry>>> = Mutex::new(BTreeMap::new()); static ref DCACHE: Mutex<BTreeMap<DentryKey, Arc<Dentry>>> = Mutex::new(BTreeMap::new());
@ -233,6 +233,11 @@ impl Dentry {
Ok(()) Ok(())
} }
/// Get the filesystem the inode belongs to
pub fn fs(&self) -> Arc<dyn FileSystem> {
self.vnode.fs()
}
/// Get the inode metadata /// Get the inode metadata
pub fn inode_metadata(&self) -> Metadata { pub fn inode_metadata(&self) -> Metadata {
self.vnode.metadata() self.vnode.metadata()

View File

@ -7,21 +7,21 @@ use crate::prelude::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SuperBlock { pub struct SuperBlock {
pub magic: usize, pub magic: u64,
pub bsize: usize, pub bsize: usize,
pub blocks: usize, pub blocks: usize,
pub bfree: usize, pub bfree: usize,
pub bavail: usize, pub bavail: usize,
pub files: usize, pub files: usize,
pub ffree: usize, pub ffree: usize,
pub fsid: usize, pub fsid: u64,
pub namelen: usize, pub namelen: usize,
pub frsize: usize, pub frsize: usize,
pub flags: usize, pub flags: u64,
} }
impl SuperBlock { 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 { Self {
magic, magic,
bsize: block_size, bsize: block_size,
@ -31,7 +31,7 @@ impl SuperBlock {
files: 0, files: 0,
ffree: 0, ffree: 0,
fsid: 0, fsid: 0,
namelen: 255, namelen: name_max_len,
frsize: block_size, frsize: block_size,
flags: 0, flags: 0,
} }

View File

@ -1,6 +1,6 @@
use super::{ use super::{
DirentVisitor, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata, PageCache, DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoEvents, IoctlCmd, Metadata,
Poller, PageCache, Poller,
}; };
use crate::fs::device::Device; use crate::fs::device::Device;
use crate::prelude::*; use crate::prelude::*;
@ -202,6 +202,10 @@ impl Vnode {
self.inner.read().inode.ioctl(cmd, arg) self.inner.read().inode.ioctl(cmd, arg)
} }
pub fn fs(&self) -> Arc<dyn FileSystem> {
self.inner.read().inode.fs()
}
pub fn metadata(&self) -> Metadata { pub fn metadata(&self) -> Metadata {
self.inner.read().inode.metadata() self.inner.read().inode.metadata()
} }

View File

@ -41,7 +41,7 @@ pub fn sys_fchdir(fd: FileDescripter) -> Result<SyscallReturn> {
let file = file_table.get_file(fd)?; let file = file_table.get_file(fd)?;
let inode_handle = file let inode_handle = file
.downcast_ref::<InodeHandle>() .downcast_ref::<InodeHandle>()
.ok_or(Error::with_message(Errno::EBADE, "not inode"))?; .ok_or(Error::with_message(Errno::EBADF, "not inode"))?;
inode_handle.dentry().clone() inode_handle.dentry().clone()
}; };
if dentry.inode_type() != InodeType::Dir { if dentry.inode_type() != InodeType::Dir {

View File

@ -29,7 +29,7 @@ pub fn sys_getdents64(
}; };
let inode_handle = file let inode_handle = file
.downcast_ref::<InodeHandle>() .downcast_ref::<InodeHandle>()
.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 { if inode_handle.dentry().inode_type() != InodeType::Dir {
return_errno!(Errno::ENOTDIR); return_errno!(Errno::ENOTDIR);
} }

View File

@ -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::set_tid_address::sys_set_tid_address;
use crate::syscall::setpgid::sys_setpgid; use crate::syscall::setpgid::sys_setpgid;
use crate::syscall::stat::{sys_fstat, sys_fstatat, sys_lstat, sys_stat}; 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::symlink::{sys_symlink, sys_symlinkat};
use crate::syscall::tgkill::sys_tgkill; use crate::syscall::tgkill::sys_tgkill;
use crate::syscall::time::sys_time; use crate::syscall::time::sys_time;
@ -150,6 +151,7 @@ mod setsockopt;
mod shutdown; mod shutdown;
mod socket; mod socket;
mod stat; mod stat;
mod statfs;
mod symlink; mod symlink;
mod tgkill; mod tgkill;
mod time; mod time;
@ -259,6 +261,8 @@ define_syscall_nums!(
SYS_SETPGID = 109, SYS_SETPGID = 109,
SYS_GETPPID = 110, SYS_GETPPID = 110,
SYS_GETPGRP = 111, SYS_GETPGRP = 111,
SYS_STATFS = 137,
SYS_FSTATFS = 138,
SYS_PRCTL = 157, SYS_PRCTL = 157,
SYS_ARCH_PRCTL = 158, SYS_ARCH_PRCTL = 158,
SYS_GETTID = 186, SYS_GETTID = 186,
@ -411,6 +415,8 @@ pub fn syscall_dispatch(
SYS_SETPGID => syscall_handler!(2, sys_setpgid, args), SYS_SETPGID => syscall_handler!(2, sys_setpgid, args),
SYS_GETPPID => syscall_handler!(0, sys_getppid), SYS_GETPPID => syscall_handler!(0, sys_getppid),
SYS_GETPGRP => syscall_handler!(0, sys_getpgrp), 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_PRCTL => syscall_handler!(5, sys_prctl, args),
SYS_ARCH_PRCTL => syscall_handler!(2, sys_arch_prctl, args, context), SYS_ARCH_PRCTL => syscall_handler!(2, sys_arch_prctl, args, context),
SYS_GETTID => syscall_handler!(0, sys_gettid), SYS_GETTID => syscall_handler!(0, sys_gettid),

View File

@ -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<SyscallReturn> {
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<SyscallReturn> {
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::<InodeHandle>()
.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<SuperBlock> 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],
}
}
}