[libos] Add syscall pwritev and preadv

This commit is contained in:
Zheng, Qi 2023-02-16 11:13:07 +08:00 committed by volcano
parent 0f33e93fd5
commit 0bbfec0f24
8 changed files with 118 additions and 16 deletions

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

@ -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<usize> {
return_op_unsupported_error!("preadv")
}
fn pwritev(&self, bufs: &[&[u8]], offset: usize) -> Result<usize> {
return_op_unsupported_error!("pwritev")
}
fn position(&self) -> Result<off_t> {
return_op_unsupported_error!("position")
}

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

@ -20,3 +20,9 @@ pub fn do_pread(fd: FileDesc, buf: &mut [u8], offset: off_t) -> Result<usize> {
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<usize> {
debug!("preadv: fd: {}, offset {}", fd, offset);
let file_ref = current!().file(fd)?;
file_ref.preadv(bufs, offset as usize)
}

@ -20,3 +20,9 @@ pub fn do_pwrite(fd: FileDesc, buf: &[u8], offset: off_t) -> Result<usize> {
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<usize> {
debug!("pwritev: fd: {}, offset {}", fd, offset);
let file_ref = current!().file(fd)?;
file_ref.pwritev(bufs, offset as usize)
}

@ -113,6 +113,44 @@ impl File for INodeFile {
Ok(*offset as i64)
}
fn preadv(&self, bufs: &mut [&mut [u8]], offset: usize) -> Result<usize> {
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<usize> {
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<off_t> {
let offset = self.offset.lock().unwrap();
Ok(*offset as off_t)

@ -148,7 +148,12 @@ pub fn do_write(fd: FileDesc, buf: *const u8, size: usize) -> Result<isize> {
Ok(len as isize)
}
pub fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result<isize> {
fn do_writev_offset(
fd: FileDesc,
iov: *const iovec_t,
count: i32,
offset: Option<off_t>,
) -> Result<isize> {
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<isize>
};
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<isize> {
pub fn do_writev(fd: FileDesc, iov: *const iovec_t, count: i32) -> Result<isize> {
do_writev_offset(fd, iov, count, None)
}
fn do_readv_offset(
fd: FileDesc,
iov: *mut iovec_t,
count: i32,
offset: Option<off_t>,
) -> Result<isize> {
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<isize> {
};
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<isize> {
do_readv_offset(fd, iov, count, None)
}
pub fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: off_t) -> Result<isize> {
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<isize> {
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<isize> {
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<isize> {
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<isize> {
from_user::check_mut_ptr(stat_buf)?;

@ -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(),