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