Skip to main content

erofs_component/
volume.rs

1// Copyright 2026 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
5use crate::directory::ErofsDirectory;
6use crate::pager::ErofsPager;
7use anyhow::Context as _;
8use erofs::ErofsFilesystem;
9use erofs::readers::VmoReader;
10use fidl_fuchsia_io as fio;
11use std::sync::Arc;
12use vfs::execution_scope::ExecutionScope;
13
14// An array used to initialize the FilesystemInfo |name| field. This just spells "erofs" 0-padded to
15// 32 bytes.
16const EROFS_INFO_NAME_FIDL: [i8; 32] = [
17    0x65, 0x72, 0x6f, 0x66, 0x73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18    0, 0, 0, 0, 0,
19];
20
21/// Holds the volume-level state for an active EROFS instance.
22pub struct ErofsVolume {
23    /// The filesystem for this EROFS volume.
24    fs: ErofsFilesystem,
25    /// Reference to the unified pager.
26    pager: Arc<ErofsPager>,
27    /// Unique filesystem ID.
28    fs_id: u64,
29}
30
31impl ErofsVolume {
32    pub fn new(backing_vmo: zx::Vmo, pager: Arc<ErofsPager>) -> Result<Self, anyhow::Error> {
33        let fs_id = zx::Event::create().koid().context("Failed to get event koid")?.raw_koid();
34        let reader =
35            Arc::new(VmoReader::new(Arc::new(backing_vmo)).context("Failed to create VmoReader")?);
36        let fs = ErofsFilesystem::new(reader).context("Failed to create ErofsFilesystem")?;
37        Ok(Self { fs, pager, fs_id })
38    }
39
40    /// Sets up and serves an EROFS volume from a backing VMO.
41    pub fn serve(
42        backing_vmo: zx::Vmo,
43        pager: Arc<ErofsPager>,
44        flags: fio::Flags,
45        root: fidl::endpoints::ServerEnd<fio::DirectoryMarker>,
46    ) -> Result<(), anyhow::Error> {
47        let scope = ExecutionScope::new();
48        let volume = Arc::new(Self::new(backing_vmo, pager)?);
49        let root_node = volume.fs().root_node();
50        let root_dir = Arc::new(ErofsDirectory::new(volume, root_node));
51
52        vfs::directory::serve_on(root_dir, flags, scope, root);
53        Ok(())
54    }
55
56    /// Returns a reference to the filesystem.
57    pub fn fs(&self) -> &ErofsFilesystem {
58        &self.fs
59    }
60
61    /// Returns a reference to the pager.
62    pub fn pager(&self) -> &ErofsPager {
63        &self.pager
64    }
65
66    pub fn query_filesystem(&self) -> Result<fio::FilesystemInfo, zx::Status> {
67        let total_bytes = self.fs.total_bytes();
68        let total_inodes = self.fs.total_inodes();
69        let block_size = self.fs.block_size() as u32;
70
71        Ok(fio::FilesystemInfo {
72            total_bytes,
73            used_bytes: total_bytes,
74            total_nodes: total_inodes,
75            used_nodes: total_inodes,
76            free_shared_pool_bytes: 0,
77            fs_id: self.fs_id,
78            block_size,
79            max_filename_size: 255,
80            fs_type: fidl_fuchsia_fs::VfsType::Erofs.into_primitive(),
81            padding: 0,
82            name: EROFS_INFO_NAME_FIDL,
83        })
84    }
85}