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

52
Cargo.lock generated
View File

@ -141,6 +141,7 @@ dependencies = [
"thiserror", "thiserror",
"versionize", "versionize",
"versionize_derive", "versionize_derive",
"vhdx",
"virtio-bindings", "virtio-bindings",
"vm-memory 0.6.0", "vm-memory 0.6.0",
"vm-virtio", "vm-virtio",
@ -224,6 +225,15 @@ dependencies = [
"bitflags", "bitflags",
] ]
[[package]]
name = "crc32c"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "210cdf933e6a81212bfabf90cd8762f471b5922e5f6b709547673ad8e04b9448"
dependencies = [
"rustc_version",
]
[[package]] [[package]]
name = "crc64" name = "crc64"
version = "1.0.0" version = "1.0.0"
@ -860,6 +870,15 @@ version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49"
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.5" version = "1.0.5"
@ -880,6 +899,21 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.127" version = "1.0.127"
@ -1058,6 +1092,9 @@ name = "uuid"
version = "0.8.2" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom",
]
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
@ -1137,6 +1174,20 @@ dependencies = [
"vmm-sys-util", "vmm-sys-util",
] ]
[[package]]
name = "vhdx"
version = "0.1.0"
dependencies = [
"byteorder",
"crc32c",
"libc",
"log",
"remain",
"thiserror",
"uuid",
"vmm-sys-util",
]
[[package]] [[package]]
name = "vhost" name = "vhost"
version = "0.1.0" version = "0.1.0"
@ -1347,6 +1398,7 @@ dependencies = [
"versionize", "versionize",
"versionize_derive", "versionize_derive",
"vfio-ioctls", "vfio-ioctls",
"vhdx",
"virtio-devices", "virtio-devices",
"vm-allocator", "vm-allocator",
"vm-device", "vm-device",

View File

@ -78,6 +78,7 @@ members = [
"qcow", "qcow",
"rate_limiter", "rate_limiter",
"vfio_user", "vfio_user",
"vhdx",
"vhost_user_backend", "vhost_user_backend",
"vhost_user_block", "vhost_user_block",
"vhost_user_net", "vhost_user_net",

View File

@ -16,6 +16,7 @@ qcow = { path = "../qcow" }
thiserror = "1.0.26" thiserror = "1.0.26"
versionize = "0.1.6" versionize = "0.1.6"
versionize_derive = "0.1.4" versionize_derive = "0.1.4"
vhdx = { path = "../vhdx" }
virtio-bindings = { version = "0.1.0", features = ["virtio-v5_0_0"] } virtio-bindings = { version = "0.1.0", features = ["virtio-v5_0_0"] }
vm-memory = { version = "0.6.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] } vm-memory = { version = "0.6.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" } vm-virtio = { path = "../vm-virtio" }

View File

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

View File

@ -111,6 +111,7 @@ fn virtio_block_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
(libc::SYS_fsync, vec![]), (libc::SYS_fsync, vec![]),
(libc::SYS_ftruncate, vec![]), (libc::SYS_ftruncate, vec![]),
(libc::SYS_futex, vec![]), (libc::SYS_futex, vec![]),
(libc::SYS_getrandom, vec![]),
(libc::SYS_io_uring_enter, vec![]), (libc::SYS_io_uring_enter, vec![]),
(libc::SYS_lseek, vec![]), (libc::SYS_lseek, vec![]),
(libc::SYS_madvise, vec![]), (libc::SYS_madvise, vec![]),

View File

@ -45,6 +45,7 @@ uuid = "0.8.2"
versionize = "0.1.6" versionize = "0.1.6"
versionize_derive = "0.1.4" versionize_derive = "0.1.4"
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio-ioctls", branch = "master", default-features = false } vfio-ioctls = { git = "https://github.com/rust-vmm/vfio-ioctls", branch = "master", default-features = false }
vhdx = { path = "../vhdx" }
virtio-devices = { path = "../virtio-devices" } virtio-devices = { path = "../virtio-devices" }
vm-allocator = { path = "../vm-allocator" } vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" } vm-device = { path = "../vm-device" }

View File

@ -39,7 +39,7 @@ use arch::{DeviceType, MmioDeviceInfo};
use block_util::{ use block_util::{
async_io::DiskFile, block_io_uring_is_supported, detect_image_type, async_io::DiskFile, block_io_uring_is_supported, detect_image_type,
fixed_vhd_async::FixedVhdDiskAsync, fixed_vhd_sync::FixedVhdDiskSync, qcow_sync::QcowDiskSync, fixed_vhd_async::FixedVhdDiskAsync, fixed_vhd_sync::FixedVhdDiskSync, qcow_sync::QcowDiskSync,
raw_async::RawFileDisk, raw_sync::RawFileDiskSync, ImageType, raw_async::RawFileDisk, raw_sync::RawFileDiskSync, vhdx_sync::VhdxDiskSync, ImageType,
}; };
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
use devices::gic; use devices::gic;
@ -420,6 +420,9 @@ pub enum DeviceManagerError {
/// Failed to create QcowDiskSync /// Failed to create QcowDiskSync
CreateQcowDiskSync(qcow::Error), CreateQcowDiskSync(qcow::Error),
/// Failed to create FixedVhdxDiskSync
CreateFixedVhdxDiskSync(vhdx::vhdx::VhdxError),
/// Failed adding DMA mapping handler to virtio-mem device. /// Failed adding DMA mapping handler to virtio-mem device.
AddDmaMappingHandlerVirtioMem(virtio_devices::mem::Error), AddDmaMappingHandlerVirtioMem(virtio_devices::mem::Error),
@ -1944,6 +1947,13 @@ impl DeviceManager {
.map_err(DeviceManagerError::CreateQcowDiskSync)?, .map_err(DeviceManagerError::CreateQcowDiskSync)?,
) as Box<dyn DiskFile> ) as Box<dyn DiskFile>
} }
ImageType::Vhdx => {
info!("Using synchronous VHDX disk file");
Box::new(
VhdxDiskSync::new(file)
.map_err(DeviceManagerError::CreateFixedVhdxDiskSync)?,
) as Box<dyn DiskFile>
}
}; };
let dev = Arc::new(Mutex::new( let dev = Arc::new(Mutex::new(