fuchsia_storage_benchmarks/filesystems/
pkgdir.rs1use crate::filesystems::{BlobFilesystem, Blobfs, CacheClearableFilesystem, Fxblob};
6use async_trait::async_trait;
7use fidl::endpoints::DiscoverableProtocolMarker;
8use fidl_fuchsia_fxfs::{BlobCreatorProxy, BlobReaderProxy};
9use fidl_fuchsia_io as fio;
10use fuchsia_component_test::{Capability, ChildOptions, RealmBuilder, RealmInstance, Ref, Route};
11use futures::future::FutureExt;
12use std::path::Path;
13use storage_benchmarks::{BlockDeviceFactory, Filesystem, FilesystemConfig};
14#[derive(Clone)]
18pub struct PkgDirTest {
19 use_fxblob: bool,
20}
21
22impl PkgDirTest {
23 pub fn new_fxblob() -> Self {
24 PkgDirTest { use_fxblob: true }
25 }
26
27 pub fn new_blobfs() -> Self {
28 PkgDirTest { use_fxblob: false }
29 }
30}
31
32#[async_trait]
33impl FilesystemConfig for PkgDirTest {
34 type Filesystem = PkgDirInstance;
35
36 async fn start_filesystem(
37 &self,
38 block_device_factory: &dyn BlockDeviceFactory,
39 ) -> PkgDirInstance {
40 let fs = if self.use_fxblob {
41 Box::new(Fxblob::new().start_filesystem(block_device_factory).await)
42 as Box<dyn BlobFilesystem>
43 } else {
44 Box::new(Blobfs.start_filesystem(block_device_factory).await) as Box<dyn BlobFilesystem>
45 };
46
47 let (clone, server_end) = fidl::endpoints::create_proxy::<fio::DirectoryMarker>();
48 fs.exposed_dir()
49 .clone(server_end.into_channel().into())
50 .expect("connect to blob volume exposed dir");
51 let realm = PkgDirRealm::new(self.use_fxblob, clone).await;
52 PkgDirInstance { fs, realm, use_fxblob: self.use_fxblob }
53 }
54
55 fn name(&self) -> String {
56 let fs = if self.use_fxblob { "fxblob" } else { "blobfs" };
57 format!("{}-pkgdir", fs)
58 }
59}
60
61pub struct PkgDirInstance {
62 fs: Box<dyn BlobFilesystem>,
63 realm: PkgDirRealm,
64 use_fxblob: bool,
65}
66
67impl PkgDirInstance {
68 pub fn pkgdir_proxy(&self) -> fidl_test_pkgdir::PkgDirProxy {
69 self.realm.realm().root.connect_to_protocol_at_exposed_dir().unwrap()
70 }
71}
72
73#[async_trait]
74impl Filesystem for PkgDirInstance {
75 async fn shutdown(self) {
76 self.fs.shutdown_boxed().await
77 }
78
79 fn benchmark_dir(&self) -> &Path {
80 self.fs.benchmark_dir()
81 }
82}
83
84#[async_trait]
85impl CacheClearableFilesystem for PkgDirInstance {
86 async fn clear_cache(&mut self) {
87 self.fs.clear_cache().await;
88 let (clone, server_end) = fidl::endpoints::create_proxy::<fio::DirectoryMarker>();
89 self.fs
90 .exposed_dir()
91 .clone(server_end.into_channel().into())
92 .expect("connect to blob volume exposed dir");
93 self.realm = PkgDirRealm::new(self.use_fxblob, clone).await
94 }
95}
96
97#[async_trait]
98impl BlobFilesystem for PkgDirInstance {
99 fn blob_creator(&self) -> &BlobCreatorProxy {
100 self.fs.blob_creator()
101 }
102
103 fn blob_reader(&self) -> &BlobReaderProxy {
104 self.fs.blob_reader()
105 }
106
107 fn exposed_dir(&self) -> &fio::DirectoryProxy {
108 self.fs.exposed_dir()
109 }
110}
111
112pub struct PkgDirRealm {
113 pub realm: RealmInstance,
114}
115
116impl PkgDirRealm {
117 pub async fn new(fxblob: bool, exposed_dir: fio::DirectoryProxy) -> Self {
118 let builder = RealmBuilder::new().await.unwrap();
119 let pkgdir = builder
120 .add_child("pkgdir-component", "#meta/pkgdir-component.cm", ChildOptions::new())
121 .await
122 .unwrap();
123 builder.init_mutable_config_from_package(&pkgdir).await.unwrap();
124 let exposed_dir = vfs::pseudo_directory! {
125 "blob" => vfs::remote::remote_dir(exposed_dir),
126 };
127 let service_reflector = builder
128 .add_local_child(
129 "service_reflector",
130 move |handles| {
131 let scope = vfs::execution_scope::ExecutionScope::new();
132 vfs::directory::serve_on(
133 exposed_dir.clone(),
134 fio::PERM_READABLE,
135 scope.clone(),
136 handles.outgoing_dir,
137 );
138 async move {
139 scope.wait().await;
140 Ok(())
141 }
142 .boxed()
143 },
144 ChildOptions::new(),
145 )
146 .await
147 .unwrap();
148 builder
149 .add_route(
150 Route::new()
151 .capability(Capability::protocol::<fidl_test_pkgdir::PkgDirMarker>())
152 .from(&pkgdir)
153 .to(Ref::parent()),
154 )
155 .await
156 .unwrap();
157 builder
158 .add_route(
159 Route::new()
160 .capability(
161 Capability::protocol::<fidl_fuchsia_tracing_provider::RegistryMarker>(),
162 )
163 .from(Ref::parent())
164 .to(&pkgdir),
165 )
166 .await
167 .unwrap();
168 builder
169 .add_route(
170 Route::new()
171 .capability(
172 Capability::directory("blob-exec")
173 .path("/blob/root")
174 .rights(fio::R_STAR_DIR),
175 )
176 .from(&service_reflector)
177 .to(&pkgdir),
178 )
179 .await
180 .unwrap();
181 let svc_path = if fxblob {
182 format!("/blob/svc/{}", fidl_fuchsia_fxfs::BlobReaderMarker::PROTOCOL_NAME)
183 } else {
184 format!("/blob/{}", fidl_fuchsia_fxfs::BlobReaderMarker::PROTOCOL_NAME)
185 };
186 builder
187 .add_route(
188 Route::new()
189 .capability(
190 Capability::protocol::<fidl_fuchsia_fxfs::BlobReaderMarker>()
191 .path(svc_path),
192 )
193 .from(&service_reflector)
194 .to(&pkgdir),
195 )
196 .await
197 .unwrap();
198 let realm = builder.build().await.expect("realm build failed");
199 Self { realm }
200 }
201
202 fn realm(&self) -> &RealmInstance {
203 &self.realm
204 }
205}