Modify the statfs on SEFS or UnionFS with ocall

This commit is contained in:
LI Qing 2021-09-03 10:51:10 +08:00 committed by Zongmin.Gu
parent 16e8b12e4d
commit 85d6977118
5 changed files with 82 additions and 4 deletions

@ -153,6 +153,8 @@ enclave {
void occlum_ocall_sync(void);
int occlum_ocall_statfs([in, string] const char* path, [out] struct statfs* buf) propagate_errno;
void* occlum_ocall_posix_memalign(size_t alignment, size_t size);
void occlum_ocall_free([user_check] void* ptr);

@ -19,7 +19,7 @@ struct occlum_stdio_fds {
int stderr_fd;
};
typedef struct _timespec{
struct _timespec{
time_t tv_sec;
syscall_slong_t tv_nsec;
};
@ -34,4 +34,19 @@ typedef struct {
unsigned long fds_bits[FD_SETSIZE / 8 / sizeof(long)];
} fd_set;
struct statfs {
unsigned long f_type;
unsigned long f_bsize;
unsigned long f_blocks;
unsigned long f_bfree;
unsigned long f_bavail;
unsigned long f_files;
unsigned long f_ffree;
int f_fsid[2];
unsigned long f_namelen;
unsigned long f_frsize;
unsigned long f_flags;
unsigned long f_spare[4];
};
#endif /* __OCCLUM_EDL_TYPES_H__ */

@ -1,11 +1,15 @@
use super::*;
use rcore_fs::vfs::FsInfo;
use std::ffi::CString;
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());
let statfs = {
let fs_info = file_ref.fs()?.info();
do_statfs_inner(fs_info)?
};
trace!("fstatfs result: {:?}", statfs);
Ok(statfs)
}
@ -18,12 +22,28 @@ pub fn do_statfs(path: &str) -> Result<Statfs> {
let fs = current.fs().read().unwrap();
fs.lookup_inode(path)?
};
let statfs = Statfs::from(inode.fs().info());
let statfs = {
let fs_info = inode.fs().info();
do_statfs_inner(fs_info)?
};
trace!("statfs result: {:?}", statfs);
Ok(statfs)
}
#[derive(Debug)]
fn do_statfs_inner(fs_info: FsInfo) -> Result<Statfs> {
let statfs = if fs_info.magic == rcore_fs_unionfs::UNIONFS_MAGIC
|| fs_info.magic == rcore_fs_sefs::SEFS_MAGIC as usize
{
let mut host_statfs = host_statfs()?;
host_statfs.f_type = fs_info.magic;
host_statfs
} else {
Statfs::from(fs_info)
};
Ok(statfs)
}
#[derive(Default, Debug)]
#[repr(C)]
pub struct Statfs {
/// Type of filesystem
@ -52,6 +72,21 @@ pub struct Statfs {
f_spare: [usize; 4],
}
impl Statfs {
fn validate(&self) -> Result<()> {
if self.f_blocks < self.f_bfree || self.f_blocks < self.f_bavail {
return_errno!(EINVAL, "invalid blocks");
}
if self.f_files < self.f_ffree {
return_errno!(EINVAL, "invalid inodes");
}
if self.f_bsize == 0 || self.f_namelen == 0 || self.f_frsize == 0 {
return_errno!(EINVAL, "invalid non-zero fields");
}
Ok(())
}
}
impl From<FsInfo> for Statfs {
fn from(info: FsInfo) -> Self {
Self {
@ -78,3 +113,23 @@ impl From<FsInfo> for Statfs {
}
}
}
fn host_statfs() -> Result<Statfs> {
extern "C" {
fn occlum_ocall_statfs(ret: *mut i32, path: *const i8, buf: *mut Statfs) -> sgx_status_t;
}
let mut ret: i32 = 0;
let mut statfs: Statfs = Default::default();
let host_dir = unsafe { CString::new(INSTANCE_DIR.as_bytes()).unwrap() };
let sgx_status = unsafe { occlum_ocall_statfs(&mut ret, host_dir.as_ptr(), &mut statfs) };
assert!(sgx_status == sgx_status_t::SGX_SUCCESS);
assert!(ret == 0 || libc::errno() == Errno::EINTR as i32);
if ret != 0 {
return_errno!(EINTR, "failed to get host statfs");
}
// do sanity check
statfs.validate().expect("invalid statfs");
Ok(statfs)
}

@ -5,6 +5,7 @@
#include <sys/select.h> // import fd_set
#include <sys/time.h> // import struct timeval
#include <sys/uio.h> // import struct iovec
#include <sys/vfs.h> // import struct statfs
#include <occlum_pal_api.h> // import occlum_stdio_fds
#endif /* __OCCLUM_EDL_TYPES__ */

@ -3,6 +3,7 @@
#include <net/if.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/vfs.h>
void occlum_ocall_sync(void) {
sync();
@ -41,3 +42,7 @@ int occlum_ocall_ioctl(int fd, int request, void *arg, size_t len) {
return ioctl(fd, request, arg);
}
int occlum_ocall_statfs(const char *path, struct statfs *buf) {
return statfs(path, buf);
}