blob: 2a508c11ed076293c64384acc43baf6f978c436d [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
pub mod operator;
use {
fidl_fuchsia_hardware_block_partition::Guid,
fs_management::Minfs,
fuchsia_async::{Task, TimeoutExt},
fuchsia_zircon::Vmo,
log::debug,
operator::MinfsOperator,
rand::rngs::SmallRng,
std::thread::sleep,
std::time::Duration,
stress_test_utils::{get_volume_path, TestInstance},
};
// All partitions in this test have their type set to this arbitrary GUID.
const TYPE_GUID: Guid = Guid {
value: [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf],
};
// The path to the minfs filesystem in the test's namespace
const MINFS_MOUNT_PATH: &str = "/minfs";
pub async fn run_test(
rng: SmallRng,
ramdisk_block_count: u64,
ramdisk_block_size: u64,
fvm_slice_size: u64,
num_operations: Option<u64>,
disconnect_secs: u64,
time_limit_secs: Option<u64>,
) {
// Create the VMO that the ramdisk is backed by
let vmo_size = ramdisk_block_count * ramdisk_block_size;
let vmo = Vmo::create(vmo_size).unwrap();
// Initialize the ramdisk and setup FVM.
let mut instance = TestInstance::init(&vmo, fvm_slice_size, ramdisk_block_size).await;
// Create a minfs volume
let volume_instance_guid = instance.new_volume("minfs", TYPE_GUID).await;
// Find the path to the volume
let block_path = instance.block_path();
let mut volume_path = get_volume_path(block_path, &volume_instance_guid).await;
// Initialize minfs for the first time
let mut minfs = Minfs::new(volume_path.to_str().unwrap()).unwrap();
minfs.format().unwrap();
if disconnect_secs > 0 {
Task::blocking(async move {
// Crash the block device every |disconnect_secs|.
loop {
{
// Start up minfs
let mut minfs = Minfs::new(volume_path.to_str().unwrap()).unwrap();
minfs.fsck().unwrap();
minfs.mount(MINFS_MOUNT_PATH).unwrap();
// Wait for the required amount of time
sleep(Duration::from_secs(disconnect_secs));
// Crash the old instance and replace it with a new instance.
// This will cause the component tree to be taken down abruptly.
debug!("Killing component manager");
instance.kill_component_manager();
// Minfs may not neatly terminate. Force kill the process.
let result = minfs.kill();
debug!("Minfs kill result = {:?}", result);
}
// Start up a new instance
instance = TestInstance::existing(&vmo, ramdisk_block_size).await;
let block_path = instance.block_path();
volume_path = get_volume_path(block_path, &volume_instance_guid).await;
}
})
.detach();
} else {
// Start up minfs
minfs.fsck().unwrap();
minfs.mount(MINFS_MOUNT_PATH).unwrap();
}
// Run the operator in a new thread
let operator_task = Task::blocking(async move {
let operator = MinfsOperator::new(rng).await;
operator.do_random_operations(num_operations.unwrap_or(u64::MAX)).await;
});
if let Some(time_limit_secs) = time_limit_secs {
operator_task.on_timeout(Duration::from_secs(time_limit_secs), || (())).await;
} else {
operator_task.await;
};
}