xref: /cloud-hypervisor/block/src/fixed_vhd_async.rs (revision eb0b14f70ed5ed44b76579145fd2a741c0100ae4)
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