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, BorrowedDiskFd, 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 fn fd(&mut self) -> BorrowedDiskFd { 38 BorrowedDiskFd::new(self.0.as_raw_fd()) 39 } 40 } 41 42 pub struct FixedVhdAsync { 43 raw_file_async: RawFileAsync, 44 size: u64, 45 } 46 47 impl FixedVhdAsync { 48 pub fn new(fd: RawFd, ring_depth: u32, size: u64) -> std::io::Result<Self> { 49 let raw_file_async = RawFileAsync::new(fd, ring_depth)?; 50 51 Ok(FixedVhdAsync { 52 raw_file_async, 53 size, 54 }) 55 } 56 } 57 58 impl AsyncIo for FixedVhdAsync { 59 fn notifier(&self) -> &EventFd { 60 self.raw_file_async.notifier() 61 } 62 63 fn read_vectored( 64 &mut self, 65 offset: libc::off_t, 66 iovecs: &[libc::iovec], 67 user_data: u64, 68 ) -> AsyncIoResult<()> { 69 if offset as u64 >= self.size { 70 return Err(AsyncIoError::ReadVectored(std::io::Error::new( 71 std::io::ErrorKind::InvalidData, 72 format!( 73 "Invalid offset {}, can't be larger than file size {}", 74 offset, self.size 75 ), 76 ))); 77 } 78 79 self.raw_file_async.read_vectored(offset, iovecs, user_data) 80 } 81 82 fn write_vectored( 83 &mut self, 84 offset: libc::off_t, 85 iovecs: &[libc::iovec], 86 user_data: u64, 87 ) -> AsyncIoResult<()> { 88 if offset as u64 >= self.size { 89 return Err(AsyncIoError::WriteVectored(std::io::Error::new( 90 std::io::ErrorKind::InvalidData, 91 format!( 92 "Invalid offset {}, can't be larger than file size {}", 93 offset, self.size 94 ), 95 ))); 96 } 97 98 self.raw_file_async 99 .write_vectored(offset, iovecs, user_data) 100 } 101 102 fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> { 103 self.raw_file_async.fsync(user_data) 104 } 105 106 fn next_completed_request(&mut self) -> Option<(u64, i32)> { 107 self.raw_file_async.next_completed_request() 108 } 109 } 110