devices/virtio/scsi/
mod.rs

1// Copyright 2023 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::path::PathBuf;
6
7use serde::Deserialize;
8use serde::Serialize;
9
10pub(crate) mod sys;
11
12pub mod commands;
13pub mod constants;
14mod device;
15
16pub use device::Controller;
17pub use device::DiskConfig;
18
19fn scsi_option_lock_default() -> bool {
20    true
21}
22fn scsi_option_block_size_default() -> u32 {
23    512
24}
25
26/// Parameters for setting up a SCSI device.
27#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, serde_keyvalue::FromKeyValues)]
28#[serde(deny_unknown_fields, rename_all = "kebab-case")]
29pub struct ScsiOption {
30    // Path to the SCSI image.
31    pub path: PathBuf,
32    // Indicates whether the device is ready only.
33    #[serde(default, rename = "ro")]
34    pub read_only: bool,
35    /// Whether to lock the disk files. Uses flock on Unix and FILE_SHARE_* flags on Windows.
36    #[serde(default = "scsi_option_lock_default")]
37    pub lock: bool,
38    // The block size of the device.
39    #[serde(default = "scsi_option_block_size_default")]
40    pub block_size: u32,
41    /// Whether this scsi device should be the root device. Can only be set once. Only useful for
42    /// adding specific command-line options.
43    #[serde(default)]
44    pub root: bool,
45}
46
47#[cfg(test)]
48impl Default for ScsiOption {
49    fn default() -> Self {
50        Self {
51            path: PathBuf::new(),
52            read_only: false,
53            lock: scsi_option_lock_default(),
54            block_size: scsi_option_block_size_default(),
55            root: false,
56        }
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use std::path::Path;
63
64    use serde_keyvalue::from_key_values;
65
66    use super::*;
67
68    #[test]
69    fn parse_scsi_options() {
70        let scsi_option = from_key_values::<ScsiOption>("/path/to/image").unwrap();
71        assert_eq!(
72            scsi_option,
73            ScsiOption {
74                path: Path::new("/path/to/image").to_path_buf(),
75                ..Default::default()
76            }
77        );
78
79        let scsi_option = from_key_values::<ScsiOption>("/path/to/image,ro").unwrap();
80        assert_eq!(
81            scsi_option,
82            ScsiOption {
83                path: Path::new("/path/to/image").to_path_buf(),
84                read_only: true,
85                ..Default::default()
86            }
87        );
88
89        let scsi_option = from_key_values::<ScsiOption>("/path/to/image,block-size=1024").unwrap();
90        assert_eq!(
91            scsi_option,
92            ScsiOption {
93                path: Path::new("/path/to/image").to_path_buf(),
94                block_size: 1024,
95                ..Default::default()
96            }
97        );
98
99        let scsi_option =
100            from_key_values::<ScsiOption>("/path/to/image,block-size=1024,root").unwrap();
101        assert_eq!(
102            scsi_option,
103            ScsiOption {
104                path: Path::new("/path/to/image").to_path_buf(),
105                block_size: 1024,
106                root: true,
107                ..Default::default()
108            }
109        );
110    }
111}