1mod error;
13pub mod filesystem;
14pub mod format;
15pub mod partition;
16
17use crate::filesystem::BlockConnector;
18use fidl_fuchsia_fs_startup::{
19 CompressionAlgorithm, EvictionPolicyOverride, FormatOptions, StartOptions,
20};
21use std::convert::From;
22use std::sync::Arc;
23
24pub use error::{QueryError, ShutdownError};
26
27pub const BLOBFS_TYPE_GUID: [u8; 16] = [
28 0x0e, 0x38, 0x67, 0x29, 0x4c, 0x13, 0xbb, 0x4c, 0xb6, 0xda, 0x17, 0xe7, 0xce, 0x1c, 0xa4, 0x5d,
29];
30pub const DATA_TYPE_GUID: [u8; 16] = [
31 0x0c, 0x5f, 0x18, 0x08, 0x2d, 0x89, 0x8a, 0x42, 0xa7, 0x89, 0xdb, 0xee, 0xc8, 0xf5, 0x5e, 0x6a,
32];
33pub const FVM_TYPE_GUID: [u8; 16] = [
34 0xb8, 0x7c, 0xfd, 0x49, 0x15, 0xdf, 0x73, 0x4e, 0xb9, 0xd9, 0x99, 0x20, 0x70, 0x12, 0x7f, 0x0f,
35];
36
37pub const FVM_TYPE_GUID_STR: &str = "49fd7cb8-df15-4e73-b9d9-992070127f0f";
38
39pub const FS_COLLECTION_NAME: &'static str = "fs-collection";
40
41#[derive(Clone)]
42pub enum ComponentType {
43 StaticChild,
46
47 DynamicChild { collection_name: String },
50}
51
52impl Default for ComponentType {
53 fn default() -> Self {
54 ComponentType::DynamicChild { collection_name: "fs-collection".to_string() }
55 }
56}
57
58pub struct Options<'a> {
59 pub component_name: &'a str,
65
66 pub reuse_component_after_serving: bool,
69
70 pub format_options: FormatOptions,
72
73 pub start_options: StartOptions,
75
76 pub component_type: ComponentType,
78}
79
80pub trait FSConfig: Send + Sync + 'static {
82 fn options(&self) -> Options<'_>;
84
85 fn is_multi_volume(&self) -> bool {
87 false
88 }
89
90 fn disk_format(&self) -> format::DiskFormat {
91 format::DiskFormat::Unknown
92 }
93}
94
95#[derive(Clone)]
101pub enum BlobLayout {
102 DeprecatedPadded,
105
106 Compact,
108}
109
110#[derive(Clone, Default)]
112pub enum BlobCompression {
113 #[default]
114 ZSTDChunked,
115 Uncompressed,
116}
117
118impl From<&str> for BlobCompression {
119 fn from(value: &str) -> Self {
120 match value {
121 "zstd_chunked" => Self::ZSTDChunked,
122 "uncompressed" => Self::Uncompressed,
123 _ => Default::default(),
124 }
125 }
126}
127
128#[derive(Clone, Default)]
130pub enum BlobEvictionPolicy {
131 #[default]
132 NeverEvict,
133 EvictImmediately,
134}
135
136impl From<&str> for BlobEvictionPolicy {
137 fn from(value: &str) -> Self {
138 match value {
139 "never_evict" => Self::NeverEvict,
140 "evict_immediately" => Self::EvictImmediately,
141 _ => Default::default(),
142 }
143 }
144}
145
146#[derive(Clone, Default)]
149pub struct Blobfs {
150 pub verbose: bool,
152 pub deprecated_padded_blobfs_format: bool,
153 pub num_inodes: u64,
154 pub readonly: bool,
156 pub write_compression_algorithm: BlobCompression,
157 pub write_compression_level: Option<i32>,
158 pub cache_eviction_policy_override: BlobEvictionPolicy,
159 pub component_type: ComponentType,
160}
161
162impl Blobfs {
163 pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
165 filesystem::Filesystem::new(block_connector, Self::default())
166 }
167
168 pub fn dynamic_child() -> Self {
170 Self {
171 component_type: ComponentType::DynamicChild {
172 collection_name: FS_COLLECTION_NAME.to_string(),
173 },
174 ..Default::default()
175 }
176 }
177}
178
179impl FSConfig for Blobfs {
180 fn options(&self) -> Options<'_> {
181 Options {
182 component_name: "blobfs",
183 reuse_component_after_serving: false,
184 format_options: FormatOptions {
185 verbose: Some(self.verbose),
186 deprecated_padded_blobfs_format: Some(self.deprecated_padded_blobfs_format),
187 num_inodes: if self.num_inodes > 0 { Some(self.num_inodes) } else { None },
188 ..Default::default()
189 },
190 start_options: {
191 let mut start_options = StartOptions {
192 read_only: Some(self.readonly),
193 verbose: Some(self.verbose),
194 write_compression_level: Some(self.write_compression_level.unwrap_or(-1)),
195 write_compression_algorithm: Some(CompressionAlgorithm::ZstdChunked),
196 cache_eviction_policy_override: Some(EvictionPolicyOverride::None),
197 ..Default::default()
198 };
199 start_options.write_compression_algorithm =
200 Some(match &self.write_compression_algorithm {
201 BlobCompression::ZSTDChunked => CompressionAlgorithm::ZstdChunked,
202 BlobCompression::Uncompressed => CompressionAlgorithm::Uncompressed,
203 });
204 start_options.cache_eviction_policy_override =
205 Some(match &self.cache_eviction_policy_override {
206 BlobEvictionPolicy::NeverEvict => EvictionPolicyOverride::NeverEvict,
207 BlobEvictionPolicy::EvictImmediately => {
208 EvictionPolicyOverride::EvictImmediately
209 }
210 });
211 start_options
212 },
213 component_type: self.component_type.clone(),
214 }
215 }
216
217 fn disk_format(&self) -> format::DiskFormat {
218 format::DiskFormat::Blobfs
219 }
220}
221
222#[derive(Clone, Default)]
225pub struct Minfs {
226 pub verbose: bool,
229 pub fvm_data_slices: u32,
230 pub readonly: bool,
232 pub fsck_after_every_transaction: bool,
233 pub component_type: ComponentType,
234}
235
236impl Minfs {
237 pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
239 filesystem::Filesystem::new(block_connector, Self::default())
240 }
241
242 pub fn dynamic_child() -> Self {
244 Self {
245 component_type: ComponentType::DynamicChild {
246 collection_name: FS_COLLECTION_NAME.to_string(),
247 },
248 ..Default::default()
249 }
250 }
251}
252
253impl FSConfig for Minfs {
254 fn options(&self) -> Options<'_> {
255 Options {
256 component_name: "minfs",
257 reuse_component_after_serving: false,
258 format_options: FormatOptions {
259 verbose: Some(self.verbose),
260 fvm_data_slices: Some(self.fvm_data_slices),
261 ..Default::default()
262 },
263 start_options: StartOptions {
264 read_only: Some(self.readonly),
265 verbose: Some(self.verbose),
266 fsck_after_every_transaction: Some(self.fsck_after_every_transaction),
267 ..Default::default()
268 },
269 component_type: self.component_type.clone(),
270 }
271 }
272
273 fn disk_format(&self) -> format::DiskFormat {
274 format::DiskFormat::Minfs
275 }
276}
277
278pub type CryptClientFn = Arc<dyn Fn() -> zx::Channel + Send + Sync>;
279
280#[derive(Clone)]
282pub struct Fxfs {
283 pub readonly: bool,
285 pub fsck_after_every_transaction: bool,
286 pub component_type: ComponentType,
287 pub startup_profiling_seconds: Option<u32>,
288 pub inline_crypto_enabled: bool,
289 pub barriers_enabled: bool,
290}
291
292impl Default for Fxfs {
293 fn default() -> Self {
294 Self {
295 readonly: false,
296 fsck_after_every_transaction: false,
297 component_type: Default::default(),
298 startup_profiling_seconds: None,
299 inline_crypto_enabled: false,
300 barriers_enabled: false,
301 }
302 }
303}
304
305impl Fxfs {
306 pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
308 filesystem::Filesystem::new(block_connector, Self::default())
309 }
310
311 pub fn dynamic_child() -> Self {
313 Self {
314 component_type: ComponentType::DynamicChild {
315 collection_name: FS_COLLECTION_NAME.to_string(),
316 },
317 ..Default::default()
318 }
319 }
320}
321
322impl FSConfig for Fxfs {
323 fn options(&self) -> Options<'_> {
324 Options {
325 component_name: "fxfs",
326 reuse_component_after_serving: true,
327 format_options: FormatOptions { verbose: Some(false), ..Default::default() },
328 start_options: StartOptions {
329 read_only: Some(self.readonly),
330 fsck_after_every_transaction: Some(self.fsck_after_every_transaction),
331 startup_profiling_seconds: Some(self.startup_profiling_seconds.unwrap_or(0)),
332 inline_crypto_enabled: Some(self.inline_crypto_enabled),
333 barriers_enabled: Some(self.barriers_enabled),
334 ..Default::default()
335 },
336 component_type: self.component_type.clone(),
337 }
338 }
339
340 fn is_multi_volume(&self) -> bool {
341 true
342 }
343
344 fn disk_format(&self) -> format::DiskFormat {
345 format::DiskFormat::Fxfs
346 }
347}
348
349#[derive(Clone, Default)]
352pub struct F2fs {
353 pub component_type: ComponentType,
354}
355
356impl F2fs {
357 pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
359 filesystem::Filesystem::new(block_connector, Self::default())
360 }
361
362 pub fn dynamic_child() -> Self {
364 Self {
365 component_type: ComponentType::DynamicChild {
366 collection_name: FS_COLLECTION_NAME.to_string(),
367 },
368 ..Default::default()
369 }
370 }
371}
372
373impl FSConfig for F2fs {
374 fn options(&self) -> Options<'_> {
375 Options {
376 component_name: "f2fs",
377 reuse_component_after_serving: false,
378 format_options: FormatOptions::default(),
379 start_options: StartOptions {
380 read_only: Some(false),
381 verbose: Some(false),
382 fsck_after_every_transaction: Some(false),
383 ..Default::default()
384 },
385 component_type: self.component_type.clone(),
386 }
387 }
388 fn is_multi_volume(&self) -> bool {
389 false
390 }
391
392 fn disk_format(&self) -> format::DiskFormat {
393 format::DiskFormat::F2fs
394 }
395}
396
397#[derive(Clone)]
399pub struct Fvm {
400 pub component_type: ComponentType,
401}
402
403impl Default for Fvm {
404 fn default() -> Self {
405 Self { component_type: Default::default() }
406 }
407}
408
409impl Fvm {
410 pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
412 filesystem::Filesystem::new(block_connector, Self::default())
413 }
414
415 pub fn dynamic_child() -> Self {
417 Self {
418 component_type: ComponentType::DynamicChild {
419 collection_name: FS_COLLECTION_NAME.to_string(),
420 },
421 ..Default::default()
422 }
423 }
424}
425
426impl FSConfig for Fvm {
427 fn options(&self) -> Options<'_> {
428 Options {
429 component_name: "fvm2",
430 reuse_component_after_serving: true,
431 format_options: FormatOptions::default(),
432 start_options: StartOptions::default(),
433 component_type: self.component_type.clone(),
434 }
435 }
436
437 fn is_multi_volume(&self) -> bool {
438 true
439 }
440
441 fn disk_format(&self) -> format::DiskFormat {
442 format::DiskFormat::Fvm
443 }
444}
445
446#[derive(Clone)]
448pub struct Gpt {
449 pub component_type: ComponentType,
450}
451
452impl Default for Gpt {
453 fn default() -> Self {
454 Self { component_type: Default::default() }
455 }
456}
457
458impl Gpt {
459 pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
461 filesystem::Filesystem::new(block_connector, Self::default())
462 }
463
464 pub fn dynamic_child() -> Self {
466 Self {
467 component_type: ComponentType::DynamicChild {
468 collection_name: FS_COLLECTION_NAME.to_string(),
469 },
470 ..Default::default()
471 }
472 }
473}
474
475impl FSConfig for Gpt {
476 fn options(&self) -> Options<'_> {
477 Options {
478 component_name: "gpt2",
479 reuse_component_after_serving: true,
480 format_options: FormatOptions::default(),
481 start_options: StartOptions::default(),
482 component_type: self.component_type.clone(),
483 }
484 }
485
486 fn is_multi_volume(&self) -> bool {
487 true
488 }
489
490 fn disk_format(&self) -> format::DiskFormat {
491 format::DiskFormat::Gpt
492 }
493}