1 // Copyright © 2021 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 use std::fs::File; 6 use std::os::unix::io::{AsRawFd, RawFd}; 7 8 use vmm_sys_util::eventfd::EventFd; 9 10 use crate::async_io::{ 11 AsyncIo, AsyncIoError, AsyncIoResult, DiskFile, DiskFileError, DiskFileResult, 12 }; 13 use crate::fixed_vhd::FixedVhd; 14 use crate::raw_async::RawFileAsync; 15 use crate::BlockBackend; 16 17 pub struct FixedVhdDiskAsync(FixedVhd); 18 19 impl FixedVhdDiskAsync { 20 pub fn new(file: File) -> std::io::Result<Self> { 21 Ok(Self(FixedVhd::new(file)?)) 22 } 23 } 24 25 impl DiskFile for FixedVhdDiskAsync { 26 fn size(&mut self) -> DiskFileResult<u64> { 27 Ok(self.0.size().unwrap()) 28 } 29 30 fn new_async_io(&self, ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> { 31 Ok(Box::new( 32 FixedVhdAsync::new(self.0.as_raw_fd(), ring_depth, self.0.size().unwrap()) 33 .map_err(DiskFileError::NewAsyncIo)?, 34 ) as Box<dyn AsyncIo>) 35 } 36 } 37 38 pub struct FixedVhdAsync { 39 raw_file_async: RawFileAsync, 40 size: u64, 41 } 42 43 impl FixedVhdAsync { 44 pub fn new(fd: RawFd, ring_depth: u32, size: u64) -> std::io::Result<Self> { 45 let raw_file_async = RawFileAsync::new(fd, ring_depth)?; 46 47 Ok(FixedVhdAsync { 48 raw_file_async, 49 size, 50 }) 51 } 52 } 53 54 impl AsyncIo for FixedVhdAsync { 55 fn notifier(&self) -> &EventFd { 56 self.raw_file_async.notifier() 57 } 58 59 fn read_vectored( 60 &mut self, 61 offset: libc::off_t, 62 iovecs: &[libc::iovec], 63 user_data: u64, 64 ) -> AsyncIoResult<()> { 65 if offset as u64 >= self.size { 66 return Err(AsyncIoError::ReadVectored(std::io::Error::new( 67 std::io::ErrorKind::InvalidData, 68 format!( 69 "Invalid offset {}, can't be larger than file size {}", 70 offset, self.size 71 ), 72 ))); 73 } 74 75 self.raw_file_async.read_vectored(offset, iovecs, user_data) 76 } 77 78 fn write_vectored( 79 &mut self, 80 offset: libc::off_t, 81 iovecs: &[libc::iovec], 82 user_data: u64, 83 ) -> AsyncIoResult<()> { 84 if offset as u64 >= self.size { 85 return Err(AsyncIoError::WriteVectored(std::io::Error::new( 86 std::io::ErrorKind::InvalidData, 87 format!( 88 "Invalid offset {}, can't be larger than file size {}", 89 offset, self.size 90 ), 91 ))); 92 } 93 94 self.raw_file_async 95 .write_vectored(offset, iovecs, user_data) 96 } 97 98 fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> { 99 self.raw_file_async.fsync(user_data) 100 } 101 102 fn next_completed_request(&mut self) -> Option<(u64, i32)> { 103 self.raw_file_async.next_completed_request() 104 } 105 } 106