fuchsia_storage_benchmarks/filesystems/
fxblob.rs1use crate::filesystems::{BlobFilesystem, FsManagementFilesystemInstance};
6use async_trait::async_trait;
7use blob_pager_and_verifier::BlobPagerAndVerifier;
8use fidl_fuchsia_fxfs::{BlobCreatorMarker, BlobCreatorProxy, BlobReaderMarker, BlobReaderProxy};
9use fidl_fuchsia_io as fio;
10use fidl_fuchsia_storage_block as fblock;
11use fidl_fuchsia_storage_mapping as fmapping;
12use fuchsia_component::client::{connect_to_protocol_at_dir_root, connect_to_protocol_at_dir_svc};
13use fuchsia_merkle::Hash;
14use std::path::Path;
15use storage_benchmarks::{
16 BlockDeviceConfig, BlockDeviceFactory, CacheClearableFilesystem, Filesystem, FilesystemConfig,
17};
18
19#[derive(Clone, Default)]
21pub struct Fxblob {
22 use_driver_blob_paging: bool,
23}
24
25impl Fxblob {
26 pub fn new() -> Self {
27 Self { use_driver_blob_paging: false }
28 }
29
30 pub fn with_driver_paging() -> Self {
31 Self { use_driver_blob_paging: true }
32 }
33}
34
35#[async_trait]
36impl FilesystemConfig for Fxblob {
37 type Filesystem = FxblobInstance;
38
39 async fn start_filesystem(
40 &self,
41 block_device_factory: &dyn BlockDeviceFactory,
42 ) -> FxblobInstance {
43 let block_device = block_device_factory
44 .create_block_device(&BlockDeviceConfig {
45 requires_fvm: false,
46 use_zxcrypt: false,
47 volume_size: Some(104 * 1024 * 1024),
48 })
49 .await;
50 let fxblob = FsManagementFilesystemInstance::new(
51 || fs_management::Fxfs { allow_type3_blobs: true, ..Default::default() },
52 block_device,
53 None,
54 true,
55 )
56 .await;
57 let blob_creator =
58 connect_to_protocol_at_dir_svc::<BlobCreatorMarker>(fxblob.exposed_dir())
59 .expect("failed to connect to the BlobCreator protocol");
60 let blob_reader = connect_to_protocol_at_dir_svc::<BlobReaderMarker>(fxblob.exposed_dir())
61 .expect("failed to connect to the BlobReader protocol");
62 let pager_and_verifier = if self.use_driver_blob_paging {
63 Some(FxblobInstance::create_pager_and_verifier(&fxblob).await)
64 } else {
65 None
66 };
67 FxblobInstance { blob_creator, blob_reader, pager_and_verifier, fxblob }
68 }
69
70 fn name(&self) -> String {
71 if self.use_driver_blob_paging { "fxblob_driver".to_owned() } else { "fxblob".to_owned() }
72 }
73}
74
75pub struct FxblobInstance {
76 blob_creator: BlobCreatorProxy,
77 blob_reader: BlobReaderProxy,
78 pager_and_verifier: Option<BlobPagerAndVerifier>,
79 fxblob: FsManagementFilesystemInstance,
80}
81
82impl FxblobInstance {
83 async fn create_pager_and_verifier(
84 fxblob: &FsManagementFilesystemInstance,
85 ) -> BlobPagerAndVerifier {
86 let mapping_provider =
87 connect_to_protocol_at_dir_svc::<fmapping::MappingProviderMarker>(fxblob.exposed_dir())
88 .expect("failed to connect to the MappingProvider protocol");
89 let block_proxy = fxblob
90 .block_device
91 .connector()
92 .connect_block()
93 .expect("failed to connect to block device")
94 .into_proxy();
95 let (mapper, mapper_server) = fidl::endpoints::create_proxy::<fblock::MapperMarker>();
96 block_proxy
97 .connect_mapper(mapper_server)
98 .await
99 .expect("FIDL error on ConnectMapper")
100 .expect("ConnectMapper failed");
101 BlobPagerAndVerifier::new(&mapping_provider, &mapper)
102 .await
103 .expect("failed to initialize BlobPagerAndVerifier")
104 }
105
106 pub fn connect_to_debug(&self) -> fidl_fuchsia_fxfs::DebugProxy {
107 connect_to_protocol_at_dir_root::<fidl_fuchsia_fxfs::DebugMarker>(
108 self.fxblob.exposed_services_dir(),
109 )
110 .expect("failed to connect to Debug protocol")
111 }
112
113 pub fn clear_unreferenced_blobs(&self) {
114 if let Some(pager) = &self.pager_and_verifier {
115 pager.clear_cache();
116 }
117 }
118}
119
120#[async_trait]
121impl Filesystem for FxblobInstance {
122 async fn shutdown(self) {
123 drop(self.pager_and_verifier);
124 self.fxblob.shutdown().await
125 }
126
127 fn benchmark_dir(&self) -> &Path {
128 self.fxblob.benchmark_dir()
129 }
130}
131
132#[async_trait]
133impl CacheClearableFilesystem for FxblobInstance {
134 async fn clear_cache(&mut self) {
135 let use_driver_blob_paging = self.pager_and_verifier.take().is_some();
136 let () = self.fxblob.clear_cache().await;
137 self.blob_creator =
138 connect_to_protocol_at_dir_svc::<BlobCreatorMarker>(self.fxblob.exposed_dir())
139 .expect("failed to connect to the BlobCreator protocol");
140 self.blob_reader =
141 connect_to_protocol_at_dir_svc::<BlobReaderMarker>(self.fxblob.exposed_dir())
142 .expect("failed to connect to the BlobReader protocol");
143 if use_driver_blob_paging {
144 self.pager_and_verifier = Some(Self::create_pager_and_verifier(&self.fxblob).await);
145 }
146 }
147}
148
149#[async_trait]
150impl BlobFilesystem for FxblobInstance {
151 async fn get_vmo(&self, name: &Hash) -> zx::Vmo {
152 if let Some(pager) = &self.pager_and_verifier {
153 pager.create_vmo(&**name).await.expect("failed to get vmo from BlobPagerAndVerifier")
154 } else {
155 self.blob_reader()
156 .get_vmo(&*name)
157 .await
158 .expect("transport error on BlobReader.GetVmo")
159 .expect("failed to get vmo")
160 }
161 }
162
163 fn blob_creator(&self) -> &BlobCreatorProxy {
164 &self.blob_creator
165 }
166
167 fn blob_reader(&self) -> &BlobReaderProxy {
168 &self.blob_reader
169 }
170
171 fn exposed_dir(&self) -> &fio::DirectoryProxy {
172 self.fxblob.exposed_dir()
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::Fxblob;
179 use crate::filesystems::testing::check_blob_filesystem;
180
181 #[fuchsia::test]
182 async fn start_fxblob_new() {
183 check_blob_filesystem(Fxblob::new()).await;
184 }
185}