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