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
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<Mutex<()>>,
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<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>> {
Ok(Box::new(RawFileSync::new(
self.raw_file.clone(),
self.semaphore.clone(),
)) as Box<dyn AsyncIo>)
Ok(Box::new(RawFileSync::new(self.file.as_raw_fd())) as Box<dyn AsyncIo>)
}
}
pub struct RawFileSync {
raw_file: RawFile,
fd: RawFd,
eventfd: EventFd,
completion_list: Vec<(u64, i32)>,
semaphore: Arc<Mutex<()>>,
}
impl RawFileSync {
pub fn new(raw_file: RawFile, semaphore: Arc<Mutex<()>>) -> 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<libc::iovec>,
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<libc::iovec>,
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<u64>) -> 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)> {

View File

@ -106,6 +106,8 @@ fn virtio_block_thread_rules() -> Result<Vec<SyscallRuleSet>, 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),

View File

@ -1686,7 +1686,7 @@ impl DeviceManager {
Box::new(RawFileDisk::new(file)) as Box<dyn DiskFile>
} else {
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 => {

View File

@ -344,8 +344,10 @@ fn vmm_thread_rules() -> Result<Vec<SyscallRuleSet>, 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),