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 <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2021-01-28 17:29:33 +01:00 committed by Rob Bradford
parent b2e5dbaecb
commit c6854c5a97
4 changed files with 64 additions and 47 deletions

View File

@ -2,54 +2,49 @@
// //
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileResult}; use crate::async_io::{
use crate::{disk_size, fsync_sync, read_vectored_sync, write_vectored_sync}; AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
use qcow::RawFile; };
use std::fs::File; 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; use vmm_sys_util::eventfd::EventFd;
pub struct RawFileDiskSync { pub struct RawFileDiskSync {
raw_file: RawFile, file: File,
semaphore: Arc<Mutex<()>>,
} }
impl RawFileDiskSync { impl RawFileDiskSync {
pub fn new(file: File, direct_io: bool) -> Self { pub fn new(file: File) -> Self {
RawFileDiskSync { RawFileDiskSync { file }
raw_file: RawFile::new(file, direct_io),
semaphore: Arc::new(Mutex::new(())),
}
} }
} }
impl DiskFile for RawFileDiskSync { impl DiskFile for RawFileDiskSync {
fn size(&mut self) -> DiskFileResult<u64> { fn size(&mut self) -> DiskFileResult<u64> {
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<Box<dyn AsyncIo>> { fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
Ok(Box::new(RawFileSync::new( Ok(Box::new(RawFileSync::new(self.file.as_raw_fd())) as Box<dyn AsyncIo>)
self.raw_file.clone(),
self.semaphore.clone(),
)) as Box<dyn AsyncIo>)
} }
} }
pub struct RawFileSync { pub struct RawFileSync {
raw_file: RawFile, fd: RawFd,
eventfd: EventFd, eventfd: EventFd,
completion_list: Vec<(u64, i32)>, completion_list: Vec<(u64, i32)>,
semaphore: Arc<Mutex<()>>,
} }
impl RawFileSync { impl RawFileSync {
pub fn new(raw_file: RawFile, semaphore: Arc<Mutex<()>>) -> Self { pub fn new(fd: RawFd) -> Self {
RawFileSync { RawFileSync {
raw_file, fd,
eventfd: EventFd::new(libc::EFD_NONBLOCK).expect("Failed creating EventFd for RawFile"), eventfd: EventFd::new(libc::EFD_NONBLOCK).expect("Failed creating EventFd for RawFile"),
completion_list: Vec::new(), completion_list: Vec::new(),
semaphore,
} }
} }
} }
@ -65,15 +60,22 @@ impl AsyncIo for RawFileSync {
iovecs: Vec<libc::iovec>, iovecs: Vec<libc::iovec>,
user_data: u64, user_data: u64,
) -> AsyncIoResult<()> { ) -> AsyncIoResult<()> {
read_vectored_sync( let result = unsafe {
offset, libc::preadv(
iovecs, self.fd as libc::c_int,
user_data, iovecs.as_ptr() as *const libc::iovec,
&mut self.raw_file, iovecs.len() as libc::c_int,
&self.eventfd, offset,
&mut self.completion_list, )
&mut self.semaphore, };
) 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( fn write_vectored(
@ -82,25 +84,36 @@ impl AsyncIo for RawFileSync {
iovecs: Vec<libc::iovec>, iovecs: Vec<libc::iovec>,
user_data: u64, user_data: u64,
) -> AsyncIoResult<()> { ) -> AsyncIoResult<()> {
write_vectored_sync( let result = unsafe {
offset, libc::pwritev(
iovecs, self.fd as libc::c_int,
user_data, iovecs.as_ptr() as *const libc::iovec,
&mut self.raw_file, iovecs.len() as libc::c_int,
&self.eventfd, offset,
&mut self.completion_list, )
&mut self.semaphore, };
) 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<u64>) -> AsyncIoResult<()> { fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
fsync_sync( let result = unsafe { libc::fsync(self.fd as libc::c_int) };
user_data, if result < 0 {
&mut self.raw_file, return Err(AsyncIoError::Fsync(std::io::Error::last_os_error()));
&self.eventfd, }
&mut self.completion_list,
&mut self.semaphore, 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)> { fn complete(&mut self) -> Vec<(u64, i32)> {

View File

@ -106,6 +106,8 @@ fn virtio_block_thread_rules() -> Result<Vec<SyscallRuleSet>, Error> {
allow_syscall(libc::SYS_openat), allow_syscall(libc::SYS_openat),
allow_syscall(libc::SYS_prctl), allow_syscall(libc::SYS_prctl),
allow_syscall(libc::SYS_pread64), allow_syscall(libc::SYS_pread64),
allow_syscall(libc::SYS_preadv),
allow_syscall(libc::SYS_pwritev),
allow_syscall(libc::SYS_read), allow_syscall(libc::SYS_read),
allow_syscall(libc::SYS_rt_sigprocmask), allow_syscall(libc::SYS_rt_sigprocmask),
allow_syscall(libc::SYS_sched_getaffinity), allow_syscall(libc::SYS_sched_getaffinity),

View File

@ -1686,7 +1686,7 @@ impl DeviceManager {
Box::new(RawFileDisk::new(file)) as Box<dyn DiskFile> Box::new(RawFileDisk::new(file)) as Box<dyn DiskFile>
} else { } else {
info!("Using synchronous RAW disk file"); info!("Using synchronous RAW disk file");
Box::new(RawFileDiskSync::new(file, disk_cfg.direct)) as Box<dyn DiskFile> Box::new(RawFileDiskSync::new(file)) as Box<dyn DiskFile>
} }
} }
ImageType::Qcow2 => { ImageType::Qcow2 => {

View File

@ -344,8 +344,10 @@ fn vmm_thread_rules() -> Result<Vec<SyscallRuleSet>, Error> {
allow_syscall(libc::SYS_pipe2), allow_syscall(libc::SYS_pipe2),
allow_syscall(libc::SYS_prctl), allow_syscall(libc::SYS_prctl),
allow_syscall(libc::SYS_pread64), allow_syscall(libc::SYS_pread64),
allow_syscall(libc::SYS_preadv),
allow_syscall(libc::SYS_prlimit64), allow_syscall(libc::SYS_prlimit64),
allow_syscall(libc::SYS_pwrite64), allow_syscall(libc::SYS_pwrite64),
allow_syscall(libc::SYS_pwritev),
allow_syscall(libc::SYS_read), allow_syscall(libc::SYS_read),
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
allow_syscall(libc::SYS_readlink), allow_syscall(libc::SYS_readlink),