xref: /aosp_15_r20/external/crosvm/devices/src/virtio/block/mod.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2021 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 #[cfg(windows)]
6*bb4ee6a4SAndroid Build Coastguard Worker use std::num::NonZeroU32;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
8*bb4ee6a4SAndroid Build Coastguard Worker 
9*bb4ee6a4SAndroid Build Coastguard Worker use cros_async::ExecutorKind;
10*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserialize;
11*bb4ee6a4SAndroid Build Coastguard Worker use serde::Deserializer;
12*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serialize;
13*bb4ee6a4SAndroid Build Coastguard Worker use serde::Serializer;
14*bb4ee6a4SAndroid Build Coastguard Worker 
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::PciAddress;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker pub mod asynchronous;
18*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) mod sys;
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker pub use asynchronous::BlockAsync;
21*bb4ee6a4SAndroid Build Coastguard Worker 
block_option_sparse_default() -> bool22*bb4ee6a4SAndroid Build Coastguard Worker fn block_option_sparse_default() -> bool {
23*bb4ee6a4SAndroid Build Coastguard Worker     true
24*bb4ee6a4SAndroid Build Coastguard Worker }
block_option_lock_default() -> bool25*bb4ee6a4SAndroid Build Coastguard Worker fn block_option_lock_default() -> bool {
26*bb4ee6a4SAndroid Build Coastguard Worker     true
27*bb4ee6a4SAndroid Build Coastguard Worker }
block_option_block_size_default() -> u3228*bb4ee6a4SAndroid Build Coastguard Worker fn block_option_block_size_default() -> u32 {
29*bb4ee6a4SAndroid Build Coastguard Worker     512
30*bb4ee6a4SAndroid Build Coastguard Worker }
31*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/237829580): Move to sys module once virtio block sys is refactored to
32*bb4ee6a4SAndroid Build Coastguard Worker // match the style guide.
33*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
block_option_io_concurrency_default() -> NonZeroU3234*bb4ee6a4SAndroid Build Coastguard Worker fn block_option_io_concurrency_default() -> NonZeroU32 {
35*bb4ee6a4SAndroid Build Coastguard Worker     NonZeroU32::new(1).unwrap()
36*bb4ee6a4SAndroid Build Coastguard Worker }
37*bb4ee6a4SAndroid Build Coastguard Worker 
38*bb4ee6a4SAndroid Build Coastguard Worker /// Maximum length of a `DiskOption` identifier.
39*bb4ee6a4SAndroid Build Coastguard Worker ///
40*bb4ee6a4SAndroid Build Coastguard Worker /// This is based on the virtio-block ID length limit.
41*bb4ee6a4SAndroid Build Coastguard Worker pub const DISK_ID_LEN: usize = 20;
42*bb4ee6a4SAndroid Build Coastguard Worker 
serialize_disk_id<S: Serializer>( id: &Option<[u8; DISK_ID_LEN]>, serializer: S, ) -> Result<S::Ok, S::Error>43*bb4ee6a4SAndroid Build Coastguard Worker pub fn serialize_disk_id<S: Serializer>(
44*bb4ee6a4SAndroid Build Coastguard Worker     id: &Option<[u8; DISK_ID_LEN]>,
45*bb4ee6a4SAndroid Build Coastguard Worker     serializer: S,
46*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<S::Ok, S::Error> {
47*bb4ee6a4SAndroid Build Coastguard Worker     match id {
48*bb4ee6a4SAndroid Build Coastguard Worker         None => serializer.serialize_none(),
49*bb4ee6a4SAndroid Build Coastguard Worker         Some(id) => {
50*bb4ee6a4SAndroid Build Coastguard Worker             // Find the first zero byte in the id.
51*bb4ee6a4SAndroid Build Coastguard Worker             let len = id.iter().position(|v| *v == 0).unwrap_or(DISK_ID_LEN);
52*bb4ee6a4SAndroid Build Coastguard Worker             serializer.serialize_some(
53*bb4ee6a4SAndroid Build Coastguard Worker                 std::str::from_utf8(&id[0..len])
54*bb4ee6a4SAndroid Build Coastguard Worker                     .map_err(|e| serde::ser::Error::custom(e.to_string()))?,
55*bb4ee6a4SAndroid Build Coastguard Worker             )
56*bb4ee6a4SAndroid Build Coastguard Worker         }
57*bb4ee6a4SAndroid Build Coastguard Worker     }
58*bb4ee6a4SAndroid Build Coastguard Worker }
59*bb4ee6a4SAndroid Build Coastguard Worker 
deserialize_disk_id<'de, D: Deserializer<'de>>( deserializer: D, ) -> Result<Option<[u8; DISK_ID_LEN]>, D::Error>60*bb4ee6a4SAndroid Build Coastguard Worker fn deserialize_disk_id<'de, D: Deserializer<'de>>(
61*bb4ee6a4SAndroid Build Coastguard Worker     deserializer: D,
62*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Option<[u8; DISK_ID_LEN]>, D::Error> {
63*bb4ee6a4SAndroid Build Coastguard Worker     let id = Option::<String>::deserialize(deserializer)?;
64*bb4ee6a4SAndroid Build Coastguard Worker 
65*bb4ee6a4SAndroid Build Coastguard Worker     match id {
66*bb4ee6a4SAndroid Build Coastguard Worker         None => Ok(None),
67*bb4ee6a4SAndroid Build Coastguard Worker         Some(id) => {
68*bb4ee6a4SAndroid Build Coastguard Worker             if id.len() > DISK_ID_LEN {
69*bb4ee6a4SAndroid Build Coastguard Worker                 return Err(serde::de::Error::custom(format!(
70*bb4ee6a4SAndroid Build Coastguard Worker                     "disk id must be {} or fewer characters",
71*bb4ee6a4SAndroid Build Coastguard Worker                     DISK_ID_LEN
72*bb4ee6a4SAndroid Build Coastguard Worker                 )));
73*bb4ee6a4SAndroid Build Coastguard Worker             }
74*bb4ee6a4SAndroid Build Coastguard Worker 
75*bb4ee6a4SAndroid Build Coastguard Worker             let mut ret = [0u8; DISK_ID_LEN];
76*bb4ee6a4SAndroid Build Coastguard Worker             // Slicing id to value's length will never panic
77*bb4ee6a4SAndroid Build Coastguard Worker             // because we checked that value will fit into id above.
78*bb4ee6a4SAndroid Build Coastguard Worker             ret[..id.len()].copy_from_slice(id.as_bytes());
79*bb4ee6a4SAndroid Build Coastguard Worker             Ok(Some(ret))
80*bb4ee6a4SAndroid Build Coastguard Worker         }
81*bb4ee6a4SAndroid Build Coastguard Worker     }
82*bb4ee6a4SAndroid Build Coastguard Worker }
83*bb4ee6a4SAndroid Build Coastguard Worker 
84*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, serde_keyvalue::FromKeyValues)]
85*bb4ee6a4SAndroid Build Coastguard Worker #[serde(deny_unknown_fields, rename_all = "kebab-case")]
86*bb4ee6a4SAndroid Build Coastguard Worker pub struct DiskOption {
87*bb4ee6a4SAndroid Build Coastguard Worker     pub path: PathBuf,
88*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default, rename = "ro")]
89*bb4ee6a4SAndroid Build Coastguard Worker     pub read_only: bool,
90*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default)]
91*bb4ee6a4SAndroid Build Coastguard Worker     /// Whether this disk should be the root device. Can only be set once. Only useful for adding
92*bb4ee6a4SAndroid Build Coastguard Worker     /// specific command-line options.
93*bb4ee6a4SAndroid Build Coastguard Worker     pub root: bool,
94*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default = "block_option_sparse_default")]
95*bb4ee6a4SAndroid Build Coastguard Worker     pub sparse: bool,
96*bb4ee6a4SAndroid Build Coastguard Worker     // camel_case variant allowed for backward compatibility.
97*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default, alias = "o_direct")]
98*bb4ee6a4SAndroid Build Coastguard Worker     pub direct: bool,
99*bb4ee6a4SAndroid Build Coastguard Worker     /// Whether to lock the disk files. Uses flock on Unix and FILE_SHARE_* flags on Windows.
100*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default = "block_option_lock_default")]
101*bb4ee6a4SAndroid Build Coastguard Worker     pub lock: bool,
102*bb4ee6a4SAndroid Build Coastguard Worker     // camel_case variant allowed for backward compatibility.
103*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default = "block_option_block_size_default", alias = "block_size")]
104*bb4ee6a4SAndroid Build Coastguard Worker     pub block_size: u32,
105*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(
106*bb4ee6a4SAndroid Build Coastguard Worker         default,
107*bb4ee6a4SAndroid Build Coastguard Worker         serialize_with = "serialize_disk_id",
108*bb4ee6a4SAndroid Build Coastguard Worker         deserialize_with = "deserialize_disk_id"
109*bb4ee6a4SAndroid Build Coastguard Worker     )]
110*bb4ee6a4SAndroid Build Coastguard Worker     pub id: Option<[u8; DISK_ID_LEN]>,
111*bb4ee6a4SAndroid Build Coastguard Worker     // Deprecated: Use async_executor=overlapped[concurrency=N]"
112*bb4ee6a4SAndroid Build Coastguard Worker     // camel_case variant allowed for backward compatibility.
113*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(windows)]
114*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(
115*bb4ee6a4SAndroid Build Coastguard Worker         default = "block_option_io_concurrency_default",
116*bb4ee6a4SAndroid Build Coastguard Worker         alias = "io_concurrency"
117*bb4ee6a4SAndroid Build Coastguard Worker     )]
118*bb4ee6a4SAndroid Build Coastguard Worker     pub io_concurrency: NonZeroU32,
119*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default)]
120*bb4ee6a4SAndroid Build Coastguard Worker     /// Experimental option to run multiple worker threads in parallel. If false, only single
121*bb4ee6a4SAndroid Build Coastguard Worker     /// thread runs by default. Note this option is not effective for vhost-user blk device.
122*bb4ee6a4SAndroid Build Coastguard Worker     pub multiple_workers: bool,
123*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default, alias = "async_executor")]
124*bb4ee6a4SAndroid Build Coastguard Worker     /// The async executor kind to simulate the block device with. This option takes
125*bb4ee6a4SAndroid Build Coastguard Worker     /// precedence over the async executor kind specified by the subcommand's option.
126*bb4ee6a4SAndroid Build Coastguard Worker     /// If None, the default or the specified by the subcommand's option would be used.
127*bb4ee6a4SAndroid Build Coastguard Worker     pub async_executor: Option<ExecutorKind>,
128*bb4ee6a4SAndroid Build Coastguard Worker     #[serde(default)]
129*bb4ee6a4SAndroid Build Coastguard Worker     //Option to choose virtqueue type. If true, use the packed virtqueue. If false
130*bb4ee6a4SAndroid Build Coastguard Worker     //or by default, use split virtqueue
131*bb4ee6a4SAndroid Build Coastguard Worker     pub packed_queue: bool,
132*bb4ee6a4SAndroid Build Coastguard Worker 
133*bb4ee6a4SAndroid Build Coastguard Worker     /// Specify the boot index for this device that the BIOS will use when attempting to boot from
134*bb4ee6a4SAndroid Build Coastguard Worker     /// bootable devices. For example, if bootindex=2, then the BIOS will attempt to boot from the
135*bb4ee6a4SAndroid Build Coastguard Worker     /// device right after booting from the device with bootindex=1 fails.
136*bb4ee6a4SAndroid Build Coastguard Worker     pub bootindex: Option<usize>,
137*bb4ee6a4SAndroid Build Coastguard Worker 
138*bb4ee6a4SAndroid Build Coastguard Worker     /// Specify PCI address will be used to attach this device
139*bb4ee6a4SAndroid Build Coastguard Worker     pub pci_address: Option<PciAddress>,
140*bb4ee6a4SAndroid Build Coastguard Worker }
141*bb4ee6a4SAndroid Build Coastguard Worker 
142*bb4ee6a4SAndroid Build Coastguard Worker impl Default for DiskOption {
default() -> Self143*bb4ee6a4SAndroid Build Coastguard Worker     fn default() -> Self {
144*bb4ee6a4SAndroid Build Coastguard Worker         Self {
145*bb4ee6a4SAndroid Build Coastguard Worker             path: PathBuf::new(),
146*bb4ee6a4SAndroid Build Coastguard Worker             read_only: false,
147*bb4ee6a4SAndroid Build Coastguard Worker             root: false,
148*bb4ee6a4SAndroid Build Coastguard Worker             sparse: block_option_sparse_default(),
149*bb4ee6a4SAndroid Build Coastguard Worker             direct: false,
150*bb4ee6a4SAndroid Build Coastguard Worker             lock: block_option_lock_default(),
151*bb4ee6a4SAndroid Build Coastguard Worker             block_size: block_option_block_size_default(),
152*bb4ee6a4SAndroid Build Coastguard Worker             id: None,
153*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(windows)]
154*bb4ee6a4SAndroid Build Coastguard Worker             io_concurrency: block_option_io_concurrency_default(),
155*bb4ee6a4SAndroid Build Coastguard Worker             multiple_workers: false,
156*bb4ee6a4SAndroid Build Coastguard Worker             async_executor: None,
157*bb4ee6a4SAndroid Build Coastguard Worker             packed_queue: false,
158*bb4ee6a4SAndroid Build Coastguard Worker             bootindex: None,
159*bb4ee6a4SAndroid Build Coastguard Worker             pci_address: None,
160*bb4ee6a4SAndroid Build Coastguard Worker         }
161*bb4ee6a4SAndroid Build Coastguard Worker     }
162*bb4ee6a4SAndroid Build Coastguard Worker }
163*bb4ee6a4SAndroid Build Coastguard Worker 
164*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
165*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
166*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(any(target_os = "android", target_os = "linux"))]
167*bb4ee6a4SAndroid Build Coastguard Worker     use cros_async::sys::linux::ExecutorKindSys;
168*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(windows)]
169*bb4ee6a4SAndroid Build Coastguard Worker     use cros_async::sys::windows::ExecutorKindSys;
170*bb4ee6a4SAndroid Build Coastguard Worker     use serde_keyvalue::*;
171*bb4ee6a4SAndroid Build Coastguard Worker 
172*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
173*bb4ee6a4SAndroid Build Coastguard Worker 
from_block_arg(options: &str) -> Result<DiskOption, ParseError>174*bb4ee6a4SAndroid Build Coastguard Worker     fn from_block_arg(options: &str) -> Result<DiskOption, ParseError> {
175*bb4ee6a4SAndroid Build Coastguard Worker         from_key_values(options)
176*bb4ee6a4SAndroid Build Coastguard Worker     }
177*bb4ee6a4SAndroid Build Coastguard Worker 
178*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
check_default_matches_from_key_values()179*bb4ee6a4SAndroid Build Coastguard Worker     fn check_default_matches_from_key_values() {
180*bb4ee6a4SAndroid Build Coastguard Worker         let path = "/path/to/disk.img";
181*bb4ee6a4SAndroid Build Coastguard Worker         let disk = DiskOption {
182*bb4ee6a4SAndroid Build Coastguard Worker             path: PathBuf::from(path),
183*bb4ee6a4SAndroid Build Coastguard Worker             ..DiskOption::default()
184*bb4ee6a4SAndroid Build Coastguard Worker         };
185*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(disk, from_key_values(path).unwrap());
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker 
188*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
params_from_key_values()189*bb4ee6a4SAndroid Build Coastguard Worker     fn params_from_key_values() {
190*bb4ee6a4SAndroid Build Coastguard Worker         // Path argument is mandatory.
191*bb4ee6a4SAndroid Build Coastguard Worker         let err = from_block_arg("").unwrap_err();
192*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
193*bb4ee6a4SAndroid Build Coastguard Worker             err,
194*bb4ee6a4SAndroid Build Coastguard Worker             ParseError {
195*bb4ee6a4SAndroid Build Coastguard Worker                 kind: ErrorKind::SerdeError("missing field `path`".into()),
196*bb4ee6a4SAndroid Build Coastguard Worker                 pos: 0,
197*bb4ee6a4SAndroid Build Coastguard Worker             }
198*bb4ee6a4SAndroid Build Coastguard Worker         );
199*bb4ee6a4SAndroid Build Coastguard Worker 
200*bb4ee6a4SAndroid Build Coastguard Worker         // Path is the default argument.
201*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/path/to/disk.img").unwrap();
202*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
203*bb4ee6a4SAndroid Build Coastguard Worker             params,
204*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
205*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/path/to/disk.img".into(),
206*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
207*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
208*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
209*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
210*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
211*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
212*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
213*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
214*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
215*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
216*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
217*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
218*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
219*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
220*bb4ee6a4SAndroid Build Coastguard Worker             }
221*bb4ee6a4SAndroid Build Coastguard Worker         );
222*bb4ee6a4SAndroid Build Coastguard Worker 
223*bb4ee6a4SAndroid Build Coastguard Worker         // bootindex
224*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/path/to/disk.img,bootindex=5").unwrap();
225*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
226*bb4ee6a4SAndroid Build Coastguard Worker             params,
227*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
228*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/path/to/disk.img".into(),
229*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
230*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
231*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
232*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
233*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
234*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
235*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
236*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
237*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
238*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
239*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
240*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
241*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: Some(5),
242*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
243*bb4ee6a4SAndroid Build Coastguard Worker             }
244*bb4ee6a4SAndroid Build Coastguard Worker         );
245*bb4ee6a4SAndroid Build Coastguard Worker 
246*bb4ee6a4SAndroid Build Coastguard Worker         // Explicitly-specified path.
247*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("path=/path/to/disk.img").unwrap();
248*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
249*bb4ee6a4SAndroid Build Coastguard Worker             params,
250*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
251*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/path/to/disk.img".into(),
252*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
253*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
254*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
255*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
256*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
257*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
258*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
259*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
260*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
261*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
262*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
263*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
264*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
265*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
266*bb4ee6a4SAndroid Build Coastguard Worker             }
267*bb4ee6a4SAndroid Build Coastguard Worker         );
268*bb4ee6a4SAndroid Build Coastguard Worker 
269*bb4ee6a4SAndroid Build Coastguard Worker         // read_only
270*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/some/path.img,ro").unwrap();
271*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
272*bb4ee6a4SAndroid Build Coastguard Worker             params,
273*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
274*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
275*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: true,
276*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
277*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
278*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
279*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
280*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
281*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
282*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
283*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
284*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
285*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
286*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
287*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
288*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
289*bb4ee6a4SAndroid Build Coastguard Worker             }
290*bb4ee6a4SAndroid Build Coastguard Worker         );
291*bb4ee6a4SAndroid Build Coastguard Worker 
292*bb4ee6a4SAndroid Build Coastguard Worker         // root
293*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/some/path.img,root").unwrap();
294*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
295*bb4ee6a4SAndroid Build Coastguard Worker             params,
296*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
297*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
298*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
299*bb4ee6a4SAndroid Build Coastguard Worker                 root: true,
300*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
301*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
302*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
303*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
304*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
305*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
306*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
307*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
308*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
309*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
310*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
311*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
312*bb4ee6a4SAndroid Build Coastguard Worker             }
313*bb4ee6a4SAndroid Build Coastguard Worker         );
314*bb4ee6a4SAndroid Build Coastguard Worker 
315*bb4ee6a4SAndroid Build Coastguard Worker         // sparse
316*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/some/path.img,sparse").unwrap();
317*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
318*bb4ee6a4SAndroid Build Coastguard Worker             params,
319*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
320*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
321*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
322*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
323*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
324*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
325*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
326*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
327*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
328*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
329*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
330*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
331*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
332*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
333*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
334*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
335*bb4ee6a4SAndroid Build Coastguard Worker             }
336*bb4ee6a4SAndroid Build Coastguard Worker         );
337*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/some/path.img,sparse=false").unwrap();
338*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
339*bb4ee6a4SAndroid Build Coastguard Worker             params,
340*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
341*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
342*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
343*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
344*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: false,
345*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
346*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
347*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
348*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
349*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
350*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
351*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
352*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
353*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
354*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
355*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
356*bb4ee6a4SAndroid Build Coastguard Worker             }
357*bb4ee6a4SAndroid Build Coastguard Worker         );
358*bb4ee6a4SAndroid Build Coastguard Worker 
359*bb4ee6a4SAndroid Build Coastguard Worker         // direct
360*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/some/path.img,direct").unwrap();
361*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
362*bb4ee6a4SAndroid Build Coastguard Worker             params,
363*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
364*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
365*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
366*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
367*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
368*bb4ee6a4SAndroid Build Coastguard Worker                 direct: true,
369*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
370*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
371*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
372*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
373*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
374*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
375*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
376*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
377*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
378*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
379*bb4ee6a4SAndroid Build Coastguard Worker             }
380*bb4ee6a4SAndroid Build Coastguard Worker         );
381*bb4ee6a4SAndroid Build Coastguard Worker 
382*bb4ee6a4SAndroid Build Coastguard Worker         // o_direct (deprecated, kept for backward compatibility)
383*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/some/path.img,o_direct").unwrap();
384*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
385*bb4ee6a4SAndroid Build Coastguard Worker             params,
386*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
387*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
388*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
389*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
390*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
391*bb4ee6a4SAndroid Build Coastguard Worker                 direct: true,
392*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
393*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
394*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
395*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
396*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
397*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
398*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
399*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
400*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
401*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
402*bb4ee6a4SAndroid Build Coastguard Worker             }
403*bb4ee6a4SAndroid Build Coastguard Worker         );
404*bb4ee6a4SAndroid Build Coastguard Worker 
405*bb4ee6a4SAndroid Build Coastguard Worker         // block-size
406*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/some/path.img,block-size=128").unwrap();
407*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
408*bb4ee6a4SAndroid Build Coastguard Worker             params,
409*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
410*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
411*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
412*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
413*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
414*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
415*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
416*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 128,
417*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
418*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
419*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
420*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
421*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
422*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
423*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
424*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
425*bb4ee6a4SAndroid Build Coastguard Worker             }
426*bb4ee6a4SAndroid Build Coastguard Worker         );
427*bb4ee6a4SAndroid Build Coastguard Worker 
428*bb4ee6a4SAndroid Build Coastguard Worker         // block_size (deprecated, kept for backward compatibility)
429*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/some/path.img,block_size=128").unwrap();
430*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
431*bb4ee6a4SAndroid Build Coastguard Worker             params,
432*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
433*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
434*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
435*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
436*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
437*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
438*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
439*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 128,
440*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
441*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
442*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
443*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
444*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
445*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
446*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
447*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
448*bb4ee6a4SAndroid Build Coastguard Worker             }
449*bb4ee6a4SAndroid Build Coastguard Worker         );
450*bb4ee6a4SAndroid Build Coastguard Worker 
451*bb4ee6a4SAndroid Build Coastguard Worker         // io_concurrency
452*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(windows)]
453*bb4ee6a4SAndroid Build Coastguard Worker         {
454*bb4ee6a4SAndroid Build Coastguard Worker             let params = from_block_arg("/some/path.img,io_concurrency=4").unwrap();
455*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(
456*bb4ee6a4SAndroid Build Coastguard Worker                 params,
457*bb4ee6a4SAndroid Build Coastguard Worker                 DiskOption {
458*bb4ee6a4SAndroid Build Coastguard Worker                     path: "/some/path.img".into(),
459*bb4ee6a4SAndroid Build Coastguard Worker                     read_only: false,
460*bb4ee6a4SAndroid Build Coastguard Worker                     root: false,
461*bb4ee6a4SAndroid Build Coastguard Worker                     sparse: true,
462*bb4ee6a4SAndroid Build Coastguard Worker                     direct: false,
463*bb4ee6a4SAndroid Build Coastguard Worker                     lock: true,
464*bb4ee6a4SAndroid Build Coastguard Worker                     block_size: 512,
465*bb4ee6a4SAndroid Build Coastguard Worker                     id: None,
466*bb4ee6a4SAndroid Build Coastguard Worker                     io_concurrency: NonZeroU32::new(4).unwrap(),
467*bb4ee6a4SAndroid Build Coastguard Worker                     multiple_workers: false,
468*bb4ee6a4SAndroid Build Coastguard Worker                     async_executor: None,
469*bb4ee6a4SAndroid Build Coastguard Worker                     packed_queue: false,
470*bb4ee6a4SAndroid Build Coastguard Worker                     bootindex: None,
471*bb4ee6a4SAndroid Build Coastguard Worker                     pci_address: None,
472*bb4ee6a4SAndroid Build Coastguard Worker                 }
473*bb4ee6a4SAndroid Build Coastguard Worker             );
474*bb4ee6a4SAndroid Build Coastguard Worker             let params = from_block_arg("/some/path.img,async-executor=overlapped").unwrap();
475*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(
476*bb4ee6a4SAndroid Build Coastguard Worker                 params,
477*bb4ee6a4SAndroid Build Coastguard Worker                 DiskOption {
478*bb4ee6a4SAndroid Build Coastguard Worker                     path: "/some/path.img".into(),
479*bb4ee6a4SAndroid Build Coastguard Worker                     read_only: false,
480*bb4ee6a4SAndroid Build Coastguard Worker                     root: false,
481*bb4ee6a4SAndroid Build Coastguard Worker                     sparse: true,
482*bb4ee6a4SAndroid Build Coastguard Worker                     direct: false,
483*bb4ee6a4SAndroid Build Coastguard Worker                     lock: true,
484*bb4ee6a4SAndroid Build Coastguard Worker                     block_size: 512,
485*bb4ee6a4SAndroid Build Coastguard Worker                     id: None,
486*bb4ee6a4SAndroid Build Coastguard Worker                     io_concurrency: NonZeroU32::new(1).unwrap(),
487*bb4ee6a4SAndroid Build Coastguard Worker                     multiple_workers: false,
488*bb4ee6a4SAndroid Build Coastguard Worker                     async_executor: Some(ExecutorKindSys::Overlapped { concurrency: None }.into()),
489*bb4ee6a4SAndroid Build Coastguard Worker                     packed_queue: false,
490*bb4ee6a4SAndroid Build Coastguard Worker                     bootindex: None,
491*bb4ee6a4SAndroid Build Coastguard Worker                     pci_address: None,
492*bb4ee6a4SAndroid Build Coastguard Worker                 }
493*bb4ee6a4SAndroid Build Coastguard Worker             );
494*bb4ee6a4SAndroid Build Coastguard Worker             let params =
495*bb4ee6a4SAndroid Build Coastguard Worker                 from_block_arg("/some/path.img,async-executor=\"overlapped,concurrency=4\"")
496*bb4ee6a4SAndroid Build Coastguard Worker                     .unwrap();
497*bb4ee6a4SAndroid Build Coastguard Worker             assert_eq!(
498*bb4ee6a4SAndroid Build Coastguard Worker                 params,
499*bb4ee6a4SAndroid Build Coastguard Worker                 DiskOption {
500*bb4ee6a4SAndroid Build Coastguard Worker                     path: "/some/path.img".into(),
501*bb4ee6a4SAndroid Build Coastguard Worker                     read_only: false,
502*bb4ee6a4SAndroid Build Coastguard Worker                     root: false,
503*bb4ee6a4SAndroid Build Coastguard Worker                     sparse: true,
504*bb4ee6a4SAndroid Build Coastguard Worker                     direct: false,
505*bb4ee6a4SAndroid Build Coastguard Worker                     lock: true,
506*bb4ee6a4SAndroid Build Coastguard Worker                     block_size: 512,
507*bb4ee6a4SAndroid Build Coastguard Worker                     id: None,
508*bb4ee6a4SAndroid Build Coastguard Worker                     io_concurrency: NonZeroU32::new(1).unwrap(),
509*bb4ee6a4SAndroid Build Coastguard Worker                     multiple_workers: false,
510*bb4ee6a4SAndroid Build Coastguard Worker                     async_executor: Some(
511*bb4ee6a4SAndroid Build Coastguard Worker                         ExecutorKindSys::Overlapped {
512*bb4ee6a4SAndroid Build Coastguard Worker                             concurrency: Some(4)
513*bb4ee6a4SAndroid Build Coastguard Worker                         }
514*bb4ee6a4SAndroid Build Coastguard Worker                         .into()
515*bb4ee6a4SAndroid Build Coastguard Worker                     ),
516*bb4ee6a4SAndroid Build Coastguard Worker                     packed_queue: false,
517*bb4ee6a4SAndroid Build Coastguard Worker                     bootindex: None,
518*bb4ee6a4SAndroid Build Coastguard Worker                     pci_address: None,
519*bb4ee6a4SAndroid Build Coastguard Worker                 }
520*bb4ee6a4SAndroid Build Coastguard Worker             );
521*bb4ee6a4SAndroid Build Coastguard Worker         }
522*bb4ee6a4SAndroid Build Coastguard Worker 
523*bb4ee6a4SAndroid Build Coastguard Worker         // id
524*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/some/path.img,id=DISK").unwrap();
525*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
526*bb4ee6a4SAndroid Build Coastguard Worker             params,
527*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
528*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
529*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
530*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
531*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
532*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
533*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
534*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
535*bb4ee6a4SAndroid Build Coastguard Worker                 id: Some(*b"DISK\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"),
536*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
537*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
538*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
539*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
540*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
541*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
542*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
543*bb4ee6a4SAndroid Build Coastguard Worker             }
544*bb4ee6a4SAndroid Build Coastguard Worker         );
545*bb4ee6a4SAndroid Build Coastguard Worker         let err = from_block_arg("/some/path.img,id=DISK_ID_IS_WAY_TOO_LONG").unwrap_err();
546*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
547*bb4ee6a4SAndroid Build Coastguard Worker             err,
548*bb4ee6a4SAndroid Build Coastguard Worker             ParseError {
549*bb4ee6a4SAndroid Build Coastguard Worker                 kind: ErrorKind::SerdeError("disk id must be 20 or fewer characters".into()),
550*bb4ee6a4SAndroid Build Coastguard Worker                 pos: 0,
551*bb4ee6a4SAndroid Build Coastguard Worker             }
552*bb4ee6a4SAndroid Build Coastguard Worker         );
553*bb4ee6a4SAndroid Build Coastguard Worker 
554*bb4ee6a4SAndroid Build Coastguard Worker         // async-executor
555*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(windows)]
556*bb4ee6a4SAndroid Build Coastguard Worker         let (ex_kind, ex_kind_opt) = (ExecutorKindSys::Handle.into(), "handle");
557*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
558*bb4ee6a4SAndroid Build Coastguard Worker         let (ex_kind, ex_kind_opt) = (ExecutorKindSys::Fd.into(), "epoll");
559*bb4ee6a4SAndroid Build Coastguard Worker         let params =
560*bb4ee6a4SAndroid Build Coastguard Worker             from_block_arg(&format!("/some/path.img,async-executor={ex_kind_opt}")).unwrap();
561*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
562*bb4ee6a4SAndroid Build Coastguard Worker             params,
563*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
564*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
565*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
566*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
567*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
568*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
569*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
570*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
571*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
572*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
573*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
574*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
575*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: Some(ex_kind),
576*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
577*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
578*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
579*bb4ee6a4SAndroid Build Coastguard Worker             }
580*bb4ee6a4SAndroid Build Coastguard Worker         );
581*bb4ee6a4SAndroid Build Coastguard Worker 
582*bb4ee6a4SAndroid Build Coastguard Worker         // packed queue
583*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/path/to/disk.img,packed-queue").unwrap();
584*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
585*bb4ee6a4SAndroid Build Coastguard Worker             params,
586*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
587*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/path/to/disk.img".into(),
588*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
589*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
590*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
591*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
592*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
593*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
594*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
595*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
596*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
597*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
598*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
599*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: true,
600*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
601*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
602*bb4ee6a4SAndroid Build Coastguard Worker             }
603*bb4ee6a4SAndroid Build Coastguard Worker         );
604*bb4ee6a4SAndroid Build Coastguard Worker 
605*bb4ee6a4SAndroid Build Coastguard Worker         // pci-address
606*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/path/to/disk.img,pci-address=00:01.1").unwrap();
607*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
608*bb4ee6a4SAndroid Build Coastguard Worker             params,
609*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
610*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/path/to/disk.img".into(),
611*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
612*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
613*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
614*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
615*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
616*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
617*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
618*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
619*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
620*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
621*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
622*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
623*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
624*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: Some(PciAddress {
625*bb4ee6a4SAndroid Build Coastguard Worker                     bus: 0,
626*bb4ee6a4SAndroid Build Coastguard Worker                     dev: 1,
627*bb4ee6a4SAndroid Build Coastguard Worker                     func: 1,
628*bb4ee6a4SAndroid Build Coastguard Worker                 }),
629*bb4ee6a4SAndroid Build Coastguard Worker             }
630*bb4ee6a4SAndroid Build Coastguard Worker         );
631*bb4ee6a4SAndroid Build Coastguard Worker 
632*bb4ee6a4SAndroid Build Coastguard Worker         // lock=true
633*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/path/to/disk.img,lock=true").unwrap();
634*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
635*bb4ee6a4SAndroid Build Coastguard Worker             params,
636*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
637*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/path/to/disk.img".into(),
638*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
639*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
640*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
641*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
642*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
643*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
644*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
645*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
646*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
647*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
648*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
649*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
650*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
651*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
652*bb4ee6a4SAndroid Build Coastguard Worker             }
653*bb4ee6a4SAndroid Build Coastguard Worker         );
654*bb4ee6a4SAndroid Build Coastguard Worker         // lock=false
655*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg("/path/to/disk.img,lock=false").unwrap();
656*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
657*bb4ee6a4SAndroid Build Coastguard Worker             params,
658*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
659*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/path/to/disk.img".into(),
660*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: false,
661*bb4ee6a4SAndroid Build Coastguard Worker                 root: false,
662*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: true,
663*bb4ee6a4SAndroid Build Coastguard Worker                 direct: false,
664*bb4ee6a4SAndroid Build Coastguard Worker                 lock: false,
665*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 512,
666*bb4ee6a4SAndroid Build Coastguard Worker                 id: None,
667*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
668*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
669*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
670*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: None,
671*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
672*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
673*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: None,
674*bb4ee6a4SAndroid Build Coastguard Worker             }
675*bb4ee6a4SAndroid Build Coastguard Worker         );
676*bb4ee6a4SAndroid Build Coastguard Worker 
677*bb4ee6a4SAndroid Build Coastguard Worker         // All together
678*bb4ee6a4SAndroid Build Coastguard Worker         let params = from_block_arg(&format!(
679*bb4ee6a4SAndroid Build Coastguard Worker             "/some/path.img,block_size=256,ro,root,sparse=false,id=DISK_LABEL\
680*bb4ee6a4SAndroid Build Coastguard Worker             ,direct,async-executor={ex_kind_opt},packed-queue=false,pci-address=00:01.1"
681*bb4ee6a4SAndroid Build Coastguard Worker         ))
682*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
683*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
684*bb4ee6a4SAndroid Build Coastguard Worker             params,
685*bb4ee6a4SAndroid Build Coastguard Worker             DiskOption {
686*bb4ee6a4SAndroid Build Coastguard Worker                 path: "/some/path.img".into(),
687*bb4ee6a4SAndroid Build Coastguard Worker                 read_only: true,
688*bb4ee6a4SAndroid Build Coastguard Worker                 root: true,
689*bb4ee6a4SAndroid Build Coastguard Worker                 sparse: false,
690*bb4ee6a4SAndroid Build Coastguard Worker                 direct: true,
691*bb4ee6a4SAndroid Build Coastguard Worker                 lock: true,
692*bb4ee6a4SAndroid Build Coastguard Worker                 block_size: 256,
693*bb4ee6a4SAndroid Build Coastguard Worker                 id: Some(*b"DISK_LABEL\0\0\0\0\0\0\0\0\0\0"),
694*bb4ee6a4SAndroid Build Coastguard Worker                 #[cfg(windows)]
695*bb4ee6a4SAndroid Build Coastguard Worker                 io_concurrency: NonZeroU32::new(1).unwrap(),
696*bb4ee6a4SAndroid Build Coastguard Worker                 multiple_workers: false,
697*bb4ee6a4SAndroid Build Coastguard Worker                 async_executor: Some(ex_kind),
698*bb4ee6a4SAndroid Build Coastguard Worker                 packed_queue: false,
699*bb4ee6a4SAndroid Build Coastguard Worker                 bootindex: None,
700*bb4ee6a4SAndroid Build Coastguard Worker                 pci_address: Some(PciAddress {
701*bb4ee6a4SAndroid Build Coastguard Worker                     bus: 0,
702*bb4ee6a4SAndroid Build Coastguard Worker                     dev: 1,
703*bb4ee6a4SAndroid Build Coastguard Worker                     func: 1,
704*bb4ee6a4SAndroid Build Coastguard Worker                 }),
705*bb4ee6a4SAndroid Build Coastguard Worker             }
706*bb4ee6a4SAndroid Build Coastguard Worker         );
707*bb4ee6a4SAndroid Build Coastguard Worker     }
708*bb4ee6a4SAndroid Build Coastguard Worker 
709*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
diskoption_serialize_deserialize()710*bb4ee6a4SAndroid Build Coastguard Worker     fn diskoption_serialize_deserialize() {
711*bb4ee6a4SAndroid Build Coastguard Worker         // With id == None
712*bb4ee6a4SAndroid Build Coastguard Worker         let original = DiskOption {
713*bb4ee6a4SAndroid Build Coastguard Worker             path: "./rootfs".into(),
714*bb4ee6a4SAndroid Build Coastguard Worker             read_only: false,
715*bb4ee6a4SAndroid Build Coastguard Worker             root: false,
716*bb4ee6a4SAndroid Build Coastguard Worker             sparse: true,
717*bb4ee6a4SAndroid Build Coastguard Worker             direct: false,
718*bb4ee6a4SAndroid Build Coastguard Worker             lock: true,
719*bb4ee6a4SAndroid Build Coastguard Worker             block_size: 512,
720*bb4ee6a4SAndroid Build Coastguard Worker             id: None,
721*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(windows)]
722*bb4ee6a4SAndroid Build Coastguard Worker             io_concurrency: NonZeroU32::new(1).unwrap(),
723*bb4ee6a4SAndroid Build Coastguard Worker             multiple_workers: false,
724*bb4ee6a4SAndroid Build Coastguard Worker             async_executor: None,
725*bb4ee6a4SAndroid Build Coastguard Worker             packed_queue: false,
726*bb4ee6a4SAndroid Build Coastguard Worker             bootindex: None,
727*bb4ee6a4SAndroid Build Coastguard Worker             pci_address: None,
728*bb4ee6a4SAndroid Build Coastguard Worker         };
729*bb4ee6a4SAndroid Build Coastguard Worker         let json = serde_json::to_string(&original).unwrap();
730*bb4ee6a4SAndroid Build Coastguard Worker         let deserialized = serde_json::from_str(&json).unwrap();
731*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(original, deserialized);
732*bb4ee6a4SAndroid Build Coastguard Worker 
733*bb4ee6a4SAndroid Build Coastguard Worker         // With id == Some
734*bb4ee6a4SAndroid Build Coastguard Worker         let original = DiskOption {
735*bb4ee6a4SAndroid Build Coastguard Worker             path: "./rootfs".into(),
736*bb4ee6a4SAndroid Build Coastguard Worker             read_only: false,
737*bb4ee6a4SAndroid Build Coastguard Worker             root: false,
738*bb4ee6a4SAndroid Build Coastguard Worker             sparse: true,
739*bb4ee6a4SAndroid Build Coastguard Worker             direct: false,
740*bb4ee6a4SAndroid Build Coastguard Worker             lock: true,
741*bb4ee6a4SAndroid Build Coastguard Worker             block_size: 512,
742*bb4ee6a4SAndroid Build Coastguard Worker             id: Some(*b"BLK\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"),
743*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(windows)]
744*bb4ee6a4SAndroid Build Coastguard Worker             io_concurrency: NonZeroU32::new(1).unwrap(),
745*bb4ee6a4SAndroid Build Coastguard Worker             multiple_workers: false,
746*bb4ee6a4SAndroid Build Coastguard Worker             async_executor: Some(ExecutorKind::default()),
747*bb4ee6a4SAndroid Build Coastguard Worker             packed_queue: false,
748*bb4ee6a4SAndroid Build Coastguard Worker             bootindex: None,
749*bb4ee6a4SAndroid Build Coastguard Worker             pci_address: None,
750*bb4ee6a4SAndroid Build Coastguard Worker         };
751*bb4ee6a4SAndroid Build Coastguard Worker         let json = serde_json::to_string(&original).unwrap();
752*bb4ee6a4SAndroid Build Coastguard Worker         let deserialized = serde_json::from_str(&json).unwrap();
753*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(original, deserialized);
754*bb4ee6a4SAndroid Build Coastguard Worker 
755*bb4ee6a4SAndroid Build Coastguard Worker         // With id taking all the available space.
756*bb4ee6a4SAndroid Build Coastguard Worker         let original = DiskOption {
757*bb4ee6a4SAndroid Build Coastguard Worker             path: "./rootfs".into(),
758*bb4ee6a4SAndroid Build Coastguard Worker             read_only: false,
759*bb4ee6a4SAndroid Build Coastguard Worker             root: false,
760*bb4ee6a4SAndroid Build Coastguard Worker             sparse: true,
761*bb4ee6a4SAndroid Build Coastguard Worker             direct: false,
762*bb4ee6a4SAndroid Build Coastguard Worker             lock: true,
763*bb4ee6a4SAndroid Build Coastguard Worker             block_size: 512,
764*bb4ee6a4SAndroid Build Coastguard Worker             id: Some(*b"QWERTYUIOPASDFGHJKL:"),
765*bb4ee6a4SAndroid Build Coastguard Worker             #[cfg(windows)]
766*bb4ee6a4SAndroid Build Coastguard Worker             io_concurrency: NonZeroU32::new(1).unwrap(),
767*bb4ee6a4SAndroid Build Coastguard Worker             multiple_workers: false,
768*bb4ee6a4SAndroid Build Coastguard Worker             async_executor: Some(ExecutorKind::default()),
769*bb4ee6a4SAndroid Build Coastguard Worker             packed_queue: false,
770*bb4ee6a4SAndroid Build Coastguard Worker             bootindex: None,
771*bb4ee6a4SAndroid Build Coastguard Worker             pci_address: None,
772*bb4ee6a4SAndroid Build Coastguard Worker         };
773*bb4ee6a4SAndroid Build Coastguard Worker         let json = serde_json::to_string(&original).unwrap();
774*bb4ee6a4SAndroid Build Coastguard Worker         let deserialized = serde_json::from_str(&json).unwrap();
775*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(original, deserialized);
776*bb4ee6a4SAndroid Build Coastguard Worker     }
777*bb4ee6a4SAndroid Build Coastguard Worker }
778