Skip to main content

fuchsia_storage_benchmarks/filesystems/
fxblob.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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/// Config object for starting Fxblob instances.
20#[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            /*as_blob=*/ 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}