fuchsia_storage_benchmarks/filesystems/
blobfs.rs

1// Copyright 2023 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::filesystems::{BlobFilesystem, DeliveryBlob, FsManagementFilesystemInstance};
6use async_trait::async_trait;
7use delivery_blob::delivery_blob_path;
8use fidl_fuchsia_io as fio;
9use std::path::Path;
10use storage_benchmarks::{
11    BlockDeviceConfig, BlockDeviceFactory, CacheClearableFilesystem, Filesystem, FilesystemConfig,
12};
13
14/// Config object for starting Blobfs instances.
15#[derive(Clone)]
16pub struct Blobfs;
17
18#[async_trait]
19impl FilesystemConfig for Blobfs {
20    type Filesystem = BlobfsInstance;
21
22    async fn start_filesystem(
23        &self,
24        block_device_factory: &dyn BlockDeviceFactory,
25    ) -> BlobfsInstance {
26        let block_device = block_device_factory
27            .create_block_device(&BlockDeviceConfig {
28                requires_fvm: true,
29                use_zxcrypt: false,
30                volume_size: None,
31            })
32            .await;
33        let blobfs = FsManagementFilesystemInstance::new(
34            fs_management::Blobfs { ..Default::default() },
35            block_device,
36            None,
37            /*as_blob=*/ false,
38        )
39        .await;
40        let root = fuchsia_fs::directory::open_in_namespace(
41            blobfs.benchmark_dir().to_str().unwrap(),
42            fuchsia_fs::PERM_WRITABLE | fuchsia_fs::PERM_READABLE,
43        )
44        .unwrap();
45        BlobfsInstance { root, blobfs }
46    }
47
48    fn name(&self) -> String {
49        "blobfs".to_owned()
50    }
51}
52
53pub struct BlobfsInstance {
54    root: fio::DirectoryProxy,
55    blobfs: FsManagementFilesystemInstance,
56}
57
58#[async_trait]
59impl Filesystem for BlobfsInstance {
60    async fn shutdown(self) {
61        self.blobfs.shutdown().await
62    }
63
64    fn benchmark_dir(&self) -> &Path {
65        self.blobfs.benchmark_dir()
66    }
67}
68
69#[async_trait]
70impl CacheClearableFilesystem for BlobfsInstance {
71    async fn clear_cache(&mut self) {
72        let () = self.blobfs.clear_cache().await;
73        self.root = fuchsia_fs::directory::open_in_namespace(
74            self.blobfs.benchmark_dir().to_str().unwrap(),
75            fuchsia_fs::PERM_WRITABLE | fuchsia_fs::PERM_READABLE,
76        )
77        .unwrap();
78    }
79}
80
81#[async_trait]
82impl BlobFilesystem for BlobfsInstance {
83    async fn get_vmo(&self, blob: &DeliveryBlob) -> zx::Vmo {
84        let blob = fuchsia_fs::directory::open_file(
85            &self.root,
86            &delivery_blob_path(blob.name),
87            fuchsia_fs::PERM_READABLE,
88        )
89        .await
90        .unwrap();
91        blob.get_backing_memory(fio::VmoFlags::READ).await.unwrap().unwrap()
92    }
93
94    async fn write_blob(&self, blob: &DeliveryBlob) {
95        let blob_proxy = fuchsia_fs::directory::open_file(
96            &self.root,
97            &delivery_blob_path(blob.name),
98            fio::Flags::FLAG_MAYBE_CREATE | fio::PERM_WRITABLE,
99        )
100        .await
101        .unwrap();
102        let blob_size = blob.data.len();
103        blob_proxy.resize(blob_size as u64).await.unwrap().unwrap();
104        let mut written = 0;
105        while written != blob_size {
106            // Don't try to write more than MAX_TRANSFER_SIZE bytes at a time.
107            let bytes_to_write =
108                std::cmp::min(fio::MAX_TRANSFER_SIZE, (blob_size - written) as u64);
109            let bytes_written: u64 = blob_proxy
110                .write(&blob.data[written..written + bytes_to_write as usize])
111                .await
112                .unwrap()
113                .unwrap();
114            assert_eq!(bytes_written, bytes_to_write);
115            written += bytes_written as usize;
116        }
117    }
118
119    fn exposed_dir(&self) -> &fio::DirectoryProxy {
120        self.blobfs.exposed_dir()
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::Blobfs;
127    use crate::filesystems::testing::check_blob_filesystem;
128
129    #[fuchsia::test]
130    async fn start_blobfs() {
131        check_blob_filesystem(Blobfs).await;
132    }
133}