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