1#![forbid(unsafe_code)]
7
8pub mod resolver;
10
11use disk_backend::Disk;
12use disk_backend::DiskError;
13use disk_backend::DiskIo;
14use disk_backend::UnmapBehavior;
15use inspect::Inspect;
16use mesh::Cell;
17use pal_async::timer::PolledTimer;
18use scsi_buffers::RequestBuffers;
19use std::time::Duration;
20use vmcore::vm_task::VmTaskDriver;
21use vmcore::vm_task::VmTaskDriverSource;
22
23#[derive(Inspect)]
25pub struct DelayDisk {
26 #[inspect(with = "|x| x.get()")]
27 delay: Cell<Duration>,
28 inner: Disk,
29 driver: VmTaskDriver,
30}
31
32impl DelayDisk {
33 pub fn new(delay: Cell<Duration>, inner: Disk, driver_source: &VmTaskDriverSource) -> Self {
35 Self {
36 delay,
37 inner,
38 driver: driver_source.simple(),
39 }
40 }
41}
42
43impl DiskIo for DelayDisk {
44 fn disk_type(&self) -> &str {
45 "delay"
46 }
47
48 fn sector_count(&self) -> u64 {
50 self.inner.sector_count()
51 }
52
53 fn sector_size(&self) -> u32 {
55 self.inner.sector_size()
56 }
57
58 fn disk_id(&self) -> Option<[u8; 16]> {
60 self.inner.disk_id()
61 }
62
63 fn physical_sector_size(&self) -> u32 {
65 self.inner.physical_sector_size()
66 }
67
68 fn is_fua_respected(&self) -> bool {
70 self.inner.is_fua_respected()
71 }
72
73 fn is_read_only(&self) -> bool {
75 self.inner.is_read_only()
76 }
77
78 fn pr(&self) -> Option<&dyn disk_backend::pr::PersistentReservation> {
80 self.inner.pr()
81 }
82
83 async fn read_vectored(
85 &self,
86 buffers: &RequestBuffers<'_>,
87 sector: u64,
88 ) -> Result<(), DiskError> {
89 PolledTimer::new(&self.driver).sleep(self.delay.get()).await;
90 self.inner.read_vectored(buffers, sector).await
91 }
92
93 async fn write_vectored(
95 &self,
96 buffers: &RequestBuffers<'_>,
97 sector: u64,
98 fua: bool,
99 ) -> Result<(), DiskError> {
100 PolledTimer::new(&self.driver).sleep(self.delay.get()).await;
101 self.inner.write_vectored(buffers, sector, fua).await
102 }
103
104 async fn sync_cache(&self) -> Result<(), DiskError> {
106 self.inner.sync_cache().await
107 }
108
109 async fn wait_resize(&self, sector_count: u64) -> u64 {
111 self.inner.wait_resize(sector_count).await
112 }
113
114 fn unmap(
116 &self,
117 sector: u64,
118 count: u64,
119 block_level_only: bool,
120 ) -> impl Future<Output = Result<(), DiskError>> + Send {
121 self.inner.unmap(sector, count, block_level_only)
122 }
123
124 fn unmap_behavior(&self) -> UnmapBehavior {
126 self.inner.unmap_behavior()
127 }
128
129 fn optimal_unmap_sectors(&self) -> u32 {
131 self.inner.optimal_unmap_sectors()
132 }
133}