fuchsia_storage_benchmarks/
testing.rs

1// Copyright 2024 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 async_trait::async_trait;
6use fidl::endpoints::DiscoverableProtocolMarker as _;
7use fidl_fuchsia_hardware_block_volume::VolumeMarker;
8use fs_management::filesystem::{
9    BlockConnector, DirBasedBlockConnector, ServingMultiVolumeFilesystem,
10};
11use fs_management::Fvm;
12use fuchsia_component::client::connect_to_protocol_at_dir_root;
13use ramdevice_client::RamdiskClient;
14use storage_benchmarks::block_device::BlockDevice;
15use storage_benchmarks::{BlockDeviceConfig, BlockDeviceFactory};
16use storage_isolated_driver_manager::{create_random_guid, fvm};
17use {fidl_fuchsia_io as fio, fuchsia_async as fasync};
18
19use crate::block_devices::create_fvm_volume;
20
21pub const RAMDISK_FVM_SLICE_SIZE: usize = 1024 * 1024;
22
23/// Creates block devices on ramdisks.
24pub struct RamdiskFactory {
25    block_size: u64,
26    block_count: u64,
27}
28
29impl RamdiskFactory {
30    #[allow(dead_code)]
31    pub async fn new(block_size: u64, block_count: u64) -> Self {
32        Self { block_size, block_count }
33    }
34}
35
36#[async_trait]
37impl BlockDeviceFactory for RamdiskFactory {
38    async fn create_block_device(&self, config: &BlockDeviceConfig) -> Box<dyn BlockDevice> {
39        Box::new(Ramdisk::new(self.block_size, self.block_count, config).await)
40    }
41}
42
43/// A ramdisk backed block device.
44pub struct Ramdisk {
45    _ramdisk: RamdiskClient,
46    _fvm: ServingMultiVolumeFilesystem,
47    volume_dir: fio::DirectoryProxy,
48    _crypt_task: Option<fasync::Task<()>>,
49}
50
51impl Ramdisk {
52    async fn new(block_size: u64, block_count: u64, config: &BlockDeviceConfig) -> Self {
53        let ramdisk = RamdiskClient::builder(block_size, block_count)
54            .use_v2()
55            .build()
56            .await
57            .expect("Failed to create RamdiskClient");
58
59        let block_device = ramdisk.open().expect("Failed to connect to block").into_proxy();
60        fvm::format_for_fvm(&block_device, RAMDISK_FVM_SLICE_SIZE).expect("Failed to format FVM");
61
62        let fvm = fs_management::filesystem::Filesystem::from_boxed_config(
63            ramdisk.connector().unwrap(),
64            Box::new(Fvm::default()),
65        )
66        .serve_multi_volume()
67        .await
68        .expect("Failed to serve FVM");
69        let volumes = connect_to_protocol_at_dir_root::<fidl_fuchsia_fs_startup::VolumesMarker>(
70            fvm.exposed_dir(),
71        )
72        .unwrap();
73        let (volume_dir, crypt_task) =
74            create_fvm_volume(&volumes, create_random_guid(), config).await;
75
76        Self { _ramdisk: ramdisk, _fvm: fvm, volume_dir, _crypt_task: crypt_task }
77    }
78}
79
80impl BlockDevice for Ramdisk {
81    fn connector(&self) -> Box<dyn BlockConnector> {
82        let volume_dir = fuchsia_fs::directory::clone(&self.volume_dir).unwrap();
83        Box::new(DirBasedBlockConnector::new(
84            volume_dir,
85            format!("svc/{}", VolumeMarker::PROTOCOL_NAME),
86        ))
87    }
88}