From 0bbfec0f24110cb529e664bf9861e0ea037cd1c5 Mon Sep 17 00:00:00 2001 From: "Zheng, Qi" Date: Thu, 16 Feb 2023 11:13:07 +0800 Subject: [PATCH] [libos] Add syscall pwritev and preadv --- demos/linux-ltp/syscalls-occlum | 4 +-- src/libos/src/fs/file.rs | 8 +++++ src/libos/src/fs/file_ops/mod.rs | 4 +-- src/libos/src/fs/file_ops/read.rs | 6 ++++ src/libos/src/fs/file_ops/write.rs | 6 ++++ src/libos/src/fs/inode_file.rs | 38 ++++++++++++++++++++++ src/libos/src/fs/syscalls.rs | 52 +++++++++++++++++++++++++++--- src/libos/src/syscall/mod.rs | 16 ++++----- 8 files changed, 118 insertions(+), 16 deletions(-) diff --git a/demos/linux-ltp/syscalls-occlum b/demos/linux-ltp/syscalls-occlum index 01db3769..0ea09dd3 100644 --- a/demos/linux-ltp/syscalls-occlum +++ b/demos/linux-ltp/syscalls-occlum @@ -1052,8 +1052,8 @@ pwrite04_64 pwrite04_64 pwritev01 pwritev01 pwritev01_64 pwritev01_64 -pwritev02 pwritev02 -pwritev02_64 pwritev02_64 +# pwritev02 pwritev02 +# pwritev02_64 pwritev02_64 pwritev03 pwritev03 pwritev03_64 pwritev03_64 diff --git a/src/libos/src/fs/file.rs b/src/libos/src/fs/file.rs index 84f27413..43d7a6f3 100644 --- a/src/libos/src/fs/file.rs +++ b/src/libos/src/fs/file.rs @@ -43,6 +43,14 @@ pub trait File: Debug + Sync + Send + Any { return_op_unsupported_error!("seek") } + fn preadv(&self, bufs: &mut [&mut [u8]], offset: usize) -> Result { + return_op_unsupported_error!("preadv") + } + + fn pwritev(&self, bufs: &[&[u8]], offset: usize) -> Result { + return_op_unsupported_error!("pwritev") + } + fn position(&self) -> Result { return_op_unsupported_error!("position") } diff --git a/src/libos/src/fs/file_ops/mod.rs b/src/libos/src/fs/file_ops/mod.rs index e64d924b..0d237dad 100644 --- a/src/libos/src/fs/file_ops/mod.rs +++ b/src/libos/src/fs/file_ops/mod.rs @@ -21,7 +21,7 @@ pub use self::link::{do_linkat, LinkFlags}; pub use self::lseek::do_lseek; pub use self::mkdir::do_mkdirat; pub use self::open::do_openat; -pub use self::read::{do_pread, do_read, do_readv}; +pub use self::read::{do_pread, do_preadv, do_read, do_readv}; pub use self::rename::do_renameat; pub use self::rmdir::do_rmdir; pub use self::sendfile::do_sendfile; @@ -32,7 +32,7 @@ pub use self::unlink::{do_unlinkat, UnlinkFlags}; pub use self::utimes::{ do_utimes_fd, do_utimes_path, get_utimes, utimbuf_t, Utime, UtimeFlags, UTIME_OMIT, }; -pub use self::write::{do_pwrite, do_write, do_writev}; +pub use self::write::{do_pwrite, do_pwritev, do_write, do_writev}; mod access; mod chmod; diff --git a/src/libos/src/fs/file_ops/read.rs b/src/libos/src/fs/file_ops/read.rs index 7af358fe..1b7e2aec 100644 --- a/src/libos/src/fs/file_ops/read.rs +++ b/src/libos/src/fs/file_ops/read.rs @@ -20,3 +20,9 @@ pub fn do_pread(fd: FileDesc, buf: &mut [u8], offset: off_t) -> Result { let file_ref = current!().file(fd)?; file_ref.read_at(offset as usize, buf) } + +pub fn do_preadv(fd: FileDesc, bufs: &mut [&mut [u8]], offset: off_t) -> Result { + debug!("preadv: fd: {}, offset {}", fd, offset); + let file_ref = current!().file(fd)?; + file_ref.preadv(bufs, offset as usize) +} diff --git a/src/libos/src/fs/file_ops/write.rs b/src/libos/src/fs/file_ops/write.rs index 34e736a9..c281570a 100644 --- a/src/libos/src/fs/file_ops/write.rs +++ b/src/libos/src/fs/file_ops/write.rs @@ -20,3 +20,9 @@ pub fn do_pwrite(fd: FileDesc, buf: &[u8], offset: off_t) -> Result { let file_ref = current!().file(fd)?; file_ref.write_at(offset as usize, buf) } + +pub fn do_pwritev(fd: FileDesc, bufs: &[&[u8]], offset: off_t) -> Result { + debug!("pwritev: fd: {}, offset {}", fd, offset); + let file_ref = current!().file(fd)?; + file_ref.pwritev(bufs, offset as usize) +} diff --git a/src/libos/src/fs/inode_file.rs b/src/libos/src/fs/inode_file.rs index 81454ded..95c8b9a2 100644 --- a/src/libos/src/fs/inode_file.rs +++ b/src/libos/src/fs/inode_file.rs @@ -113,6 +113,44 @@ impl File for INodeFile { Ok(*offset as i64) } + fn preadv(&self, bufs: &mut [&mut [u8]], offset: usize) -> Result { + if !self.access_mode.readable() { + return_errno!(EBADF, "File not readable"); + } + let mut offset = offset; + let mut total_len = 0; + for buf in bufs { + match self.inode.read_at(offset, buf) { + Ok(len) => { + total_len += len; + offset += len; + } + Err(_) if total_len != 0 => break, + Err(e) => return Err(e.into()), + } + } + Ok(total_len) + } + + fn pwritev(&self, bufs: &[&[u8]], offset: usize) -> Result { + if !self.access_mode.writable() { + return_errno!(EBADF, "File not writable"); + } + let mut offset = offset; + let mut total_len = 0; + for buf in bufs { + match self.inode.write_at(offset, buf) { + Ok(len) => { + total_len += len; + offset += len; + } + Err(_) if total_len != 0 => break, + Err(e) => return Err(e.into()), + } + } + Ok(total_len) + } + fn position(&self) -> Result { let offset = self.offset.lock().unwrap(); Ok(*offset as off_t) diff --git a/src/libos/src/fs/syscalls.rs b/src/libos/src/fs/syscalls.rs index 33bc24ba..04d2f658 100644 --- a/src/libos/src/fs/syscalls.rs +++ b/src/libos/src/fs/syscalls.rs @@ -148,7 +148,12 @@ pub fn do_write(fd: FileDesc, buf: *const u8, size: usize) -> Result { Ok(len as isize) } -pub fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result { +fn do_writev_offset( + fd: FileDesc, + iov: *const iovec_t, + count: i32, + offset: Option, +) -> Result { let count = { if count < 0 { return_errno!(EINVAL, "Invalid count of iovec"); @@ -169,11 +174,25 @@ pub fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result }; let bufs = &bufs_vec[..]; - let len = file_ops::do_writev(fd, bufs)?; + let len = if let Some(offset) = offset { + file_ops::do_pwritev(fd, bufs, offset)? + } else { + file_ops::do_writev(fd, bufs)? + }; + Ok(len as isize) } -pub fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result { +pub fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result { + do_writev_offset(fd, iov, count, None) +} + +fn do_readv_offset( + fd: FileDesc, + iov: *mut iovec_t, + count: i32, + offset: Option, +) -> Result { let count = { if count < 0 { return_errno!(EINVAL, "Invalid count of iovec"); @@ -194,10 +213,19 @@ pub fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result { }; let bufs = &mut bufs_vec[..]; - let len = file_ops::do_readv(fd, bufs)?; + let len = if let Some(offset) = offset { + file_ops::do_preadv(fd, bufs, offset)? + } else { + file_ops::do_readv(fd, bufs)? + }; + Ok(len as isize) } +pub fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result { + do_readv_offset(fd, iov, count, None) +} + pub fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: off_t) -> Result { let safe_buf = { from_user::check_mut_array(buf, size)?; @@ -207,6 +235,14 @@ pub fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: off_t) -> Resul Ok(len as isize) } +pub fn do_preadv(fd: FileDesc, iov: *mut iovec_t, count: i32, offset: off_t) -> Result { + if offset < 0 { + return_errno!(EINVAL, "Invalid offset"); + } + + do_readv_offset(fd, iov, count, Some(offset)) +} + pub fn do_pwrite(fd: FileDesc, buf: *const u8, size: usize, offset: off_t) -> Result { let safe_buf = { from_user::check_array(buf, size)?; @@ -216,6 +252,14 @@ pub fn do_pwrite(fd: FileDesc, buf: *const u8, size: usize, offset: off_t) -> Re Ok(len as isize) } +pub fn do_pwritev(fd: FileDesc, iov: *const iovec_t, count: i32, offset: off_t) -> Result { + if offset < 0 { + return_errno!(EINVAL, "Invalid offset"); + } + + do_writev_offset(fd, iov, count, Some(offset)) +} + pub fn do_fstat(fd: FileDesc, stat_buf: *mut Stat) -> Result { from_user::check_mut_ptr(stat_buf)?; diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 9f7a5e78..2bea12a2 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -27,12 +27,12 @@ use crate::fs::{ do_fchown, do_fchownat, do_fcntl, do_fdatasync, do_flock, do_fstat, do_fstatat, do_fstatfs, do_fsync, do_ftruncate, do_futimesat, do_getcwd, do_getdents, do_getdents64, do_ioctl, do_lchown, do_link, do_linkat, do_lseek, do_lstat, do_mkdir, do_mkdirat, do_mount, - 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, do_stat, - do_statfs, do_symlink, do_symlinkat, do_sync, do_timerfd_create, do_timerfd_gettime, - do_timerfd_settime, do_truncate, do_umask, do_umount, do_unlink, do_unlinkat, do_utime, - do_utimensat, do_utimes, do_write, do_writev, iovec_t, utimbuf_t, AsTimer, File, FileDesc, - FileRef, HostStdioFds, Stat, Statfs, + do_mount_rootfs, do_open, do_openat, do_pipe, do_pipe2, do_pread, do_preadv, do_pwrite, + do_pwritev, do_read, do_readlink, do_readlinkat, do_readv, do_rename, do_renameat, do_rmdir, + do_sendfile, do_stat, do_statfs, do_symlink, do_symlinkat, do_sync, do_timerfd_create, + do_timerfd_gettime, do_timerfd_settime, do_truncate, do_umask, do_umount, do_unlink, + do_unlinkat, do_utime, do_utimensat, do_utimes, do_write, do_writev, iovec_t, utimbuf_t, + AsTimer, File, FileDesc, FileRef, HostStdioFds, Stat, Statfs, }; use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t}; use crate::ipc::{do_shmat, do_shmctl, do_shmdt, do_shmget, key_t, shmids_t}; @@ -388,8 +388,8 @@ macro_rules! process_syscall_table_with_callback { (Dup3 = 292) => do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32), (Pipe2 = 293) => do_pipe2(fds_u: *mut i32, flags: u32), (InotifyInit1 = 294) => handle_unsupported(), - (Preadv = 295) => handle_unsupported(), - (Pwritev = 296) => handle_unsupported(), + (Preadv = 295) => do_preadv(fd: FileDesc, iov: *mut iovec_t, count: i32, offset: off_t), + (Pwritev = 296) => do_pwritev(fd: FileDesc, iov: *const iovec_t, count: i32, offset: off_t), (RtTgsigqueueinfo = 297) => handle_unsupported(), (PerfEventOpen = 298) => handle_unsupported(), (Recvmmsg = 299) => handle_unsupported(),