1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker //! Integration test for scsi devices as virtio-scsi.
6*bb4ee6a4SAndroid Build Coastguard Worker
7*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
8*bb4ee6a4SAndroid Build Coastguard Worker
9*bb4ee6a4SAndroid Build Coastguard Worker use fixture::utils::prepare_disk_img;
10*bb4ee6a4SAndroid Build Coastguard Worker use fixture::vm::Config;
11*bb4ee6a4SAndroid Build Coastguard Worker use fixture::vm::TestVm;
12*bb4ee6a4SAndroid Build Coastguard Worker
13*bb4ee6a4SAndroid Build Coastguard Worker // Mount the scsi device, and then check if simple read, write, and sync operations work.
mount_scsi_devices(mut config: Config, count: usize) -> anyhow::Result<()>14*bb4ee6a4SAndroid Build Coastguard Worker fn mount_scsi_devices(mut config: Config, count: usize) -> anyhow::Result<()> {
15*bb4ee6a4SAndroid Build Coastguard Worker let disks = (0..count).map(|_| prepare_disk_img()).collect::<Vec<_>>();
16*bb4ee6a4SAndroid Build Coastguard Worker for disk in &disks {
17*bb4ee6a4SAndroid Build Coastguard Worker let scsi_disk = disk.path().to_str().unwrap();
18*bb4ee6a4SAndroid Build Coastguard Worker println!("scsi-disk={scsi_disk}");
19*bb4ee6a4SAndroid Build Coastguard Worker config = config.extra_args(vec!["--scsi-block".to_string(), scsi_disk.to_string()]);
20*bb4ee6a4SAndroid Build Coastguard Worker }
21*bb4ee6a4SAndroid Build Coastguard Worker
22*bb4ee6a4SAndroid Build Coastguard Worker let mut vm = TestVm::new(config).unwrap();
23*bb4ee6a4SAndroid Build Coastguard Worker for (i, disk) in disks.iter().enumerate() {
24*bb4ee6a4SAndroid Build Coastguard Worker let dev = format!("/dev/sd{}", char::from(b'a' + i as u8));
25*bb4ee6a4SAndroid Build Coastguard Worker let dest = Path::new("/mnt").join(disk.path().file_name().unwrap());
26*bb4ee6a4SAndroid Build Coastguard Worker vm.exec_in_guest("mount -t tmpfs none /mnt")?;
27*bb4ee6a4SAndroid Build Coastguard Worker vm.exec_in_guest(&format!("mkdir -p {}", dest.display()))?;
28*bb4ee6a4SAndroid Build Coastguard Worker vm.exec_in_guest(&format!("mount -t ext4 {dev} {}", dest.display()))?;
29*bb4ee6a4SAndroid Build Coastguard Worker
30*bb4ee6a4SAndroid Build Coastguard Worker let output = dest.join("tmp");
31*bb4ee6a4SAndroid Build Coastguard Worker vm.exec_in_guest(&format!("echo 42 > {}", output.display()))?;
32*bb4ee6a4SAndroid Build Coastguard Worker vm.exec_in_guest(&format!("sync -d {}", output.display()))?;
33*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(
34*bb4ee6a4SAndroid Build Coastguard Worker vm.exec_in_guest(&format!("cat {}", output.display()))?
35*bb4ee6a4SAndroid Build Coastguard Worker .stdout
36*bb4ee6a4SAndroid Build Coastguard Worker .trim(),
37*bb4ee6a4SAndroid Build Coastguard Worker "42"
38*bb4ee6a4SAndroid Build Coastguard Worker );
39*bb4ee6a4SAndroid Build Coastguard Worker }
40*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
41*bb4ee6a4SAndroid Build Coastguard Worker }
42*bb4ee6a4SAndroid Build Coastguard Worker
43*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_mount()44*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_mount() {
45*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new();
46*bb4ee6a4SAndroid Build Coastguard Worker mount_scsi_devices(config, 1).unwrap();
47*bb4ee6a4SAndroid Build Coastguard Worker }
48*bb4ee6a4SAndroid Build Coastguard Worker
49*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_mount_disable_sandbox()50*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_mount_disable_sandbox() {
51*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new().disable_sandbox();
52*bb4ee6a4SAndroid Build Coastguard Worker mount_scsi_devices(config, 1).unwrap();
53*bb4ee6a4SAndroid Build Coastguard Worker }
54*bb4ee6a4SAndroid Build Coastguard Worker
55*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_mount_multi_devices()56*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_mount_multi_devices() {
57*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new();
58*bb4ee6a4SAndroid Build Coastguard Worker mount_scsi_devices(config, 3).unwrap();
59*bb4ee6a4SAndroid Build Coastguard Worker }
60*bb4ee6a4SAndroid Build Coastguard Worker
61*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_mount_multi_devices_disable_sandbox()62*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_mount_multi_devices_disable_sandbox() {
63*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new().disable_sandbox();
64*bb4ee6a4SAndroid Build Coastguard Worker mount_scsi_devices(config, 3).unwrap();
65*bb4ee6a4SAndroid Build Coastguard Worker }
66*bb4ee6a4SAndroid Build Coastguard Worker
67*bb4ee6a4SAndroid Build Coastguard Worker // This test is for commands in controlq.
68*bb4ee6a4SAndroid Build Coastguard Worker // First check if the resetting behavior is supported by `sg_opcodes` commands, and then issue the
69*bb4ee6a4SAndroid Build Coastguard Worker // `sg_reset` command.
reset_scsi(config: Config) -> anyhow::Result<()>70*bb4ee6a4SAndroid Build Coastguard Worker fn reset_scsi(config: Config) -> anyhow::Result<()> {
71*bb4ee6a4SAndroid Build Coastguard Worker let disk = prepare_disk_img();
72*bb4ee6a4SAndroid Build Coastguard Worker let scsi_disk = disk.path().to_str().unwrap();
73*bb4ee6a4SAndroid Build Coastguard Worker let config = config.extra_args(vec!["--scsi-block".to_string(), scsi_disk.to_string()]);
74*bb4ee6a4SAndroid Build Coastguard Worker println!("scsi-disk={scsi_disk}");
75*bb4ee6a4SAndroid Build Coastguard Worker
76*bb4ee6a4SAndroid Build Coastguard Worker let mut vm = TestVm::new(config).unwrap();
77*bb4ee6a4SAndroid Build Coastguard Worker let cmd = vm.exec_in_guest("sg_opcodes --tmf /dev/sda")?;
78*bb4ee6a4SAndroid Build Coastguard Worker let stdout = cmd.stdout.trim();
79*bb4ee6a4SAndroid Build Coastguard Worker assert!(stdout.contains("Logical unit reset"));
80*bb4ee6a4SAndroid Build Coastguard Worker assert!(stdout.contains("Target reset"));
81*bb4ee6a4SAndroid Build Coastguard Worker
82*bb4ee6a4SAndroid Build Coastguard Worker assert!(vm.exec_in_guest("sg_reset -d /dev/sda").is_ok());
83*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
84*bb4ee6a4SAndroid Build Coastguard Worker }
85*bb4ee6a4SAndroid Build Coastguard Worker
86*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_reset()87*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_reset() {
88*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new();
89*bb4ee6a4SAndroid Build Coastguard Worker reset_scsi(config).unwrap();
90*bb4ee6a4SAndroid Build Coastguard Worker }
91*bb4ee6a4SAndroid Build Coastguard Worker
92*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_reset_disable_sandbox()93*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_reset_disable_sandbox() {
94*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new().disable_sandbox();
95*bb4ee6a4SAndroid Build Coastguard Worker reset_scsi(config).unwrap();
96*bb4ee6a4SAndroid Build Coastguard Worker }
97*bb4ee6a4SAndroid Build Coastguard Worker
write_same_scsi(config: Config) -> anyhow::Result<()>98*bb4ee6a4SAndroid Build Coastguard Worker fn write_same_scsi(config: Config) -> anyhow::Result<()> {
99*bb4ee6a4SAndroid Build Coastguard Worker let disk = prepare_disk_img();
100*bb4ee6a4SAndroid Build Coastguard Worker let scsi_disk = disk.path().to_str().unwrap();
101*bb4ee6a4SAndroid Build Coastguard Worker let config = config.extra_args(vec!["--scsi-block".to_string(), scsi_disk.to_string()]);
102*bb4ee6a4SAndroid Build Coastguard Worker println!("scsi-disk={scsi_disk}");
103*bb4ee6a4SAndroid Build Coastguard Worker
104*bb4ee6a4SAndroid Build Coastguard Worker let mut vm = TestVm::new(config)?;
105*bb4ee6a4SAndroid Build Coastguard Worker assert!(vm
106*bb4ee6a4SAndroid Build Coastguard Worker .exec_in_guest("sg_write_same --16 --lba=0 --num=1 --unmap /dev/sda")
107*bb4ee6a4SAndroid Build Coastguard Worker .is_ok());
108*bb4ee6a4SAndroid Build Coastguard Worker assert!(vm
109*bb4ee6a4SAndroid Build Coastguard Worker .exec_in_guest("sg_write_same --16 --lba=0 --num=1 /dev/sda")
110*bb4ee6a4SAndroid Build Coastguard Worker .is_ok());
111*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
112*bb4ee6a4SAndroid Build Coastguard Worker }
113*bb4ee6a4SAndroid Build Coastguard Worker
114*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_write_same()115*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_write_same() {
116*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new();
117*bb4ee6a4SAndroid Build Coastguard Worker write_same_scsi(config).unwrap();
118*bb4ee6a4SAndroid Build Coastguard Worker }
119*bb4ee6a4SAndroid Build Coastguard Worker
120*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_write_same_disable_sandbox()121*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_write_same_disable_sandbox() {
122*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new().disable_sandbox();
123*bb4ee6a4SAndroid Build Coastguard Worker write_same_scsi(config).unwrap();
124*bb4ee6a4SAndroid Build Coastguard Worker }
125*bb4ee6a4SAndroid Build Coastguard Worker
unmap_scsi(config: Config) -> anyhow::Result<()>126*bb4ee6a4SAndroid Build Coastguard Worker fn unmap_scsi(config: Config) -> anyhow::Result<()> {
127*bb4ee6a4SAndroid Build Coastguard Worker let disk = prepare_disk_img();
128*bb4ee6a4SAndroid Build Coastguard Worker let scsi_disk = disk.path().to_str().unwrap();
129*bb4ee6a4SAndroid Build Coastguard Worker let config = config.extra_args(vec!["--scsi-block".to_string(), scsi_disk.to_string()]);
130*bb4ee6a4SAndroid Build Coastguard Worker println!("scsi-disk={scsi_disk}");
131*bb4ee6a4SAndroid Build Coastguard Worker
132*bb4ee6a4SAndroid Build Coastguard Worker let mut vm = TestVm::new(config)?;
133*bb4ee6a4SAndroid Build Coastguard Worker assert!(vm
134*bb4ee6a4SAndroid Build Coastguard Worker .exec_in_guest("sg_unmap --lba=0 --num=1 -f /dev/sda")
135*bb4ee6a4SAndroid Build Coastguard Worker .is_ok());
136*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
137*bb4ee6a4SAndroid Build Coastguard Worker }
138*bb4ee6a4SAndroid Build Coastguard Worker
139*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_unmap()140*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_unmap() {
141*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new();
142*bb4ee6a4SAndroid Build Coastguard Worker unmap_scsi(config).unwrap();
143*bb4ee6a4SAndroid Build Coastguard Worker }
144*bb4ee6a4SAndroid Build Coastguard Worker
145*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_scsi_unmap_disable_sandbox()146*bb4ee6a4SAndroid Build Coastguard Worker fn test_scsi_unmap_disable_sandbox() {
147*bb4ee6a4SAndroid Build Coastguard Worker let config = Config::new().disable_sandbox();
148*bb4ee6a4SAndroid Build Coastguard Worker unmap_scsi(config).unwrap();
149*bb4ee6a4SAndroid Build Coastguard Worker }
150