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_sync::RawFileSync; 15 use crate::BlockBackend; 16 17 pub struct FixedVhdDiskSync(FixedVhd); 18 19 impl FixedVhdDiskSync { new(file: File) -> std::io::Result<Self>20 pub fn new(file: File) -> std::io::Result<Self> { 21 Ok(Self(FixedVhd::new(file)?)) 22 } 23 } 24 25 impl DiskFile for FixedVhdDiskSync { size(&mut self) -> DiskFileResult<u64>26 fn size(&mut self) -> DiskFileResult<u64> { 27 Ok(self.0.size().unwrap()) 28 } 29 new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>>30 fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> { 31 Ok(Box::new( 32 FixedVhdSync::new(self.0.as_raw_fd(), self.0.size().unwrap()) 33 .map_err(DiskFileError::NewAsyncIo)?, 34 ) as Box<dyn AsyncIo>) 35 } 36 fd(&mut self) -> BorrowedDiskFd<'_>37 fn fd(&mut self) -> BorrowedDiskFd<'_> { 38 BorrowedDiskFd::new(self.0.as_raw_fd()) 39 } 40 } 41 42 pub struct FixedVhdSync { 43 raw_file_sync: RawFileSync, 44 size: u64, 45 } 46 47 impl FixedVhdSync { new(fd: RawFd, size: u64) -> std::io::Result<Self>48 pub fn new(fd: RawFd, size: u64) -> std::io::Result<Self> { 49 Ok(FixedVhdSync { 50 raw_file_sync: RawFileSync::new(fd), 51 size, 52 }) 53 } 54 } 55 56 impl AsyncIo for FixedVhdSync { notifier(&self) -> &EventFd57 fn notifier(&self) -> &EventFd { 58 self.raw_file_sync.notifier() 59 } 60 read_vectored( &mut self, offset: libc::off_t, iovecs: &[libc::iovec], user_data: u64, ) -> AsyncIoResult<()>61 fn read_vectored( 62 &mut self, 63 offset: libc::off_t, 64 iovecs: &[libc::iovec], 65 user_data: u64, 66 ) -> AsyncIoResult<()> { 67 if offset as u64 >= self.size { 68 return Err(AsyncIoError::ReadVectored(std::io::Error::new( 69 std::io::ErrorKind::InvalidData, 70 format!( 71 "Invalid offset {}, can't be larger than file size {}", 72 offset, self.size 73 ), 74 ))); 75 } 76 77 self.raw_file_sync.read_vectored(offset, iovecs, user_data) 78 } 79 write_vectored( &mut self, offset: libc::off_t, iovecs: &[libc::iovec], user_data: u64, ) -> AsyncIoResult<()>80 fn write_vectored( 81 &mut self, 82 offset: libc::off_t, 83 iovecs: &[libc::iovec], 84 user_data: u64, 85 ) -> AsyncIoResult<()> { 86 if offset as u64 >= self.size { 87 return Err(AsyncIoError::WriteVectored(std::io::Error::new( 88 std::io::ErrorKind::InvalidData, 89 format!( 90 "Invalid offset {}, can't be larger than file size {}", 91 offset, self.size 92 ), 93 ))); 94 } 95 96 self.raw_file_sync.write_vectored(offset, iovecs, user_data) 97 } 98 fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()>99 fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> { 100 self.raw_file_sync.fsync(user_data) 101 } 102 next_completed_request(&mut self) -> Option<(u64, i32)>103 fn next_completed_request(&mut self) -> Option<(u64, i32)> { 104 self.raw_file_sync.next_completed_request() 105 } 106 } 107