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::sync::{Arc, OnceLock};
24
25pub mod buffer;
26pub mod buffer_allocator;
27
28#[cfg(target_os = "fuchsia")]
29pub mod block_device;
30
31#[cfg(target_family = "unix")]
32pub mod file_backed_device;
33
34pub mod fake_device;
35
36pub mod ranged_device;
37
38#[async_trait]
39pub trait Device: Send + Sync {
41 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_>;
45
46 fn block_size(&self) -> u32;
48
49 fn block_count(&self) -> u64;
51
52 fn size(&self) -> u64 {
54 self.block_size() as u64 * self.block_count()
55 }
56
57 async fn read(&self, offset: u64, buffer: MutableBufferRef<'_>) -> Result<(), Error> {
59 self.read_with_opts(offset, buffer, ReadOptions::default()).await
60 }
61
62 async fn read_with_opts(
64 &self,
65 offset: u64,
66 buffer: MutableBufferRef<'_>,
67 read_opts: ReadOptions,
68 ) -> Result<(), Error>;
69
70 async fn write(&self, offset: u64, buffer: BufferRef<'_>) -> Result<(), Error> {
72 self.write_with_opts(offset, buffer, WriteOptions::default()).await
73 }
74
75 async fn write_with_opts(
77 &self,
78 offset: u64,
79 buffer: BufferRef<'_>,
80 write_opts: WriteOptions,
81 ) -> Result<(), Error>;
82
83 async fn trim(&self, range: Range<u64>) -> Result<(), Error>;
85
86 async fn close(&self) -> Result<(), Error>;
89
90 async fn flush(&self) -> Result<(), Error>;
92
93 fn barrier(&self);
95
96 fn reopen(&self, _read_only: bool) {
98 unreachable!();
99 }
100 fn is_read_only(&self) -> bool;
102
103 fn supports_trim(&self) -> bool;
105
106 fn snapshot(&self) -> Result<DeviceHolder, Error> {
108 bail!("Not supported");
109 }
110
111 fn discard_random_since_last_flush(&self) -> Result<(), Error> {
113 bail!("Not supported");
114 }
115
116 fn poison(&self) -> Result<(), Error> {
118 bail!("Not supported");
119 }
120}
121
122pub struct DeviceHolder {
129 device: ManuallyDrop<Arc<dyn Device>>,
130 on_drop: OnceLock<Sender<DeviceHolder>>,
131}
132
133impl DeviceHolder {
134 pub fn new(device: impl Device + 'static) -> Self {
135 DeviceHolder { device: ManuallyDrop::new(Arc::new(device)), on_drop: OnceLock::new() }
136 }
137
138 pub fn ensure_unique(&self) {
141 assert_eq!(Arc::strong_count(&self.device), 1);
142 }
143
144 pub fn take_when_dropped(&self) -> impl Future<Output = DeviceHolder> + use<> {
145 let (sender, receiver) = channel::<DeviceHolder>();
146 self.on_drop
147 .set(sender)
148 .unwrap_or_else(|_| panic!("take_when_dropped should only be called once"));
149 async { receiver.await.unwrap() }
150 }
151}
152
153impl Drop for DeviceHolder {
154 fn drop(&mut self) {
155 if let Some(sender) = self.on_drop.take() {
156 let device = ManuallyDrop::new(unsafe { ManuallyDrop::take(&mut self.device) });
158 let _ = sender.send(DeviceHolder { device, on_drop: OnceLock::new() });
160 } else {
161 unsafe { ManuallyDrop::drop(&mut self.device) }
163 }
164 }
165}
166
167impl Deref for DeviceHolder {
168 type Target = Arc<dyn Device>;
169
170 fn deref(&self) -> &Self::Target {
171 &self.device
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use super::DeviceHolder;
178 use crate::fake_device::FakeDevice;
179
180 #[fuchsia::test]
181 async fn test_take_when_dropped() {
182 let holder = DeviceHolder::new(FakeDevice::new(1, 512));
183 let fut = holder.take_when_dropped();
184 std::mem::drop(holder);
185 fut.await.ensure_unique();
186 }
187}