fs_management/
lib.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Library for filesystem management in rust.
6//!
7//! This library is analogous to the fs-management library in zircon. It provides support for
8//! formatting, mounting, unmounting, and fsck-ing. It is implemented in a similar way to the C++
9//! version.  For components v2, add `/svc/fuchsia.process.Launcher` to `use` and add the
10//! binaries as dependencies to your component.
11
12mod error;
13pub mod filesystem;
14pub mod format;
15pub mod partition;
16
17use crate::filesystem::BlockConnector;
18use fidl_fuchsia_fs_startup::{FormatOptions, StartOptions};
19use std::sync::Arc;
20
21// Re-export errors as public.
22pub use error::{QueryError, ShutdownError};
23
24pub const BLOBFS_TYPE_GUID: [u8; 16] = [
25    0x0e, 0x38, 0x67, 0x29, 0x4c, 0x13, 0xbb, 0x4c, 0xb6, 0xda, 0x17, 0xe7, 0xce, 0x1c, 0xa4, 0x5d,
26];
27pub const DATA_TYPE_GUID: [u8; 16] = [
28    0x0c, 0x5f, 0x18, 0x08, 0x2d, 0x89, 0x8a, 0x42, 0xa7, 0x89, 0xdb, 0xee, 0xc8, 0xf5, 0x5e, 0x6a,
29];
30pub const FVM_TYPE_GUID: [u8; 16] = [
31    0xb8, 0x7c, 0xfd, 0x49, 0x15, 0xdf, 0x73, 0x4e, 0xb9, 0xd9, 0x99, 0x20, 0x70, 0x12, 0x7f, 0x0f,
32];
33
34pub const FVM_TYPE_GUID_STR: &str = "49fd7cb8-df15-4e73-b9d9-992070127f0f";
35
36pub const FS_COLLECTION_NAME: &'static str = "fs-collection";
37
38#[derive(Clone)]
39pub enum ComponentType {
40    /// Launch the filesystem as a static child, using the configured name in the options as the
41    /// child name. If the child doesn't exist, this will fail.
42    StaticChild,
43
44    /// Launch the filesystem as a dynamic child, in the configured collection. By default, the
45    /// collection is "fs-collection".
46    DynamicChild { collection_name: String },
47}
48
49impl Default for ComponentType {
50    fn default() -> Self {
51        ComponentType::DynamicChild { collection_name: "fs-collection".to_string() }
52    }
53}
54
55pub struct Options<'a> {
56    /// For static children, the name specifies the name of the child.  For dynamic children, the
57    /// component URL is "fuchsia-boot:///{component-name}#meta/{component-name}.cm" or
58    /// "#meta/{component-name}.cm".  The library will attempt to connect to a static child first,
59    /// and if that fails, it will launch the filesystem within a collection. It will try to
60    /// create a child component via the absolute URL and then fallback to the relative URL.
61    pub component_name: &'a str,
62
63    /// It should be possible to reuse components after serving them, but it's not universally
64    /// supported.
65    pub reuse_component_after_serving: bool,
66
67    /// Format options as defined by the startup protocol
68    pub format_options: FormatOptions,
69
70    /// Start options as defined by the startup protocol
71    pub start_options: StartOptions,
72
73    /// Whether to launch this filesystem as a dynamic or static child.
74    pub component_type: ComponentType,
75}
76
77/// Describes the configuration for a particular filesystem.
78pub trait FSConfig: Send + Sync + 'static {
79    /// Returns the options specifying how to run this filesystem.
80    fn options(&self) -> Options<'_>;
81
82    /// Whether the filesystem supports multiple volumes.
83    fn is_multi_volume(&self) -> bool {
84        false
85    }
86
87    fn disk_format(&self) -> format::DiskFormat {
88        format::DiskFormat::Unknown
89    }
90}
91
92///
93/// FILESYSTEMS
94///
95
96/// Layout of blobs in blobfs
97#[derive(Clone)]
98pub enum BlobLayout {
99    /// Merkle tree is stored in a separate block. This is deprecated and used only on Astro
100    /// devices (it takes more space).
101    DeprecatedPadded,
102
103    /// Merkle tree is appended to the last block of data
104    Compact,
105}
106
107/// Blobfs Filesystem Configuration
108/// If fields are None or false, they will not be set in arguments.
109#[derive(Clone, Default)]
110pub struct Blobfs {
111    // Format options
112    pub verbose: bool,
113    pub deprecated_padded_blobfs_format: bool,
114    pub num_inodes: u64,
115    // Start Options
116    pub readonly: bool,
117    pub component_type: ComponentType,
118}
119
120impl Blobfs {
121    /// Manages a block device using the default configuration.
122    pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
123        filesystem::Filesystem::new(block_connector, Self::default())
124    }
125
126    /// Launch blobfs, with the default configuration, as a dynamic child in the fs-collection.
127    pub fn dynamic_child() -> Self {
128        Self {
129            component_type: ComponentType::DynamicChild {
130                collection_name: FS_COLLECTION_NAME.to_string(),
131            },
132            ..Default::default()
133        }
134    }
135}
136
137impl FSConfig for Blobfs {
138    fn options(&self) -> Options<'_> {
139        Options {
140            component_name: "blobfs",
141            reuse_component_after_serving: false,
142            format_options: FormatOptions {
143                verbose: Some(self.verbose),
144                deprecated_padded_blobfs_format: Some(self.deprecated_padded_blobfs_format),
145                num_inodes: if self.num_inodes > 0 { Some(self.num_inodes) } else { None },
146                ..Default::default()
147            },
148            start_options: {
149                StartOptions {
150                    read_only: Some(self.readonly),
151                    verbose: Some(self.verbose),
152                    ..Default::default()
153                }
154            },
155            component_type: self.component_type.clone(),
156        }
157    }
158
159    fn disk_format(&self) -> format::DiskFormat {
160        format::DiskFormat::Blobfs
161    }
162}
163
164/// Minfs Filesystem Configuration
165/// If fields are None or false, they will not be set in arguments.
166#[derive(Clone, Default)]
167pub struct Minfs {
168    // TODO(xbhatnag): Add support for fvm_data_slices
169    // Format options
170    pub verbose: bool,
171    pub fvm_data_slices: u32,
172    // Start Options
173    pub readonly: bool,
174    pub fsck_after_every_transaction: bool,
175    pub component_type: ComponentType,
176}
177
178impl Minfs {
179    /// Manages a block device using the default configuration.
180    pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
181        filesystem::Filesystem::new(block_connector, Self::default())
182    }
183
184    /// Launch minfs, with the default configuration, as a dynamic child in the fs-collection.
185    pub fn dynamic_child() -> Self {
186        Self {
187            component_type: ComponentType::DynamicChild {
188                collection_name: FS_COLLECTION_NAME.to_string(),
189            },
190            ..Default::default()
191        }
192    }
193}
194
195impl FSConfig for Minfs {
196    fn options(&self) -> Options<'_> {
197        Options {
198            component_name: "minfs",
199            reuse_component_after_serving: false,
200            format_options: FormatOptions {
201                verbose: Some(self.verbose),
202                fvm_data_slices: Some(self.fvm_data_slices),
203                ..Default::default()
204            },
205            start_options: StartOptions {
206                read_only: Some(self.readonly),
207                verbose: Some(self.verbose),
208                fsck_after_every_transaction: Some(self.fsck_after_every_transaction),
209                ..Default::default()
210            },
211            component_type: self.component_type.clone(),
212        }
213    }
214
215    fn disk_format(&self) -> format::DiskFormat {
216        format::DiskFormat::Minfs
217    }
218}
219
220pub type CryptClientFn = Arc<dyn Fn() -> zx::Channel + Send + Sync>;
221
222/// Fxfs Filesystem Configuration
223#[derive(Clone)]
224pub struct Fxfs {
225    // Start Options
226    pub readonly: bool,
227    pub fsck_after_every_transaction: bool,
228    pub component_type: ComponentType,
229    pub startup_profiling_seconds: Option<u32>,
230    pub inline_crypto_enabled: bool,
231    pub barriers_enabled: bool,
232}
233
234impl Default for Fxfs {
235    fn default() -> Self {
236        Self {
237            readonly: false,
238            fsck_after_every_transaction: false,
239            component_type: Default::default(),
240            startup_profiling_seconds: None,
241            inline_crypto_enabled: false,
242            barriers_enabled: false,
243        }
244    }
245}
246
247impl Fxfs {
248    /// Manages a block device using the default configuration.
249    pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
250        filesystem::Filesystem::new(block_connector, Self::default())
251    }
252
253    /// Launch Fxfs, with the default configuration, as a dynamic child in the fs-collection.
254    pub fn dynamic_child() -> Self {
255        Self {
256            component_type: ComponentType::DynamicChild {
257                collection_name: FS_COLLECTION_NAME.to_string(),
258            },
259            ..Default::default()
260        }
261    }
262}
263
264impl FSConfig for Fxfs {
265    fn options(&self) -> Options<'_> {
266        Options {
267            component_name: "fxfs",
268            reuse_component_after_serving: true,
269            format_options: FormatOptions { verbose: Some(false), ..Default::default() },
270            start_options: StartOptions {
271                read_only: Some(self.readonly),
272                fsck_after_every_transaction: Some(self.fsck_after_every_transaction),
273                startup_profiling_seconds: Some(self.startup_profiling_seconds.unwrap_or(0)),
274                inline_crypto_enabled: Some(self.inline_crypto_enabled),
275                barriers_enabled: Some(self.barriers_enabled),
276                ..Default::default()
277            },
278            component_type: self.component_type.clone(),
279        }
280    }
281
282    fn is_multi_volume(&self) -> bool {
283        true
284    }
285
286    fn disk_format(&self) -> format::DiskFormat {
287        format::DiskFormat::Fxfs
288    }
289}
290
291/// F2fs Filesystem Configuration
292/// If fields are None or false, they will not be set in arguments.
293#[derive(Clone, Default)]
294pub struct F2fs {
295    pub component_type: ComponentType,
296}
297
298impl F2fs {
299    /// Manages a block device using the default configuration.
300    pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
301        filesystem::Filesystem::new(block_connector, Self::default())
302    }
303
304    /// Launch f2fs, with the default configuration, as a dynamic child in the fs-collection.
305    pub fn dynamic_child() -> Self {
306        Self {
307            component_type: ComponentType::DynamicChild {
308                collection_name: FS_COLLECTION_NAME.to_string(),
309            },
310            ..Default::default()
311        }
312    }
313}
314
315impl FSConfig for F2fs {
316    fn options(&self) -> Options<'_> {
317        Options {
318            component_name: "f2fs",
319            reuse_component_after_serving: false,
320            format_options: FormatOptions::default(),
321            start_options: StartOptions {
322                read_only: Some(false),
323                verbose: Some(false),
324                fsck_after_every_transaction: Some(false),
325                ..Default::default()
326            },
327            component_type: self.component_type.clone(),
328        }
329    }
330    fn is_multi_volume(&self) -> bool {
331        false
332    }
333
334    fn disk_format(&self) -> format::DiskFormat {
335        format::DiskFormat::F2fs
336    }
337}
338
339/// FvmFilesystem Configuration
340#[derive(Clone)]
341pub struct Fvm {
342    pub component_type: ComponentType,
343}
344
345impl Default for Fvm {
346    fn default() -> Self {
347        Self { component_type: Default::default() }
348    }
349}
350
351impl Fvm {
352    /// Manages a block device using the default configuration.
353    pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
354        filesystem::Filesystem::new(block_connector, Self::default())
355    }
356
357    /// Launch Fvm, with the default configuration, as a dynamic child in the fs-collection.
358    pub fn dynamic_child() -> Self {
359        Self {
360            component_type: ComponentType::DynamicChild {
361                collection_name: FS_COLLECTION_NAME.to_string(),
362            },
363            ..Default::default()
364        }
365    }
366}
367
368impl FSConfig for Fvm {
369    fn options(&self) -> Options<'_> {
370        Options {
371            component_name: "fvm2",
372            reuse_component_after_serving: true,
373            format_options: FormatOptions::default(),
374            start_options: StartOptions::default(),
375            component_type: self.component_type.clone(),
376        }
377    }
378
379    fn is_multi_volume(&self) -> bool {
380        true
381    }
382
383    fn disk_format(&self) -> format::DiskFormat {
384        format::DiskFormat::Fvm
385    }
386}
387
388/// Gpt Configuration
389#[derive(Clone)]
390pub struct Gpt {
391    pub component_type: ComponentType,
392    pub merge_super_and_userdata: bool,
393}
394
395impl Default for Gpt {
396    fn default() -> Self {
397        Self { component_type: Default::default(), merge_super_and_userdata: false }
398    }
399}
400
401impl Gpt {
402    /// Manages a block device using the default configuration.
403    pub fn new<B: BlockConnector + 'static>(block_connector: B) -> filesystem::Filesystem {
404        filesystem::Filesystem::new(block_connector, Self::default())
405    }
406
407    /// Launch Gpt, with the default configuration, as a dynamic child in the fs-collection.
408    pub fn dynamic_child() -> Self {
409        Self {
410            component_type: ComponentType::DynamicChild {
411                collection_name: FS_COLLECTION_NAME.to_string(),
412            },
413            ..Default::default()
414        }
415    }
416}
417
418impl FSConfig for Gpt {
419    fn options(&self) -> Options<'_> {
420        Options {
421            component_name: "gpt2",
422            reuse_component_after_serving: true,
423            format_options: FormatOptions::default(),
424            start_options: StartOptions {
425                merge_super_and_userdata: Some(self.merge_super_and_userdata),
426                ..Default::default()
427            },
428            component_type: self.component_type.clone(),
429        }
430    }
431
432    fn is_multi_volume(&self) -> bool {
433        true
434    }
435
436    fn disk_format(&self) -> format::DiskFormat {
437        format::DiskFormat::Gpt
438    }
439}