From be62e2c65d33c9bb9ff81c5fee5d86cb7d36cd99 Mon Sep 17 00:00:00 2001 From: LI Qing Date: Fri, 5 Feb 2021 14:58:11 +0800 Subject: [PATCH] Add posix_fallocate --- deps/sefs | 2 +- src/libos/src/error/to_errno.rs | 1 + src/libos/src/fs/file.rs | 4 +++ src/libos/src/fs/file_ops/fallocate.rs | 11 ++++++ src/libos/src/fs/file_ops/mod.rs | 2 ++ src/libos/src/fs/inode_file.rs | 5 +++ src/libos/src/fs/syscalls.rs | 16 +++++++++ src/libos/src/syscall/mod.rs | 6 ++-- test/file/main.c | 46 ++++++++++++++++++++++++++ 9 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 src/libos/src/fs/file_ops/fallocate.rs diff --git a/deps/sefs b/deps/sefs index 88784548..bb574e0c 160000 --- a/deps/sefs +++ b/deps/sefs @@ -1 +1 @@ -Subproject commit 88784548d5db1156f2d9e71f968d0d78fa7957db +Subproject commit bb574e0c0bb0a3034f1f4eb48b1d559fe84d2555 diff --git a/src/libos/src/error/to_errno.rs b/src/libos/src/error/to_errno.rs index 6ccc87a9..d205f04e 100644 --- a/src/libos/src/error/to_errno.rs +++ b/src/libos/src/error/to_errno.rs @@ -96,6 +96,7 @@ impl ToErrno for rcore_fs::vfs::FsError { FsError::NoIntegrity => EIO, FsError::PermError => EPERM, FsError::NameTooLong => ENAMETOOLONG, + FsError::FileTooBig => EFBIG, } } } diff --git a/src/libos/src/fs/file.rs b/src/libos/src/fs/file.rs index bb5ead4e..b60d0239 100644 --- a/src/libos/src/fs/file.rs +++ b/src/libos/src/fs/file.rs @@ -91,6 +91,10 @@ pub trait File: Debug + Sync + Send + Any { return_op_unsupported_error!("set_advisory_lock") } + fn fallocate(&self, _mode: u32, _offset: u64, _len: u64) -> Result<()> { + return_op_unsupported_error!("fallocate") + } + // TODO: remove this function after all users of this code are removed fn poll(&self) -> Result<(crate::net::PollEventFlags)> { return_op_unsupported_error!("poll") diff --git a/src/libos/src/fs/file_ops/fallocate.rs b/src/libos/src/fs/file_ops/fallocate.rs new file mode 100644 index 00000000..449f1e87 --- /dev/null +++ b/src/libos/src/fs/file_ops/fallocate.rs @@ -0,0 +1,11 @@ +use super::*; + +pub fn do_fallocate(fd: FileDesc, mode: u32, offset: u64, len: u64) -> Result<()> { + debug!( + "fallocate: fd: {}, mode: {}, offset: {}, len: {}", + fd, mode, offset, len + ); + let file_ref = current!().file(fd)?; + file_ref.fallocate(mode, offset, len)?; + Ok(()) +} diff --git a/src/libos/src/fs/file_ops/mod.rs b/src/libos/src/fs/file_ops/mod.rs index 6b6ad8ac..c641fd23 100644 --- a/src/libos/src/fs/file_ops/mod.rs +++ b/src/libos/src/fs/file_ops/mod.rs @@ -7,6 +7,7 @@ pub use self::chown::{do_fchown, do_fchownat, ChownFlags}; pub use self::close::do_close; pub use self::dirent::{do_getdents, do_getdents64}; pub use self::dup::{do_dup, do_dup2, do_dup3}; +pub use self::fallocate::do_fallocate; pub use self::fcntl::{do_fcntl, FcntlCmd}; pub use self::file_flags::{AccessMode, CreationFlags, StatusFlags}; pub use self::flock::{Flock, FlockType}; @@ -36,6 +37,7 @@ mod chown; mod close; mod dirent; mod dup; +mod fallocate; mod fcntl; mod file_flags; mod flock; diff --git a/src/libos/src/fs/inode_file.rs b/src/libos/src/fs/inode_file.rs index f2cf9ba0..bbbaf948 100644 --- a/src/libos/src/fs/inode_file.rs +++ b/src/libos/src/fs/inode_file.rs @@ -121,6 +121,11 @@ impl File for INodeFile { Ok(()) } + fn fallocate(&self, mode: u32, offset: u64, len: u64) -> Result<()> { + self.inode.fallocate(mode, offset, len)?; + Ok(()) + } + fn set_len(&self, len: u64) -> Result<()> { if !self.access_mode.writable() { return_errno!(EACCES, "File not writable. Can't set len."); diff --git a/src/libos/src/fs/syscalls.rs b/src/libos/src/fs/syscalls.rs index 852dd308..21996c8e 100644 --- a/src/libos/src/fs/syscalls.rs +++ b/src/libos/src/fs/syscalls.rs @@ -537,3 +537,19 @@ pub fn do_mount_rootfs( fs_ops::do_mount_rootfs(&user_config, &key)?; Ok(0) } + +pub fn do_fallocate(fd: FileDesc, mode: u32, offset: off_t, len: off_t) -> Result { + if offset < 0 || len <= 0 { + return_errno!( + EINVAL, + "offset was less than 0, or len was less than or equal to 0" + ); + } + // Current implementation is just the posix_fallocate + // TODO: Support more modes in fallocate + if mode != 0 { + return_errno!(ENOSYS, "unsupported mode"); + } + file_ops::do_fallocate(fd, mode, offset as u64, len as u64)?; + Ok(0) +} diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 7ad9af50..6479075f 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -23,8 +23,8 @@ use util::mem_util::from_user::*; use crate::exception::do_handle_exception; use crate::fs::{ do_access, do_chdir, do_chmod, do_chown, do_close, do_dup, do_dup2, do_dup3, do_eventfd, - do_eventfd2, do_faccessat, 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_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_getdents64, do_ioctl, do_lchown, do_link, do_linkat, do_lseek, do_lstat, do_mkdir, do_mkdirat, do_mount_rootfs, do_open, do_openat, do_pipe, do_pipe2, do_pread, do_pwrite, do_read, do_readlink, do_readlinkat, do_readv, do_rename, do_renameat, do_rmdir, do_sendfile, @@ -369,7 +369,7 @@ macro_rules! process_syscall_table_with_callback { (Signalfd = 282) => handle_unsupported(), (TimerfdCreate = 283) => handle_unsupported(), (Eventfd = 284) => do_eventfd(init_val: u32), - (Fallocate = 285) => handle_unsupported(), + (Fallocate = 285) => do_fallocate(fd: FileDesc, mode: u32, offset: off_t, len: off_t), (TimerfdSettime = 286) => handle_unsupported(), (TimerfdGettime = 287) => handle_unsupported(), (Accept4 = 288) => do_accept4(fd: c_int, addr: *mut libc::sockaddr, addr_len: *mut libc::socklen_t, flags: c_int), diff --git a/test/file/main.c b/test/file/main.c index a1860f81..a3dcc986 100644 --- a/test/file/main.c +++ b/test/file/main.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "test_fs.h" // ============================================================================ @@ -162,6 +163,46 @@ static int __test_lseek(const char *file_path) { return 0; } +static int __test_posix_fallocate(const char *file_path) { + int fd = open(file_path, O_RDWR); + if (fd < 0) { + THROW_ERROR("failed to open a file to read/write"); + } + off_t offset = -1; + off_t len = 100; + if (posix_fallocate(fd, offset, len) != EINVAL) { + THROW_ERROR("failed to call posix_fallocate with invalid offset"); + } + offset = 16; + len = 0; + if (posix_fallocate(fd, offset, len) != EINVAL) { + THROW_ERROR("failed to call posix_fallocate with invalid len"); + } + len = 48; + if (posix_fallocate(fd, offset, len) != 0) { + THROW_ERROR("failed to call posix_fallocate"); + } + struct stat stat_buf; + if (fstat(fd, &stat_buf) < 0) { + THROW_ERROR("failed to stat file"); + } + if (stat_buf.st_size < offset + len) { + THROW_ERROR("failed to check the len after posix_fallocate"); + } + + char *read_buf = malloc(stat_buf.st_size); + if (read_buf == NULL) { + THROW_ERROR("failed to malloc buf to read"); + } + if (read(fd, read_buf, stat_buf.st_size) != stat_buf.st_size) { + THROW_ERROR("failed to read correct size of fallocated file"); + } + + free(read_buf); + close(fd); + return 0; +} + typedef int(*test_file_func_t)(const char *); static int test_file_framework(test_file_func_t fn) { @@ -195,6 +236,10 @@ static int test_lseek() { return test_file_framework(__test_lseek); } +static int test_posix_fallocate() { + return test_file_framework(__test_posix_fallocate); +} + // ============================================================================ // Test suite main // ============================================================================ @@ -204,6 +249,7 @@ static test_case_t test_cases[] = { TEST_CASE(test_pwrite_pread), TEST_CASE(test_writev_readv), TEST_CASE(test_lseek), + TEST_CASE(test_posix_fallocate), }; int main(int argc, const char *argv[]) {