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)))
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
.get_file(fd)?
.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())
}
@ -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 {

View File

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

View File

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

View File

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

View File

@ -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<BTreeMap<DentryKey, Arc<Dentry>>> = Mutex::new(BTreeMap::new());
@ -233,6 +233,11 @@ impl Dentry {
Ok(())
}
/// Get the filesystem the inode belongs to
pub fn fs(&self) -> Arc<dyn FileSystem> {
self.vnode.fs()
}
/// Get the inode metadata
pub fn inode_metadata(&self) -> Metadata {
self.vnode.metadata()

View File

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

View File

@ -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<dyn FileSystem> {
self.inner.read().inode.fs()
}
pub fn metadata(&self) -> 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 inode_handle = file
.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()
};
if dentry.inode_type() != InodeType::Dir {

View File

@ -29,7 +29,7 @@ pub fn sys_getdents64(
};
let inode_handle = file
.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 {
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::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),

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],
}
}
}