Add statfs and fstatfs syscall
This commit is contained in:
parent
f2968799ae
commit
789b57c6f7
2
deps/sefs
vendored
2
deps/sefs
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 633060491f1e2a5c61cd331520c83d588eb5926b
|
Subproject commit 6df33e6e415be7b17d6d46babf74ef15c044fba9
|
@ -95,6 +95,10 @@ pub trait File: Debug + Sync + Send + Any {
|
|||||||
return_op_unsupported_error!("fallocate")
|
return_op_unsupported_error!("fallocate")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fs(&self) -> Result<Arc<dyn FileSystem>> {
|
||||||
|
return_op_unsupported_error!("fs")
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: remove this function after all users of this code are removed
|
// TODO: remove this function after all users of this code are removed
|
||||||
fn poll(&self) -> Result<(crate::net::PollEventFlags)> {
|
fn poll(&self) -> Result<(crate::net::PollEventFlags)> {
|
||||||
return_op_unsupported_error!("poll")
|
return_op_unsupported_error!("poll")
|
||||||
|
@ -3,9 +3,11 @@ use super::*;
|
|||||||
pub use self::chdir::do_chdir;
|
pub use self::chdir::do_chdir;
|
||||||
pub use self::getcwd::do_getcwd;
|
pub use self::getcwd::do_getcwd;
|
||||||
pub use self::mount::do_mount_rootfs;
|
pub use self::mount::do_mount_rootfs;
|
||||||
|
pub use self::statfs::{do_fstatfs, do_statfs, Statfs};
|
||||||
pub use self::sync::do_sync;
|
pub use self::sync::do_sync;
|
||||||
|
|
||||||
mod chdir;
|
mod chdir;
|
||||||
mod getcwd;
|
mod getcwd;
|
||||||
mod mount;
|
mod mount;
|
||||||
|
mod statfs;
|
||||||
mod sync;
|
mod sync;
|
||||||
|
80
src/libos/src/fs/fs_ops/statfs.rs
Normal file
80
src/libos/src/fs/fs_ops/statfs.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
use super::*;
|
||||||
|
use rcore_fs::vfs::FsInfo;
|
||||||
|
|
||||||
|
pub fn do_fstatfs(fd: FileDesc) -> Result<Statfs> {
|
||||||
|
debug!("fstatfs: fd: {}", fd);
|
||||||
|
|
||||||
|
let file_ref = current!().file(fd)?;
|
||||||
|
let statfs = Statfs::from(file_ref.fs()?.info());
|
||||||
|
trace!("fstatfs result: {:?}", statfs);
|
||||||
|
Ok(statfs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_statfs(path: &str) -> Result<Statfs> {
|
||||||
|
debug!("statfs: path: {:?}", path);
|
||||||
|
|
||||||
|
let inode = {
|
||||||
|
let current = current!();
|
||||||
|
let fs = current.fs().read().unwrap();
|
||||||
|
fs.lookup_inode(path)?
|
||||||
|
};
|
||||||
|
let statfs = Statfs::from(inode.fs().info());
|
||||||
|
trace!("statfs result: {:?}", statfs);
|
||||||
|
Ok(statfs)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Statfs {
|
||||||
|
/// Type of filesystem
|
||||||
|
f_type: usize,
|
||||||
|
/// 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: [i32; 2],
|
||||||
|
/// Maximum length of filenames
|
||||||
|
f_namelen: usize,
|
||||||
|
/// Fragment size
|
||||||
|
f_frsize: usize,
|
||||||
|
/// Mount flags of filesystem
|
||||||
|
f_flags: usize,
|
||||||
|
/// Padding bytes reserved for future use
|
||||||
|
f_spare: [usize; 4],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<FsInfo> for Statfs {
|
||||||
|
fn from(info: FsInfo) -> Self {
|
||||||
|
Self {
|
||||||
|
f_type: match info.magic {
|
||||||
|
// The "/dev" and "/dev/shm" are tmpfs on Linux, so we transform the
|
||||||
|
// magic number to TMPFS_MAGIC.
|
||||||
|
rcore_fs_ramfs::RAMFS_MAGIC | rcore_fs_devfs::DEVFS_MAGIC => {
|
||||||
|
const TMPFS_MAGIC: usize = 0x0102_1994;
|
||||||
|
TMPFS_MAGIC
|
||||||
|
}
|
||||||
|
val => val,
|
||||||
|
},
|
||||||
|
f_bsize: info.bsize,
|
||||||
|
f_blocks: info.blocks,
|
||||||
|
f_bfree: info.bfree,
|
||||||
|
f_bavail: info.bavail,
|
||||||
|
f_files: info.files,
|
||||||
|
f_ffree: info.ffree,
|
||||||
|
f_fsid: [0i32; 2],
|
||||||
|
f_namelen: info.namemax,
|
||||||
|
f_frsize: info.frsize,
|
||||||
|
f_flags: 0,
|
||||||
|
f_spare: [0usize; 4],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -36,7 +36,8 @@ impl FileSystem for HostFS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn info(&self) -> FsInfo {
|
fn info(&self) -> FsInfo {
|
||||||
unimplemented!()
|
warn!("HostFS: FsInfo is unimplemented");
|
||||||
|
Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +221,10 @@ impl File for INodeFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fs(&self) -> Result<Arc<dyn FileSystem>> {
|
||||||
|
Ok(self.inode.fs())
|
||||||
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ pub use self::file_ops::{
|
|||||||
IfConf, IoctlCmd, Stat, StatusFlags, StructuredIoctlArgType, StructuredIoctlNum,
|
IfConf, IoctlCmd, Stat, StatusFlags, StructuredIoctlArgType, StructuredIoctlNum,
|
||||||
};
|
};
|
||||||
pub use self::file_table::{FileDesc, FileTable, FileTableEvent, FileTableNotifier};
|
pub use self::file_table::{FileDesc, FileTable, FileTableEvent, FileTableNotifier};
|
||||||
|
pub use self::fs_ops::Statfs;
|
||||||
pub use self::fs_view::FsView;
|
pub use self::fs_view::FsView;
|
||||||
pub use self::host_fd::HostFd;
|
pub use self::host_fd::HostFd;
|
||||||
pub use self::inode_file::{AsINodeFile, INodeExt, INodeFile};
|
pub use self::inode_file::{AsINodeFile, INodeExt, INodeFile};
|
||||||
|
@ -16,6 +16,9 @@ mod pid_inode;
|
|||||||
mod proc_inode;
|
mod proc_inode;
|
||||||
mod self_inode;
|
mod self_inode;
|
||||||
|
|
||||||
|
// Same with the procfs on Linux
|
||||||
|
const PROC_SUPER_MAGIC: usize = 0x9fa0;
|
||||||
|
|
||||||
/// Proc file system
|
/// Proc file system
|
||||||
pub struct ProcFS {
|
pub struct ProcFS {
|
||||||
root: Arc<Dir<LockedProcRootINode>>,
|
root: Arc<Dir<LockedProcRootINode>>,
|
||||||
@ -33,14 +36,15 @@ impl FileSystem for ProcFS {
|
|||||||
|
|
||||||
fn info(&self) -> vfs::FsInfo {
|
fn info(&self) -> vfs::FsInfo {
|
||||||
vfs::FsInfo {
|
vfs::FsInfo {
|
||||||
bsize: 0,
|
magic: PROC_SUPER_MAGIC,
|
||||||
frsize: 0,
|
bsize: 4096,
|
||||||
|
frsize: 4096,
|
||||||
blocks: 0,
|
blocks: 0,
|
||||||
bfree: 0,
|
bfree: 0,
|
||||||
bavail: 0,
|
bavail: 0,
|
||||||
files: 0,
|
files: 0,
|
||||||
ffree: 0,
|
ffree: 0,
|
||||||
namemax: 0,
|
namemax: 255,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,3 +553,24 @@ pub fn do_fallocate(fd: FileDesc, mode: u32, offset: off_t, len: off_t) -> Resul
|
|||||||
file_ops::do_fallocate(fd, mode, offset as u64, len as u64)?;
|
file_ops::do_fallocate(fd, mode, offset as u64, len as u64)?;
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn do_fstatfs(fd: FileDesc, statfs_buf: *mut Statfs) -> Result<isize> {
|
||||||
|
from_user::check_mut_ptr(statfs_buf)?;
|
||||||
|
|
||||||
|
let statfs = fs_ops::do_fstatfs(fd)?;
|
||||||
|
unsafe {
|
||||||
|
statfs_buf.write(statfs);
|
||||||
|
}
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_statfs(path: *const i8, statfs_buf: *mut Statfs) -> Result<isize> {
|
||||||
|
let path = from_user::clone_cstring_safely(path)?
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
let statfs = fs_ops::do_statfs(&path)?;
|
||||||
|
unsafe {
|
||||||
|
statfs_buf.write(statfs);
|
||||||
|
}
|
||||||
|
Ok(0)
|
||||||
|
}
|
||||||
|
@ -24,12 +24,12 @@ use crate::exception::do_handle_exception;
|
|||||||
use crate::fs::{
|
use crate::fs::{
|
||||||
do_access, do_chdir, do_chmod, do_chown, do_close, do_dup, do_dup2, do_dup3, do_eventfd,
|
do_access, do_chdir, do_chmod, do_chown, do_close, do_dup, do_dup2, do_dup3, do_eventfd,
|
||||||
do_eventfd2, do_faccessat, do_fallocate, do_fchmod, do_fchmodat, do_fchown, do_fchownat,
|
do_eventfd2, do_faccessat, do_fallocate, do_fchmod, do_fchmodat, do_fchown, do_fchownat,
|
||||||
do_fcntl, do_fdatasync, do_fstat, do_fstatat, do_fsync, do_ftruncate, do_getcwd, do_getdents,
|
do_fcntl, do_fdatasync, do_fstat, do_fstatat, do_fstatfs, do_fsync, do_ftruncate, do_getcwd,
|
||||||
do_getdents64, do_ioctl, do_lchown, do_link, do_linkat, do_lseek, do_lstat, do_mkdir,
|
do_getdents, do_getdents64, do_ioctl, do_lchown, do_link, do_linkat, do_lseek, do_lstat,
|
||||||
do_mkdirat, do_mount_rootfs, do_open, do_openat, do_pipe, do_pipe2, do_pread, do_pwrite,
|
do_mkdir, do_mkdirat, do_mount_rootfs, do_open, do_openat, do_pipe, do_pipe2, do_pread,
|
||||||
do_read, do_readlink, do_readlinkat, do_readv, do_rename, do_renameat, do_rmdir, do_sendfile,
|
do_pwrite, do_read, do_readlink, do_readlinkat, do_readv, do_rename, do_renameat, do_rmdir,
|
||||||
do_stat, do_symlink, do_symlinkat, do_sync, do_truncate, do_unlink, do_unlinkat, do_write,
|
do_sendfile, do_stat, do_statfs, do_symlink, do_symlinkat, do_sync, do_truncate, do_unlink,
|
||||||
do_writev, iovec_t, File, FileDesc, FileRef, HostStdioFds, Stat,
|
do_unlinkat, do_write, do_writev, iovec_t, File, FileDesc, FileRef, HostStdioFds, Stat, Statfs,
|
||||||
};
|
};
|
||||||
use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t};
|
use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t};
|
||||||
use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t};
|
use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t};
|
||||||
@ -222,8 +222,8 @@ macro_rules! process_syscall_table_with_callback {
|
|||||||
(Uselib = 134) => handle_unsupported(),
|
(Uselib = 134) => handle_unsupported(),
|
||||||
(Personality = 135) => handle_unsupported(),
|
(Personality = 135) => handle_unsupported(),
|
||||||
(Ustat = 136) => handle_unsupported(),
|
(Ustat = 136) => handle_unsupported(),
|
||||||
(Statfs = 137) => handle_unsupported(),
|
(Statfs = 137) => do_statfs(path: *const i8, statfs_buf: *mut Statfs),
|
||||||
(Fstatfs = 138) => handle_unsupported(),
|
(Fstatfs = 138) => do_fstatfs(fd: FileDesc, statfs_buf: *mut Statfs),
|
||||||
(SysFs = 139) => handle_unsupported(),
|
(SysFs = 139) => handle_unsupported(),
|
||||||
(Getpriority = 140) => handle_unsupported(),
|
(Getpriority = 140) => handle_unsupported(),
|
||||||
(Setpriority = 141) => handle_unsupported(),
|
(Setpriority = 141) => handle_unsupported(),
|
||||||
|
@ -18,7 +18,8 @@ TEST_DEPS := client data_sink naughty_child
|
|||||||
TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe time \
|
TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe time \
|
||||||
truncate readdir mkdir open stat link symlink chmod chown tls pthread uname rlimit \
|
truncate readdir mkdir open stat link symlink chmod chown tls pthread uname rlimit \
|
||||||
server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
|
server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
|
||||||
ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait spawn_attribute
|
ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait \
|
||||||
|
spawn_attribute statfs
|
||||||
# Benchmarks: need to be compiled and run by bench-% target
|
# Benchmarks: need to be compiled and run by bench-% target
|
||||||
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/vfs.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -142,6 +143,22 @@ static int test_read_from_proc_cpuinfo() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PROC_SUPER_MAGIC 0x9fa0
|
||||||
|
static int test_statfs() {
|
||||||
|
const char *file_path = "/proc/cpuinfo";
|
||||||
|
struct statfs statfs_buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = statfs(file_path, &statfs_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to statfs the file");
|
||||||
|
}
|
||||||
|
if (statfs_buf.f_type != PROC_SUPER_MAGIC) {
|
||||||
|
THROW_ERROR("failed to check the f_type");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Test suite main
|
// Test suite main
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@ -154,6 +171,7 @@ static test_case_t test_cases[] = {
|
|||||||
TEST_CASE(test_read_from_proc_self_cmdline),
|
TEST_CASE(test_read_from_proc_self_cmdline),
|
||||||
TEST_CASE(test_read_from_proc_meminfo),
|
TEST_CASE(test_read_from_proc_meminfo),
|
||||||
TEST_CASE(test_read_from_proc_cpuinfo),
|
TEST_CASE(test_read_from_proc_cpuinfo),
|
||||||
|
TEST_CASE(test_statfs),
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
|
5
test/statfs/Makefile
Normal file
5
test/statfs/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include ../test_common.mk
|
||||||
|
|
||||||
|
EXTRA_C_FLAGS :=
|
||||||
|
EXTRA_LINK_FLAGS :=
|
||||||
|
BIN_ARGS :=
|
117
test/statfs/main.c
Normal file
117
test/statfs/main.c
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include <sys/vfs.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "test_fs.h"
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Helper function
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int create_file(const char *file_path) {
|
||||||
|
int fd;
|
||||||
|
int flags = O_RDONLY | O_CREAT | O_TRUNC;
|
||||||
|
int mode = 00666;
|
||||||
|
|
||||||
|
fd = open(file_path, flags, mode);
|
||||||
|
if (fd < 0) {
|
||||||
|
THROW_ERROR("failed to create a file");
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_file(const char *file_path) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = unlink(file_path);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to unlink the created file");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test cases for statfs
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static int __test_statfs(const char *file_path, unsigned long expected_type) {
|
||||||
|
struct statfs statfs_buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = statfs(file_path, &statfs_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to statfs the file");
|
||||||
|
}
|
||||||
|
if (statfs_buf.f_type != expected_type) {
|
||||||
|
THROW_ERROR("failed to check the f_type");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __test_fstatfs(const char *file_path, unsigned long expected_type) {
|
||||||
|
struct statfs statfs_buf;
|
||||||
|
int fd, ret;
|
||||||
|
int flags = O_RDONLY;
|
||||||
|
|
||||||
|
fd = open(file_path, flags);
|
||||||
|
if (fd < 0) {
|
||||||
|
THROW_ERROR("failed to open file");
|
||||||
|
}
|
||||||
|
ret = fstatfs(fd, &statfs_buf);
|
||||||
|
if (ret < 0) {
|
||||||
|
THROW_ERROR("failed to fstatfs the file");
|
||||||
|
}
|
||||||
|
if (statfs_buf.f_type != expected_type) {
|
||||||
|
THROW_ERROR("failed to check the f_type");
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int(*test_statfs_func_t)(const char *, unsigned long);
|
||||||
|
|
||||||
|
static int test_statfs_framework(test_statfs_func_t fn, const char *file_path,
|
||||||
|
unsigned long expected_type) {
|
||||||
|
if (create_file(file_path) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fn(file_path, expected_type) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (remove_file(file_path) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UNIONFS_MAGIC 0x2f8dbe2f
|
||||||
|
#define TMPFS_MAGIC 0x01021994
|
||||||
|
|
||||||
|
static int test_statfs_on_root() {
|
||||||
|
const char *file_path = "/root/test_fs_statfs.txt";
|
||||||
|
unsigned long expected_type = UNIONFS_MAGIC;
|
||||||
|
return test_statfs_framework(__test_statfs, file_path, expected_type) +
|
||||||
|
test_statfs_framework(__test_fstatfs, file_path, expected_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_statfs_on_dev_shm() {
|
||||||
|
const char *file_path = "/dev/shm/test_fs_statfs.txt";
|
||||||
|
unsigned long expected_type = TMPFS_MAGIC;
|
||||||
|
return test_statfs_framework(__test_statfs, file_path, expected_type) +
|
||||||
|
test_statfs_framework(__test_fstatfs, file_path, expected_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Test suite main
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static test_case_t test_cases[] = {
|
||||||
|
TEST_CASE(test_statfs_on_root),
|
||||||
|
TEST_CASE(test_statfs_on_dev_shm),
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, const char *argv[]) {
|
||||||
|
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user