1use crate::Device;
6use crate::buffer::{BufferFuture, BufferRef, MutableBufferRef};
7use crate::buffer_allocator::{BufferAllocator, BufferSource};
8use anyhow::{Error, bail, ensure};
9use async_trait::async_trait;
10use block_client::{
11 BlockClient, BlockDeviceFlag, BufferSlice, MutableBufferSlice, ReadOptions, VmoId, WriteOptions,
12};
13use std::ops::Range;
14use zx::Status;
15
16pub struct BlockDevice<T> {
18 allocator: BufferAllocator,
19 remote: T,
20 read_only: bool,
21 vmoid: VmoId,
22}
23
24const TRANSFER_VMO_SIZE: usize = 128 * 1024 * 1024;
25
26impl<T: BlockClient> BlockDevice<T> {
27 pub async fn new(remote: T, read_only: bool) -> Result<Self, Error> {
29 let buffer_source = BufferSource::new(TRANSFER_VMO_SIZE);
30 let vmoid = unsafe { remote.attach_vmo(buffer_source.vmo()) }.await?;
33 let allocator = BufferAllocator::new(remote.block_size() as usize, buffer_source);
34 Ok(Self { allocator, remote, read_only, vmoid })
35 }
36
37 async fn read_with_opts_internal(
38 &self,
39 offset: u64,
40 buffer: MutableBufferRef<'_>,
41 read_opts: ReadOptions,
42 ) -> Result<(), Error> {
43 if buffer.len() == 0 {
44 return Ok(());
45 }
46 ensure!(self.vmoid.is_valid(), Status::INVALID_ARGS);
47 ensure!(offset % (self.block_size() as u64) == 0, Status::INVALID_ARGS);
48 ensure!(buffer.range().start % (self.block_size() as usize) == 0, Status::INVALID_ARGS);
49 ensure!(buffer.range().end % (self.block_size() as usize) == 0, Status::INVALID_ARGS);
50 Ok(self
51 .remote
52 .read_at_with_opts(
53 MutableBufferSlice::new_with_vmo_id(
54 &self.vmoid,
55 buffer.range().start as u64,
56 buffer.len() as u64,
57 ),
58 offset,
59 read_opts,
60 )
61 .await?)
62 }
63
64 async fn write_with_opts_internal(
65 &self,
66 offset: u64,
67 buffer: BufferRef<'_>,
68 opts: WriteOptions,
69 ) -> Result<(), Error> {
70 if self.read_only {
71 bail!(Status::ACCESS_DENIED);
72 }
73 if buffer.len() == 0 {
74 return Ok(());
75 }
76 ensure!(self.vmoid.is_valid(), "Device is closed");
77 ensure!(offset % (self.block_size() as u64) == 0, Status::INVALID_ARGS);
78 ensure!(buffer.range().start % (self.block_size() as usize) == 0, Status::INVALID_ARGS);
79 ensure!(buffer.range().end % (self.block_size() as usize) == 0, Status::INVALID_ARGS);
80 Ok(self
81 .remote
82 .write_at_with_opts(
83 BufferSlice::new_with_vmo_id(
84 &self.vmoid,
85 buffer.range().start as u64,
86 buffer.len() as u64,
87 ),
88 offset,
89 opts,
90 )
91 .await?)
92 }
93}
94
95#[async_trait]
96impl<T: BlockClient> Device for BlockDevice<T> {
97 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
98 self.allocator.allocate_buffer(size)
99 }
100
101 fn clean_transfer_buffer(&self) {
102 self.allocator.clean_transfer_buffer();
103 }
104
105 fn block_size(&self) -> u32 {
106 self.remote.block_size()
107 }
108
109 fn block_count(&self) -> u64 {
110 self.remote.block_count()
111 }
112
113 async fn read_with_opts(
114 &self,
115 offset: u64,
116 mut buffer: MutableBufferRef<'_>,
117 read_opts: ReadOptions,
118 ) -> Result<(), Error> {
119 if buffer.allocator_id() != self.allocator.identifier() {
120 let mut temp_buf = self.allocator.allocate_buffer(buffer.len()).await;
122 self.read_with_opts_internal(offset, temp_buf.as_mut(), read_opts).await?;
123 buffer.as_mut_ptr_slice().copy_from_ptr_slice(temp_buf.as_ptr_slice());
124 Ok(())
125 } else {
126 self.read_with_opts_internal(offset, buffer, read_opts).await
127 }
128 }
129
130 async fn write_with_opts(
131 &self,
132 offset: u64,
133 buffer: BufferRef<'_>,
134 opts: WriteOptions,
135 ) -> Result<(), Error> {
136 if buffer.allocator_id() != self.allocator.identifier() {
137 let mut temp_buf = self.allocator.allocate_buffer(buffer.len()).await;
139 temp_buf.as_mut().as_mut_ptr_slice().copy_from_ptr_slice(buffer.as_ptr_slice());
140 self.write_with_opts_internal(offset, temp_buf.as_ref(), opts).await
141 } else {
142 self.write_with_opts_internal(offset, buffer, opts).await
143 }
144 }
145
146 async fn trim(&self, range: Range<u64>) -> Result<(), Error> {
147 if self.read_only {
148 bail!(Status::ACCESS_DENIED);
149 }
150 ensure!(range.start % (self.block_size() as u64) == 0, Status::INVALID_ARGS);
151 ensure!(range.end % (self.block_size() as u64) == 0, Status::INVALID_ARGS);
152 Ok(self.remote.trim(range).await?)
153 }
154
155 async fn close(&self) -> Result<(), Error> {
156 let _ = self.vmoid.take().into_id();
158 Ok(self.remote.close().await?)
159 }
160
161 async fn flush(&self) -> Result<(), Error> {
162 Ok(self.remote.flush().await?)
163 }
164
165 fn is_read_only(&self) -> bool {
166 self.read_only
167 }
168
169 fn supports_trim(&self) -> bool {
170 self.remote.block_flags().contains(BlockDeviceFlag::TRIM_SUPPORT)
171 }
172
173 async fn connect_mapper(
174 &self,
175 server_end: fidl::endpoints::ServerEnd<fidl_fuchsia_storage_block::MapperMarker>,
176 ) -> Result<(), Status> {
177 self.remote.connect_mapper(server_end).await
178 }
179
180 async fn register_key(&self, key_token: zx::EventPair) -> Result<u8, Status> {
181 self.remote.register_key(key_token).await
182 }
183}
184
185impl<T> Drop for BlockDevice<T> {
186 fn drop(&mut self) {
187 let _ = self.vmoid.take().into_id();
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use crate::Device;
196 use crate::block_device::BlockDevice;
197 use fake_block_client::FakeBlockClient;
198 use zx::Status;
199
200 #[fuchsia::test]
201 async fn test_lifecycle() {
202 let device =
203 BlockDevice::new(FakeBlockClient::new(1024, 1024), false).await.expect("new failed");
204
205 {
206 let _buf = device.allocate_buffer(8192).await;
207 }
208
209 device.close().await.expect("Close failed");
210 }
211
212 #[fuchsia::test]
213 async fn test_read_write_buffer() {
214 let device =
215 BlockDevice::new(FakeBlockClient::new(1024, 1024), false).await.expect("new failed");
216
217 {
218 let mut buf1 = device.allocate_buffer(8192).await;
219 let mut buf2 = device.allocate_buffer(1024).await;
220 buf1.fill(0xaa);
221 buf2.fill(0xbb);
222 device.write(65536, buf1.as_ref()).await.expect("Write failed");
223 device.write(65536 + 8192, buf2.as_ref()).await.expect("Write failed");
224 }
225 {
226 let mut buf = device.allocate_buffer(8192 + 1024).await;
227 device.read(65536, buf.as_mut()).await.expect("Read failed");
228 let mut data = vec![0u8; 8192 + 1024];
229 buf.copy_to_slice(&mut data);
230 assert_eq!(data[..8192], vec![0xaa as u8; 8192]);
231 assert_eq!(data[8192..], vec![0xbb as u8; 1024]);
232 }
233
234 device.close().await.expect("Close failed");
235 }
236
237 #[fuchsia::test]
238 async fn test_read_only() {
239 let device =
240 BlockDevice::new(FakeBlockClient::new(1024, 1024), true).await.expect("new failed");
241 let mut buf1 = device.allocate_buffer(8192).await;
242 buf1.fill(0xaa);
243 let err = device.write(65536, buf1.as_ref()).await.expect_err("Write succeeded");
244 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::ACCESS_DENIED);
245 }
246
247 #[fuchsia::test]
248 async fn test_unaligned_access() {
249 let device =
250 BlockDevice::new(FakeBlockClient::new(1024, 1024), false).await.expect("new failed");
251 let mut buf1 = device.allocate_buffer(device.block_size() as usize * 2).await;
252 buf1.fill(0xaa);
253
254 {
256 let err = device.write(1, buf1.as_ref()).await.expect_err("Write succeeded");
257 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
258 }
259 {
260 let err = device
261 .write(0, buf1.subslice(1..(device.block_size() as usize + 1)))
262 .await
263 .expect_err("Write succeeded");
264 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
265 }
266 {
267 let err = device
268 .write(0, buf1.subslice(1..device.block_size() as usize))
269 .await
270 .expect_err("Write succeeded");
271 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
272 }
273 {
274 let err = device
275 .write(0, buf1.subslice(0..(device.block_size() as usize + 1)))
276 .await
277 .expect_err("Write succeeded");
278 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
279 }
280
281 {
283 let err = device.read(1, buf1.as_mut()).await.expect_err("Read succeeded");
284 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
285 }
286 {
287 let err = device
288 .read(0, buf1.subslice_mut(1..(device.block_size() as usize + 1)))
289 .await
290 .expect_err("Read succeeded");
291 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
292 }
293 {
294 let err = device
295 .read(0, buf1.subslice_mut(1..device.block_size() as usize))
296 .await
297 .expect_err("Read succeeded");
298 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
299 }
300 {
301 let err = device
302 .read(0, buf1.subslice_mut(0..(device.block_size() as usize + 1)))
303 .await
304 .expect_err("Read succeeded");
305 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
306 }
307
308 {
310 let err = device.trim(1..device.block_size() as u64).await.expect_err("Read succeeded");
311 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
312 }
313 {
314 let err =
315 device.trim(1..(device.block_size() as u64 + 1)).await.expect_err("Read succeeded");
316 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
317 }
318 {
319 let err =
320 device.trim(0..(device.block_size() as u64 + 1)).await.expect_err("Read succeeded");
321 assert_eq!(err.root_cause().downcast_ref::<Status>().unwrap(), &Status::INVALID_ARGS);
322 }
323 }
324
325 #[fuchsia::test]
326 async fn test_foreign_buffer_read_write() {
327 let device1 =
328 BlockDevice::new(FakeBlockClient::new(1024, 1024), false).await.expect("new failed");
329 let device2 =
330 BlockDevice::new(FakeBlockClient::new(1024, 1024), false).await.expect("new failed");
331
332 let mut foreign_buf = device2.allocate_buffer(8192).await;
334 foreign_buf.fill(0xaa);
335 device1.write(0, foreign_buf.as_ref()).await.expect("Foreign write failed");
336
337 let mut foreign_read_buf = device2.allocate_buffer(8192).await;
339 device1.read(0, foreign_read_buf.as_mut()).await.expect("Foreign read failed");
340
341 let mut data = vec![0u8; 8192];
342 foreign_read_buf.copy_to_slice(&mut data);
343 assert_eq!(data, vec![0xaa; 8192]);
344 }
345}