storage_device/
ranged_device.rs1use crate::buffer::{BufferRef, MutableBufferRef};
6use crate::buffer_allocator::BufferFuture;
7use crate::{Device, ReadOptions, WriteOptions};
8use anyhow::{Error, anyhow, bail, ensure};
9use async_trait::async_trait;
10use std::ops::Range;
11use std::sync::Arc;
12
13pub struct RangedDevice {
15 source: Arc<dyn Device>,
17 range: Range<u64>,
19}
20
21impl RangedDevice {
22 pub fn new(source: Arc<dyn Device>, start_block: u64, num_blocks: u64) -> Result<Self, Error> {
23 ensure!(
24 start_block + num_blocks <= source.block_count(),
25 "failed to create RangedDevice (out of range)"
26 );
27 ensure!(num_blocks > 0, "failed to create RangedDevice (no size)");
28 let start = start_block
29 .checked_mul(source.block_size() as u64)
30 .ok_or_else(|| anyhow!("arithmetic overflow calculating ranged start"))?;
31 let end = (start_block + num_blocks)
32 .checked_mul(source.block_size() as u64)
33 .ok_or_else(|| anyhow!("arithmetic overflow calculating ranged end"))?;
34
35 Ok(Self { source: source.clone(), range: (start..end) })
36 }
37
38 fn num_blocks(&self) -> u64 {
39 (self.range.end - self.range.start) / self.block_size() as u64
40 }
41}
42
43#[async_trait]
44impl Device for RangedDevice {
45 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
46 self.source.allocate_buffer(size)
47 }
48
49 fn block_size(&self) -> u32 {
50 self.source.block_size()
51 }
52
53 fn block_count(&self) -> u64 {
54 self.num_blocks()
55 }
56
57 async fn read_with_opts(
58 &self,
59 offset: u64,
60 buffer: MutableBufferRef<'_>,
61 _read_opts: ReadOptions,
62 ) -> Result<(), Error> {
63 let adjusted_offset = self
64 .range
65 .start
66 .checked_add(offset)
67 .ok_or_else(|| anyhow!("arithmetic overflow calculating offset"))?;
68 ensure!(
69 adjusted_offset + buffer.len() as u64 <= self.range.end,
70 "reading past end of device"
71 );
72 self.source.read(adjusted_offset, buffer).await
73 }
74
75 async fn write_with_opts(
76 &self,
77 offset: u64,
78 buffer: BufferRef<'_>,
79 opts: WriteOptions,
80 ) -> Result<(), Error> {
81 let adjusted_offset = self
82 .range
83 .start
84 .checked_add(offset)
85 .ok_or_else(|| anyhow!("arithmetic overflow calculating offset"))?;
86 ensure!(
87 adjusted_offset + buffer.len() as u64 <= self.range.end,
88 "writing past end of device"
89 );
90 self.source.write_with_opts(adjusted_offset, buffer, opts).await
91 }
92
93 async fn trim(&self, _range: Range<u64>) -> Result<(), Error> {
94 bail!("RangedDevice does not support trim");
95 }
96
97 async fn close(&self) -> Result<(), Error> {
98 self.source.close().await
99 }
100
101 async fn flush(&self) -> Result<(), Error> {
102 self.source.flush().await
103 }
104
105 fn barrier(&self) {
106 self.source.barrier()
107 }
108
109 fn is_read_only(&self) -> bool {
110 self.source.is_read_only()
111 }
112
113 fn supports_trim(&self) -> bool {
114 false
115 }
116
117 fn reopen(&self, read_only: bool) {
118 self.source.reopen(read_only)
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::RangedDevice;
125 use crate::Device;
126 use crate::fake_device::FakeDevice;
127 use std::sync::Arc;
128
129 #[fuchsia::test]
130 async fn test_ranged_device_reads() {
131 const BLOCK_SIZE: usize = 512;
132 let device = Arc::new(FakeDevice::new(8, BLOCK_SIZE as u32));
133
134 let mut buffer = device.allocate_buffer(BLOCK_SIZE).await;
135 buffer.as_mut_slice().copy_from_slice(&[1; 512]);
136 device.write(BLOCK_SIZE as u64, buffer.as_ref()).await.expect("failed to write to device");
137
138 buffer.as_mut_slice().copy_from_slice(&[2; 512]);
139 device
140 .write(2 * BLOCK_SIZE as u64, buffer.as_ref())
141 .await
142 .expect("failed to write to device");
143
144 let sub_device =
146 RangedDevice::new(device.clone(), 1, 3).expect("failed to create new RangedDevice");
147
148 let mut ranged_device_buffer = sub_device.allocate_buffer(BLOCK_SIZE).await;
150 sub_device
151 .read(0, ranged_device_buffer.as_mut())
152 .await
153 .expect("failed to read from RangedDevice");
154 assert_eq!(ranged_device_buffer.as_slice(), [1; 512]);
155
156 sub_device
157 .read(BLOCK_SIZE as u64, ranged_device_buffer.as_mut())
158 .await
159 .expect("failed to read from RangedDevice");
160 assert_eq!(ranged_device_buffer.as_slice(), [2; 512]);
161
162 sub_device
163 .read(2 * BLOCK_SIZE as u64, ranged_device_buffer.as_mut())
164 .await
165 .expect("failed to read from RangedDevice");
166 assert_eq!(ranged_device_buffer.as_slice(), [0; 512]);
167
168 sub_device
169 .read(3 * BLOCK_SIZE as u64, ranged_device_buffer.as_mut())
170 .await
171 .expect_err("unexepectedly passed reading out of range of RangedDevice");
172 }
173
174 #[fuchsia::test]
175 async fn test_ranged_device_writes() {
176 const BLOCK_SIZE: usize = 512;
177 let device = Arc::new(FakeDevice::new(8, BLOCK_SIZE as u32));
178
179 let block_offset = 1;
181 let sub_device = RangedDevice::new(device.clone(), block_offset, 3)
182 .expect("failed to create new RangedDevice");
183
184 let mut invalid_buffer = sub_device.allocate_buffer(4 * BLOCK_SIZE).await;
185 invalid_buffer.as_mut_slice().copy_from_slice(&[3; 2048]);
186 sub_device
187 .write(0, invalid_buffer.as_ref())
188 .await
189 .expect_err("unexpectedly passed writing a buffer that is too big");
190
191 let mut write_buffer = sub_device.allocate_buffer(BLOCK_SIZE).await;
192 write_buffer.as_mut_slice().copy_from_slice(&[3; 512]);
193 let write_block_offset = 2;
194 sub_device
195 .write(write_block_offset * BLOCK_SIZE as u64, write_buffer.as_ref())
196 .await
197 .expect("failed to write to RangedDevice");
198
199 let mut read_buffer = device.allocate_buffer(BLOCK_SIZE).await;
201 device
202 .read((block_offset + write_block_offset) * BLOCK_SIZE as u64, read_buffer.as_mut())
203 .await
204 .expect("failed to read from device");
205 assert_eq!(read_buffer.as_slice(), [3; 512]);
206 }
207}