From 24c8cce012691da3d5cf620abd6e2fa5c1e0748f Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Thu, 28 Jan 2021 16:23:03 +0100 Subject: [PATCH] block_util: Add synchronous support for fixed VHD disk files Relying on the simplified version of the synchronous support for RAW disk files, the new fixed_vhd_sync module in the block_util crate introduces the synchronous support for fixed VHD disk files. With this patch, the fixed VHD support is complete as it is implemented in both synchronous and asynchronous versions. Signed-off-by: Sebastien Boeuf --- block_util/src/fixed_vhd_sync.rs | 107 +++++++++++++++++++++++++++++++ block_util/src/lib.rs | 1 + vmm/src/device_manager.rs | 13 +++- 3 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 block_util/src/fixed_vhd_sync.rs diff --git a/block_util/src/fixed_vhd_sync.rs b/block_util/src/fixed_vhd_sync.rs new file mode 100644 index 000000000..f4293ea88 --- /dev/null +++ b/block_util/src/fixed_vhd_sync.rs @@ -0,0 +1,107 @@ +// Copyright © 2021 Intel Corporation +// +// SPDX-License-Identifier: Apache-2.0 + +use crate::async_io::{ + AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult, +}; +use crate::raw_sync::RawFileSync; +use crate::vhd::VhdFooter; +use std::fs::File; +use std::os::unix::io::{AsRawFd, RawFd}; +use vmm_sys_util::eventfd::EventFd; + +pub struct FixedVhdDiskSync { + file: File, + size: u64, +} + +impl FixedVhdDiskSync { + pub fn new(mut file: File) -> std::io::Result { + let footer = VhdFooter::new(&mut file)?; + + Ok(FixedVhdDiskSync { + file, + size: footer.current_size(), + }) + } +} + +impl DiskFile for FixedVhdDiskSync { + fn size(&mut self) -> DiskFileResult { + Ok(self.size) + } + + fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult> { + Ok(Box::new( + FixedVhdSync::new(self.file.as_raw_fd(), self.size) + .map_err(DiskFileError::NewAsyncIo)?, + ) as Box) + } +} + +pub struct FixedVhdSync { + raw_file_sync: RawFileSync, + size: u64, +} + +impl FixedVhdSync { + pub fn new(fd: RawFd, size: u64) -> std::io::Result { + Ok(FixedVhdSync { + raw_file_sync: RawFileSync::new(fd), + size, + }) + } +} + +impl AsyncIo for FixedVhdSync { + fn notifier(&self) -> &EventFd { + self.raw_file_sync.notifier() + } + + fn read_vectored( + &mut self, + offset: libc::off_t, + iovecs: Vec, + 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_sync.read_vectored(offset, iovecs, user_data) + } + + fn write_vectored( + &mut self, + offset: libc::off_t, + iovecs: Vec, + 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_sync.write_vectored(offset, iovecs, user_data) + } + + fn fsync(&mut self, user_data: Option) -> AsyncIoResult<()> { + self.raw_file_sync.fsync(user_data) + } + + fn complete(&mut self) -> Vec<(u64, i32)> { + self.raw_file_sync.complete() + } +} diff --git a/block_util/src/lib.rs b/block_util/src/lib.rs index 087edfa7d..8527a7fc2 100644 --- a/block_util/src/lib.rs +++ b/block_util/src/lib.rs @@ -15,6 +15,7 @@ extern crate serde_derive; pub mod async_io; pub mod fixed_vhd_async; +pub mod fixed_vhd_sync; pub mod qcow_sync; pub mod raw_async; pub mod raw_sync; diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 55953131e..c83ca3fc9 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -40,8 +40,8 @@ use arch::layout::{APIC_START, IOAPIC_SIZE, IOAPIC_START}; use arch::DeviceType; use block_util::{ async_io::DiskFile, block_io_uring_is_supported, detect_image_type, - fixed_vhd_async::FixedVhdDiskAsync, qcow_sync::QcowDiskSync, raw_async::RawFileDisk, - raw_sync::RawFileDiskSync, ImageType, + fixed_vhd_async::FixedVhdDiskAsync, fixed_vhd_sync::FixedVhdDiskSync, qcow_sync::QcowDiskSync, + raw_async::RawFileDisk, raw_sync::RawFileDiskSync, ImageType, }; #[cfg(target_arch = "aarch64")] use devices::gic; @@ -383,6 +383,9 @@ pub enum DeviceManagerError { /// Failed to create FixedVhdDiskAsync CreateFixedVhdDiskAsync(io::Error), + + /// Failed to create FixedVhdDiskSync + CreateFixedVhdDiskSync(io::Error), } pub type DeviceManagerResult = result::Result; @@ -1675,7 +1678,11 @@ impl DeviceManager { .map_err(DeviceManagerError::CreateFixedVhdDiskAsync)?, ) as Box } else { - unimplemented!("No synchronous implementation for fixed VHD files"); + info!("Using synchronous fixed VHD disk file"); + Box::new( + FixedVhdDiskSync::new(file) + .map_err(DeviceManagerError::CreateFixedVhdDiskSync)?, + ) as Box } } ImageType::Raw => {