fuchsia_storage_benchmarks/filesystems/
fxfs.rs1use crate::filesystems::FsManagementFilesystemInstance;
6use async_trait::async_trait;
7use fidl::endpoints::ClientEnd;
8use fidl_fuchsia_fxfs::{CryptManagementMarker, CryptMarker, KeyPurpose};
9use fuchsia_component::client::{connect_channel_to_protocol, connect_to_protocol_at_dir_root};
10
11use std::path::Path;
12use std::sync::{Arc, Once};
13use storage_benchmarks::{
14 BlockDeviceConfig, BlockDeviceFactory, CacheClearableFilesystem, Filesystem, FilesystemConfig,
15};
16
17#[derive(Clone)]
19pub struct Fxfs {
20 volume_size: u64,
21}
22
23impl Fxfs {
24 pub fn new(volume_size: u64) -> Self {
25 Fxfs { volume_size }
26 }
27}
28
29#[async_trait]
30impl FilesystemConfig for Fxfs {
31 type Filesystem = FxfsInstance;
32
33 async fn start_filesystem(
34 &self,
35 block_device_factory: &dyn BlockDeviceFactory,
36 ) -> FxfsInstance {
37 let block_device = block_device_factory
38 .create_block_device(&BlockDeviceConfig {
39 requires_fvm: false,
40 use_zxcrypt: false,
41 volume_size: Some(self.volume_size),
42 })
43 .await;
44 FxfsInstance {
45 fxfs: FsManagementFilesystemInstance::new(
46 fs_management::Fxfs::default(),
47 block_device,
48 Some(Arc::new(get_crypt_client)),
49 false,
50 )
51 .await,
52 }
53 }
54
55 fn name(&self) -> String {
56 "fxfs".to_owned()
57 }
58}
59
60fn get_crypt_client() -> ClientEnd<CryptMarker> {
61 static CRYPT_CLIENT_INITIALIZER: Once = Once::new();
62 CRYPT_CLIENT_INITIALIZER.call_once(|| {
63 let (client_end, server_end) = zx::Channel::create();
64 connect_channel_to_protocol::<CryptManagementMarker>(server_end)
65 .expect("Failed to connect to the crypt management service");
66 let crypt_management_service =
67 fidl_fuchsia_fxfs::CryptManagementSynchronousProxy::new(client_end);
68
69 let mut key = [0; 32];
70 zx::cprng_draw(&mut key);
71 let wrapping_key_id_0 = [0; 16];
72 match crypt_management_service
73 .add_wrapping_key(&wrapping_key_id_0, &key, zx::MonotonicInstant::INFINITE)
74 .expect("FIDL failed")
75 .map_err(zx::Status::from_raw)
76 {
77 Ok(()) => {}
78 Err(zx::Status::ALREADY_EXISTS) => {
79 return;
82 }
83 Err(e) => panic!("add_wrapping_key failed: {:?}", e),
84 };
85 zx::cprng_draw(&mut key);
86 let mut wrapping_key_id_1 = [0; 16];
87 wrapping_key_id_1[0] = 1;
88 crypt_management_service
89 .add_wrapping_key(&wrapping_key_id_1, &key, zx::MonotonicInstant::INFINITE)
90 .expect("FIDL failed")
91 .map_err(zx::Status::from_raw)
92 .expect("add_wrapping_key failed");
93 crypt_management_service
94 .set_active_key(KeyPurpose::Data, &wrapping_key_id_0, zx::MonotonicInstant::INFINITE)
95 .expect("FIDL failed")
96 .map_err(zx::Status::from_raw)
97 .expect("set_active_key failed");
98 crypt_management_service
99 .set_active_key(
100 KeyPurpose::Metadata,
101 &wrapping_key_id_1,
102 zx::MonotonicInstant::INFINITE,
103 )
104 .expect("FIDL failed")
105 .map_err(zx::Status::from_raw)
106 .expect("set_active_key failed");
107 });
108 let (client_end, server_end) = fidl::endpoints::create_endpoints();
109 connect_channel_to_protocol::<CryptMarker>(server_end.into())
110 .expect("Failed to connect to crypt service");
111 client_end
112}
113
114pub struct FxfsInstance {
115 fxfs: FsManagementFilesystemInstance,
116}
117
118impl FxfsInstance {
119 async fn flush_journal(&self) {
120 connect_to_protocol_at_dir_root::<fidl_fuchsia_fxfs::DebugMarker>(
121 self.fxfs.exposed_services_dir(),
122 )
123 .expect("Connecting to debug protocol")
124 .compact()
125 .await
126 .expect("Sending journal flush message")
127 .map_err(zx::Status::from_raw)
128 .expect("Journal flush");
129 }
130}
131
132#[async_trait]
133impl Filesystem for FxfsInstance {
134 async fn shutdown(self) {
135 self.fxfs.shutdown().await
136 }
137
138 fn benchmark_dir(&self) -> &Path {
139 self.fxfs.benchmark_dir()
140 }
141}
142
143#[async_trait]
144impl CacheClearableFilesystem for FxfsInstance {
145 async fn clear_cache(&mut self) {
146 self.flush_journal().await;
150 self.fxfs.clear_cache().await
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::Fxfs;
157 use crate::filesystems::testing::check_filesystem;
158
159 #[fuchsia::test]
160 async fn start_fxfs() {
161 check_filesystem(Fxfs { volume_size: 4 * 1024 * 1024 }).await;
162 }
163}