mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-28 17:44:10 +00:00
547aa2aaf5
The current scsi integration test does not include test cases for the block discard operation. Because of the lack of the test case, it could not catch some bugs caused by other CLs (https://crrev.com/c/5019243). This adds a test function in the e2e_tests crate for the discard operation. BUG=b:300042376 TEST=./tools/run_tests --dut=vm -E 'test(test_scsi)' Change-Id: Ia7ec3850fdf493371fab8fc102d4bf7f978da696 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5075901 Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org> Commit-Queue: Keiichi Watanabe <keiichiw@chromium.org> Reviewed-by: Takaya Saeki <takayas@chromium.org>
149 lines
4.5 KiB
Rust
149 lines
4.5 KiB
Rust
// Copyright 2023 The ChromiumOS Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
//! Integration test for scsi devices as virtio-scsi.
|
|
|
|
use std::path::Path;
|
|
|
|
use fixture::utils::prepare_disk_img;
|
|
use fixture::vm::Config;
|
|
use fixture::vm::TestVm;
|
|
|
|
// Mount the scsi device, and then check if simple read, write, and sync operations work.
|
|
fn mount_scsi_devices(mut config: Config, count: usize) -> anyhow::Result<()> {
|
|
let disks = (0..count).map(|_| prepare_disk_img()).collect::<Vec<_>>();
|
|
for disk in &disks {
|
|
let scsi_disk = disk.path().to_str().unwrap();
|
|
println!("scsi-disk={scsi_disk}");
|
|
config = config.extra_args(vec!["--scsi-block".to_string(), scsi_disk.to_string()]);
|
|
}
|
|
|
|
let mut vm = TestVm::new(config).unwrap();
|
|
for (i, disk) in disks.iter().enumerate() {
|
|
let dev = format!("/dev/sd{}", char::from(b'a' + i as u8));
|
|
let dest = Path::new("/mnt").join(disk.path().file_name().unwrap());
|
|
vm.exec_in_guest("mount -t tmpfs none /mnt")?;
|
|
vm.exec_in_guest(&format!("mkdir -p {}", dest.display()))?;
|
|
vm.exec_in_guest(&format!("mount -t ext4 {dev} {}", dest.display()))?;
|
|
|
|
let output = dest.join("tmp");
|
|
vm.exec_in_guest(&format!("echo 42 > {}", output.display()))?;
|
|
vm.exec_in_guest(&format!("sync -d {}", output.display()))?;
|
|
assert_eq!(
|
|
vm.exec_in_guest(&format!("cat {}", output.display()))?
|
|
.stdout
|
|
.trim(),
|
|
"42"
|
|
);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_mount() {
|
|
let config = Config::new();
|
|
mount_scsi_devices(config, 1).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_mount_disable_sandbox() {
|
|
let config = Config::new().disable_sandbox();
|
|
mount_scsi_devices(config, 1).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_mount_multi_devices() {
|
|
let config = Config::new();
|
|
mount_scsi_devices(config, 3).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_mount_multi_devices_disable_sandbox() {
|
|
let config = Config::new().disable_sandbox();
|
|
mount_scsi_devices(config, 3).unwrap();
|
|
}
|
|
|
|
// This test is for commands in controlq.
|
|
// First check if the resetting behavior is supported by `sg_opcodes` commands, and then issue the
|
|
// `sg_reset` command.
|
|
fn reset_scsi(config: Config) -> anyhow::Result<()> {
|
|
let disk = prepare_disk_img();
|
|
let scsi_disk = disk.path().to_str().unwrap();
|
|
let config = config.extra_args(vec!["--scsi-block".to_string(), scsi_disk.to_string()]);
|
|
println!("scsi-disk={scsi_disk}");
|
|
|
|
let mut vm = TestVm::new(config).unwrap();
|
|
let cmd = vm.exec_in_guest("sg_opcodes --tmf /dev/sda")?;
|
|
let stdout = cmd.stdout.trim();
|
|
assert!(stdout.contains("Logical unit reset"));
|
|
assert!(stdout.contains("Target reset"));
|
|
|
|
assert!(vm.exec_in_guest("sg_reset -d /dev/sda").is_ok());
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_reset() {
|
|
let config = Config::new();
|
|
reset_scsi(config).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_reset_disable_sandbox() {
|
|
let config = Config::new().disable_sandbox();
|
|
reset_scsi(config).unwrap();
|
|
}
|
|
|
|
fn write_same_scsi(config: Config) -> anyhow::Result<()> {
|
|
let disk = prepare_disk_img();
|
|
let scsi_disk = disk.path().to_str().unwrap();
|
|
let config = config.extra_args(vec!["--scsi-block".to_string(), scsi_disk.to_string()]);
|
|
println!("scsi-disk={scsi_disk}");
|
|
|
|
let mut vm = TestVm::new(config)?;
|
|
assert!(vm
|
|
.exec_in_guest("sg_write_same --16 --lba=0 --num=1 --unmap /dev/sda")
|
|
.is_ok());
|
|
assert!(vm
|
|
.exec_in_guest("sg_write_same --16 --lba=0 --num=1 /dev/sda")
|
|
.is_ok());
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_write_same() {
|
|
let config = Config::new();
|
|
write_same_scsi(config).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_write_same_disable_sandbox() {
|
|
let config = Config::new().disable_sandbox();
|
|
write_same_scsi(config).unwrap();
|
|
}
|
|
|
|
fn unmap_scsi(config: Config) -> anyhow::Result<()> {
|
|
let disk = prepare_disk_img();
|
|
let scsi_disk = disk.path().to_str().unwrap();
|
|
let config = config.extra_args(vec!["--scsi-block".to_string(), scsi_disk.to_string()]);
|
|
println!("scsi-disk={scsi_disk}");
|
|
|
|
let mut vm = TestVm::new(config)?;
|
|
assert!(vm
|
|
.exec_in_guest("sg_unmap --lba=0 --num=1 -f /dev/sda")
|
|
.is_ok());
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_unmap() {
|
|
let config = Config::new();
|
|
unmap_scsi(config).unwrap();
|
|
}
|
|
|
|
#[test]
|
|
fn test_scsi_unmap_disable_sandbox() {
|
|
let config = Config::new().disable_sandbox();
|
|
unmap_scsi(config).unwrap();
|
|
}
|