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 => {