// 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 { let footer = VhdFooter::new(&mut file)?; Ok(FixedVhdDiskAsync { file, size: footer.current_size(), }) } } impl DiskFile for FixedVhdDiskAsync { fn size(&mut self) -> DiskFileResult { Ok(self.size) } fn new_async_io(&self, ring_depth: u32) -> DiskFileResult> { Ok(Box::new( FixedVhdAsync::new(self.file.as_raw_fd(), ring_depth, self.size) .map_err(DiskFileError::NewAsyncIo)?, ) as Box) } } pub struct FixedVhdAsync { raw_file_async: RawFileAsync, size: u64, } impl FixedVhdAsync { pub fn new(fd: RawFd, ring_depth: u32, size: u64) -> std::io::Result { 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, 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, 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) -> AsyncIoResult<()> { self.raw_file_async.fsync(user_data) } fn complete(&mut self) -> Vec<(u64, i32)> { self.raw_file_async.complete() } }