cloud-hypervisor/block_util/src/fixed_vhd_async.rs
Sebastien Boeuf b2e5dbaecb block_util, vmm: Add fixed VHD asynchronous implementation
This commit adds the asynchronous support for fixed VHD disk files.

It introduces FixedVhd as a new ImageType, moving the image type
detection to the block_util crate (instead of qcow crate).

It creates a new vhd module in the block_util crate in order to handle
VHD footer, following the VHD specification.

It creates a new fixed_vhd_async module in the block_util crate to
implement the asynchronous version of fixed VHD disk file. It relies on
io_uring.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
2021-02-01 13:45:08 +00:00

111 lines
2.8 KiB
Rust

// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
use crate::async_io::{
AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult,
};
use crate::raw_async::RawFileAsync;
use crate::vhd::VhdFooter;
use std::fs::File;
use std::os::unix::io::{AsRawFd, RawFd};
use vmm_sys_util::eventfd::EventFd;
pub struct FixedVhdDiskAsync {
file: File,
size: u64,
}
impl FixedVhdDiskAsync {
pub fn new(mut file: File) -> std::io::Result<Self> {
let footer = VhdFooter::new(&mut file)?;
Ok(FixedVhdDiskAsync {
file,
size: footer.current_size(),
})
}
}
impl DiskFile for FixedVhdDiskAsync {
fn size(&mut self) -> DiskFileResult<u64> {
Ok(self.size)
}
fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
Ok(Box::new(
FixedVhdAsync::new(self.file.as_raw_fd(), ring_depth, self.size)
.map_err(DiskFileError::NewAsyncIo)?,
) as Box<dyn AsyncIo>)
}
}
pub struct FixedVhdAsync {
raw_file_async: RawFileAsync,
size: u64,
}
impl FixedVhdAsync {
pub fn new(fd: RawFd, ring_depth: u32, size: u64) -> std::io::Result<Self> {
let raw_file_async = RawFileAsync::new(fd, ring_depth)?;
Ok(FixedVhdAsync {
raw_file_async,
size,
})
}
}
impl AsyncIo for FixedVhdAsync {
fn notifier(&self) -> &EventFd {
self.raw_file_async.notifier()
}
fn read_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
if offset as u64 >= self.size {
return Err(AsyncIoError::ReadVectored(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"Invalid offset {}, can't be larger than file size {}",
offset, self.size
),
)));
}
self.raw_file_async.read_vectored(offset, iovecs, user_data)
}
fn write_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
if offset as u64 >= self.size {
return Err(AsyncIoError::WriteVectored(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"Invalid offset {}, can't be larger than file size {}",
offset, self.size
),
)));
}
self.raw_file_async
.write_vectored(offset, iovecs, user_data)
}
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
self.raw_file_async.fsync(user_data)
}
fn complete(&mut self) -> Vec<(u64, i32)> {
self.raw_file_async.complete()
}
}