1use crate::buffer::{BufferFuture, BufferRef, MutableBufferRef};
15use anyhow::{Error, bail};
16use async_trait::async_trait;
17pub use block_protocol::{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
36#[async_trait]
37pub trait Device: Send + Sync {
39 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_>;
43
44 fn block_size(&self) -> u32;
46
47 fn block_count(&self) -> u64;
49
50 fn size(&self) -> u64 {
52 self.block_size() as u64 * self.block_count()
53 }
54
55 async fn read(&self, offset: u64, buffer: MutableBufferRef<'_>) -> Result<(), Error> {
57 self.read_with_opts(offset, buffer, ReadOptions::default()).await
58 }
59
60 async fn read_with_opts(
62 &self,
63 offset: u64,
64 buffer: MutableBufferRef<'_>,
65 read_opts: ReadOptions,
66 ) -> Result<(), Error>;
67
68 async fn write(&self, offset: u64, buffer: BufferRef<'_>) -> Result<(), Error> {
70 self.write_with_opts(offset, buffer, WriteOptions::default()).await
71 }
72
73 async fn write_with_opts(
75 &self,
76 offset: u64,
77 buffer: BufferRef<'_>,
78 write_opts: WriteOptions,
79 ) -> Result<(), Error>;
80
81 async fn trim(&self, range: Range<u64>) -> Result<(), Error>;
83
84 async fn close(&self) -> Result<(), Error>;
87
88 async fn flush(&self) -> Result<(), Error>;
90
91 fn barrier(&self);
93
94 fn reopen(&self, _read_only: bool) {
96 unreachable!();
97 }
98 fn is_read_only(&self) -> bool;
100
101 fn supports_trim(&self) -> bool;
103
104 fn snapshot(&self) -> Result<DeviceHolder, Error> {
106 bail!("Not supported");
107 }
108
109 fn discard_random_since_last_flush(&self) -> Result<(), Error> {
111 bail!("Not supported");
112 }
113
114 fn poison(&self) -> Result<(), Error> {
116 bail!("Not supported");
117 }
118}
119
120pub struct DeviceHolder {
127 device: ManuallyDrop<Arc<dyn Device>>,
128 on_drop: OnceLock<Sender<DeviceHolder>>,
129}
130
131impl DeviceHolder {
132 pub fn new(device: impl Device + 'static) -> Self {
133 DeviceHolder { device: ManuallyDrop::new(Arc::new(device)), on_drop: OnceLock::new() }
134 }
135
136 pub fn ensure_unique(&self) {
139 assert_eq!(Arc::strong_count(&self.device), 1);
140 }
141
142 pub fn take_when_dropped(&self) -> impl Future<Output = DeviceHolder> {
143 let (sender, receiver) = channel::<DeviceHolder>();
144 self.on_drop
145 .set(sender)
146 .unwrap_or_else(|_| panic!("take_when_dropped should only be called once"));
147 async { receiver.await.unwrap() }
148 }
149}
150
151impl Drop for DeviceHolder {
152 fn drop(&mut self) {
153 if let Some(sender) = self.on_drop.take() {
154 let device = ManuallyDrop::new(unsafe { ManuallyDrop::take(&mut self.device) });
156 let _ = sender.send(DeviceHolder { device, on_drop: OnceLock::new() });
158 } else {
159 unsafe { ManuallyDrop::drop(&mut self.device) }
161 }
162 }
163}
164
165impl Deref for DeviceHolder {
166 type Target = Arc<dyn Device>;
167
168 fn deref(&self) -> &Self::Target {
169 &self.device
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::DeviceHolder;
176 use crate::fake_device::FakeDevice;
177
178 #[fuchsia::test]
179 async fn test_take_when_dropped() {
180 let holder = DeviceHolder::new(FakeDevice::new(1, 512));
181 let fut = holder.take_when_dropped();
182 std::mem::drop(holder);
183 fut.await.ensure_unique();
184 }
185}