1use crate::buffer::{BufferFuture, BufferRef, MutableBufferRef};
15use anyhow::{Error, bail};
16use async_trait::async_trait;
17pub use block_protocol::{InlineCryptoOptions, ReadOptions, WriteOptions};
19use futures::channel::oneshot::{Sender, channel};
20use std::future::Future;
21use std::mem::ManuallyDrop;
22use std::ops::{Deref, Range};
23use std::pin::Pin;
24use std::sync::{Arc, OnceLock};
25
26pub mod buffer;
27pub mod buffer_allocator;
28
29#[cfg(target_os = "fuchsia")]
30pub mod block_device;
31
32#[cfg(target_family = "unix")]
33pub mod file_backed_device;
34
35pub mod fake_device;
36
37pub mod ranged_device;
38
39#[async_trait]
40pub trait Device: Send + Sync {
42 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_>;
46
47 fn clean_transfer_buffer(&self) {}
49
50 fn block_size(&self) -> u32;
52
53 fn block_count(&self) -> u64;
55
56 fn size(&self) -> u64 {
58 self.block_size() as u64 * self.block_count()
59 }
60
61 fn read<'a>(
63 &'a self,
64 offset: u64,
65 buffer: MutableBufferRef<'a>,
66 ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>> {
67 self.read_with_opts(offset, buffer, ReadOptions::default())
68 }
69
70 async fn read_with_opts(
72 &self,
73 offset: u64,
74 buffer: MutableBufferRef<'_>,
75 read_opts: ReadOptions,
76 ) -> Result<(), Error>;
77
78 fn write<'a>(
80 &'a self,
81 offset: u64,
82 buffer: BufferRef<'a>,
83 ) -> Pin<Box<dyn Future<Output = Result<(), Error>> + Send + 'a>> {
84 self.write_with_opts(offset, buffer, WriteOptions::default())
85 }
86
87 async fn write_with_opts(
89 &self,
90 offset: u64,
91 buffer: BufferRef<'_>,
92 write_opts: WriteOptions,
93 ) -> Result<(), Error>;
94
95 async fn trim(&self, range: Range<u64>) -> Result<(), Error>;
97
98 async fn close(&self) -> Result<(), Error>;
101
102 async fn flush(&self) -> Result<(), Error>;
104
105 fn barrier(&self);
107
108 fn reopen(&self, _read_only: bool) {
110 unreachable!();
111 }
112 fn is_read_only(&self) -> bool;
114
115 fn supports_trim(&self) -> bool;
117
118 fn snapshot(&self) -> Result<DeviceHolder, Error> {
120 bail!("Not supported");
121 }
122
123 fn discard_random_since_last_flush(&self) -> Result<(), Error> {
125 bail!("Not supported");
126 }
127
128 fn poison(&self) -> Result<(), Error> {
130 bail!("Not supported");
131 }
132}
133
134pub struct DeviceHolder {
141 device: ManuallyDrop<Arc<dyn Device>>,
142 on_drop: OnceLock<Sender<DeviceHolder>>,
143}
144
145impl DeviceHolder {
146 pub fn new(device: impl Device + 'static) -> Self {
147 DeviceHolder { device: ManuallyDrop::new(Arc::new(device)), on_drop: OnceLock::new() }
148 }
149
150 pub fn ensure_unique(&self) {
153 assert_eq!(Arc::strong_count(&self.device), 1);
154 }
155
156 pub fn take_when_dropped(&self) -> impl Future<Output = DeviceHolder> + use<> {
157 let (sender, receiver) = channel::<DeviceHolder>();
158 self.on_drop
159 .set(sender)
160 .unwrap_or_else(|_| panic!("take_when_dropped should only be called once"));
161 async { receiver.await.unwrap() }
162 }
163}
164
165impl Drop for DeviceHolder {
166 fn drop(&mut self) {
167 if let Some(sender) = self.on_drop.take() {
168 let device = ManuallyDrop::new(unsafe { ManuallyDrop::take(&mut self.device) });
170 let _ = sender.send(DeviceHolder { device, on_drop: OnceLock::new() });
172 } else {
173 unsafe { ManuallyDrop::drop(&mut self.device) }
175 }
176 }
177}
178
179impl Deref for DeviceHolder {
180 type Target = Arc<dyn Device>;
181
182 fn deref(&self) -> &Self::Target {
183 &self.device
184 }
185}
186
187#[cfg(test)]
188mod tests {
189 use super::DeviceHolder;
190 use crate::fake_device::FakeDevice;
191
192 #[fuchsia::test]
193 async fn test_take_when_dropped() {
194 let holder = DeviceHolder::new(FakeDevice::new(1, 512));
195 let fut = holder.take_when_dropped();
196 std::mem::drop(holder);
197 fut.await.ensure_unique();
198 }
199}