From c6854c5a97bd393d629177423386128c1c68eba0 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Thu, 28 Jan 2021 17:29:33 +0100 Subject: [PATCH] block_util: Simplify RAW synchronous implementation Using directly preadv and pwritev, we can simply use a RawFd instead of a file, and we don't need to use the more complex implementation from the qcow crate. Signed-off-by: Sebastien Boeuf --- block_util/src/raw_sync.rs | 105 +++++++++++++++----------- virtio-devices/src/seccomp_filters.rs | 2 + vmm/src/device_manager.rs | 2 +- vmm/src/seccomp_filters.rs | 2 + 4 files changed, 64 insertions(+), 47 deletions(-) diff --git a/block_util/src/raw_sync.rs b/block_util/src/raw_sync.rs index 1175d6c67..e6e090b7d 100644 --- a/block_util/src/raw_sync.rs +++ b/block_util/src/raw_sync.rs @@ -2,54 +2,49 @@ // // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause -use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileResult}; -use crate::{disk_size, fsync_sync, read_vectored_sync, write_vectored_sync}; -use qcow::RawFile; +use crate::async_io::{ + AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult, +}; use std::fs::File; -use std::sync::{Arc, Mutex}; +use std::io::{Seek, SeekFrom}; +use std::os::unix::io::{AsRawFd, RawFd}; use vmm_sys_util::eventfd::EventFd; pub struct RawFileDiskSync { - raw_file: RawFile, - semaphore: Arc>, + file: File, } impl RawFileDiskSync { - pub fn new(file: File, direct_io: bool) -> Self { - RawFileDiskSync { - raw_file: RawFile::new(file, direct_io), - semaphore: Arc::new(Mutex::new(())), - } + pub fn new(file: File) -> Self { + RawFileDiskSync { file } } } impl DiskFile for RawFileDiskSync { fn size(&mut self) -> DiskFileResult { - disk_size(&mut self.raw_file, &mut self.semaphore) + Ok(self + .file + .seek(SeekFrom::End(0)) + .map_err(DiskFileError::Size)? as u64) } fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult> { - Ok(Box::new(RawFileSync::new( - self.raw_file.clone(), - self.semaphore.clone(), - )) as Box) + Ok(Box::new(RawFileSync::new(self.file.as_raw_fd())) as Box) } } pub struct RawFileSync { - raw_file: RawFile, + fd: RawFd, eventfd: EventFd, completion_list: Vec<(u64, i32)>, - semaphore: Arc>, } impl RawFileSync { - pub fn new(raw_file: RawFile, semaphore: Arc>) -> Self { + pub fn new(fd: RawFd) -> Self { RawFileSync { - raw_file, + fd, eventfd: EventFd::new(libc::EFD_NONBLOCK).expect("Failed creating EventFd for RawFile"), completion_list: Vec::new(), - semaphore, } } } @@ -65,15 +60,22 @@ impl AsyncIo for RawFileSync { iovecs: Vec, user_data: u64, ) -> AsyncIoResult<()> { - read_vectored_sync( - offset, - iovecs, - user_data, - &mut self.raw_file, - &self.eventfd, - &mut self.completion_list, - &mut self.semaphore, - ) + let result = unsafe { + libc::preadv( + self.fd as libc::c_int, + iovecs.as_ptr() as *const libc::iovec, + iovecs.len() as libc::c_int, + offset, + ) + }; + if result < 0 { + return Err(AsyncIoError::ReadVectored(std::io::Error::last_os_error())); + } + + self.completion_list.push((user_data, result as i32)); + self.eventfd.write(1).unwrap(); + + Ok(()) } fn write_vectored( @@ -82,25 +84,36 @@ impl AsyncIo for RawFileSync { iovecs: Vec, user_data: u64, ) -> AsyncIoResult<()> { - write_vectored_sync( - offset, - iovecs, - user_data, - &mut self.raw_file, - &self.eventfd, - &mut self.completion_list, - &mut self.semaphore, - ) + let result = unsafe { + libc::pwritev( + self.fd as libc::c_int, + iovecs.as_ptr() as *const libc::iovec, + iovecs.len() as libc::c_int, + offset, + ) + }; + if result < 0 { + return Err(AsyncIoError::WriteVectored(std::io::Error::last_os_error())); + } + + self.completion_list.push((user_data, result as i32)); + self.eventfd.write(1).unwrap(); + + Ok(()) } fn fsync(&mut self, user_data: Option) -> AsyncIoResult<()> { - fsync_sync( - user_data, - &mut self.raw_file, - &self.eventfd, - &mut self.completion_list, - &mut self.semaphore, - ) + let result = unsafe { libc::fsync(self.fd as libc::c_int) }; + if result < 0 { + return Err(AsyncIoError::Fsync(std::io::Error::last_os_error())); + } + + if let Some(user_data) = user_data { + self.completion_list.push((user_data, result as i32)); + self.eventfd.write(1).unwrap(); + } + + Ok(()) } fn complete(&mut self) -> Vec<(u64, i32)> { diff --git a/virtio-devices/src/seccomp_filters.rs b/virtio-devices/src/seccomp_filters.rs index 1c68d6cb0..41dc73136 100644 --- a/virtio-devices/src/seccomp_filters.rs +++ b/virtio-devices/src/seccomp_filters.rs @@ -106,6 +106,8 @@ fn virtio_block_thread_rules() -> Result, Error> { allow_syscall(libc::SYS_openat), allow_syscall(libc::SYS_prctl), allow_syscall(libc::SYS_pread64), + allow_syscall(libc::SYS_preadv), + allow_syscall(libc::SYS_pwritev), allow_syscall(libc::SYS_read), allow_syscall(libc::SYS_rt_sigprocmask), allow_syscall(libc::SYS_sched_getaffinity), diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 321e00760..55953131e 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1686,7 +1686,7 @@ impl DeviceManager { Box::new(RawFileDisk::new(file)) as Box } else { info!("Using synchronous RAW disk file"); - Box::new(RawFileDiskSync::new(file, disk_cfg.direct)) as Box + Box::new(RawFileDiskSync::new(file)) as Box } } ImageType::Qcow2 => { diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index d8f7aa4fd..d14c20053 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -344,8 +344,10 @@ fn vmm_thread_rules() -> Result, Error> { allow_syscall(libc::SYS_pipe2), allow_syscall(libc::SYS_prctl), allow_syscall(libc::SYS_pread64), + allow_syscall(libc::SYS_preadv), allow_syscall(libc::SYS_prlimit64), allow_syscall(libc::SYS_pwrite64), + allow_syscall(libc::SYS_pwritev), allow_syscall(libc::SYS_read), #[cfg(target_arch = "x86_64")] allow_syscall(libc::SYS_readlink),