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