block_util, vhdx: vhdx crate integration with the cloud hypervisor

vhdx_sync.rs in block_util implements traits to represent the vhdx
crate as a supported block device in the cloud hypervisor. The vhdx
is added to the block device list in device_manager.rs at the vmm
crate so that it can automatically detect a vhdx disk and invoke the
corresponding crate.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Fazla Mehrab <akm.fazla.mehrab@intel.com>
This commit is contained in:
Fazla Mehrab
2021-07-26 11:51:03 -04:00
committed by Sebastien Boeuf
parent 452af9b17c
commit 5db4dede28
8 changed files with 185 additions and 1 deletions

View File

@@ -18,6 +18,7 @@ pub mod qcow_sync;
pub mod raw_async;
pub mod raw_sync;
pub mod vhd;
pub mod vhdx_sync;
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, DiskFileError, DiskFileResult};
#[cfg(feature = "io_uring")]
@@ -602,9 +603,11 @@ pub enum ImageType {
FixedVhd,
Qcow2,
Raw,
Vhdx,
}
const QCOW_MAGIC: u32 = 0x5146_49fb;
const VHDX_SIGN: u64 = 0x656C_6966_7864_6876;
/// Determine image type through file parsing.
pub fn detect_image_type(f: &mut File) -> std::io::Result<ImageType> {
@@ -623,6 +626,8 @@ pub fn detect_image_type(f: &mut File) -> std::io::Result<ImageType> {
ImageType::Qcow2
} else if vhd::is_fixed_vhd(f)? {
ImageType::FixedVhd
} else if u64::from_le_bytes(s.data[0..8].try_into().unwrap()) == VHDX_SIGN {
ImageType::Vhdx
} else {
ImageType::Raw
};

113
block_util/src/vhdx_sync.rs Normal file
View File

@@ -0,0 +1,113 @@
// Copyright © 2021 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
use crate::async_io::{AsyncIo, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult};
use crate::{fsync_sync, read_vectored_sync, write_vectored_sync};
use std::fs::File;
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use vhdx::vhdx::{Result as VhdxResult, Vhdx};
use vmm_sys_util::eventfd::EventFd;
pub struct VhdxDiskSync {
vhdx_file: Arc<Mutex<Vhdx>>,
semaphore: Arc<Mutex<()>>,
}
impl VhdxDiskSync {
pub fn new(f: File) -> VhdxResult<Self> {
let vhdx = Vhdx::new(f)?;
let vhdx_file = Arc::new(Mutex::new(vhdx));
Ok(VhdxDiskSync {
vhdx_file,
semaphore: Arc::new(Mutex::new(())),
})
}
}
impl DiskFile for VhdxDiskSync {
fn size(&mut self) -> DiskFileResult<u64> {
Ok(self.vhdx_file.lock().unwrap().virtual_disk_size())
}
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
Ok(Box::new(
VhdxSync::new(self.vhdx_file.clone(), self.semaphore.clone())
.map_err(DiskFileError::NewAsyncIo)?,
) as Box<dyn AsyncIo>)
}
}
pub struct VhdxSync {
vhdx_file: Arc<Mutex<Vhdx>>,
eventfd: EventFd,
completion_list: Vec<(u64, i32)>,
semaphore: Arc<Mutex<()>>,
}
impl VhdxSync {
pub fn new(vhdx_file: Arc<Mutex<Vhdx>>, semaphore: Arc<Mutex<()>>) -> std::io::Result<Self> {
Ok(VhdxSync {
vhdx_file,
eventfd: EventFd::new(libc::EFD_NONBLOCK)?,
completion_list: Vec::new(),
semaphore,
})
}
}
impl AsyncIo for VhdxSync {
fn notifier(&self) -> &EventFd {
&self.eventfd
}
fn read_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
read_vectored_sync(
offset,
iovecs,
user_data,
self.vhdx_file.lock().unwrap().deref_mut(),
&self.eventfd,
&mut self.completion_list,
&mut self.semaphore,
)
}
fn write_vectored(
&mut self,
offset: libc::off_t,
iovecs: Vec<libc::iovec>,
user_data: u64,
) -> AsyncIoResult<()> {
write_vectored_sync(
offset,
iovecs,
user_data,
self.vhdx_file.lock().unwrap().deref_mut(),
&self.eventfd,
&mut self.completion_list,
&mut self.semaphore,
)
}
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
fsync_sync(
user_data,
self.vhdx_file.lock().unwrap().deref_mut(),
&self.eventfd,
&mut self.completion_list,
&mut self.semaphore,
)
}
fn complete(&mut self) -> Vec<(u64, i32)> {
self.completion_list.drain(..).collect()
}
}