virtio-devices, vmm: replace Vec<T> with Box<[T]> in config structs

I started by looking at all `Option<Vec<T>>` values in config.rs and
vm_config.rs, and replaced them with `Option<Box<[T]>>`. This has the
advantage that one now can see at a glance if this field will ever
resize during operation or not, reducing cognitive load and increasing
maintainability. All fields that need the properties of a Ver or where
this change was not trivial are kept intact.

On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
This commit is contained in:
Philipp Schuster
2026-05-15 10:26:59 +02:00
committed by Rob Bradford
parent 29e2319247
commit ba04c4f318
3 changed files with 93 additions and 87 deletions
+8 -6
View File
@@ -155,7 +155,7 @@ struct BlockEpollHandler {
disk_image: Box<dyn AsyncIo>, disk_image: Box<dyn AsyncIo>,
disk_nsectors: Arc<AtomicU64>, disk_nsectors: Arc<AtomicU64>,
interrupt_cb: Arc<dyn VirtioInterrupt>, interrupt_cb: Arc<dyn VirtioInterrupt>,
serial: Vec<u8>, serial: Box<[u8]>,
kill_evt: EventFd, kill_evt: EventFd,
pause_evt: EventFd, pause_evt: EventFd,
writeback: Arc<AtomicBool>, writeback: Arc<AtomicBool>,
@@ -164,7 +164,7 @@ struct BlockEpollHandler {
inflight_requests: VecDeque<(u16, Request)>, inflight_requests: VecDeque<(u16, Request)>,
rate_limiter: Option<RateLimiterGroupHandle>, rate_limiter: Option<RateLimiterGroupHandle>,
access_platform: Option<Arc<dyn AccessPlatform>>, access_platform: Option<Arc<dyn AccessPlatform>>,
host_cpus: Option<Vec<usize>>, host_cpus: Option<Box<[usize]>>,
acked_features: u64, acked_features: u64,
disable_sector0_writes: bool, disable_sector0_writes: bool,
} }
@@ -723,8 +723,8 @@ pub struct Block {
seccomp_action: SeccompAction, seccomp_action: SeccompAction,
rate_limiter: Option<Arc<RateLimiterGroup>>, rate_limiter: Option<Arc<RateLimiterGroup>>,
exit_evt: EventFd, exit_evt: EventFd,
serial: Vec<u8>, serial: Box<[u8]>,
queue_affinity: BTreeMap<u16, Vec<usize>>, queue_affinity: BTreeMap<u16, Box<[usize]>>,
disable_sector0_writes: bool, disable_sector0_writes: bool,
lock_granularity_choice: LockGranularityChoice, lock_granularity_choice: LockGranularityChoice,
device_status: Arc<AtomicU8>, device_status: Arc<AtomicU8>,
@@ -755,7 +755,7 @@ impl Block {
rate_limiter: Option<Arc<RateLimiterGroup>>, rate_limiter: Option<Arc<RateLimiterGroup>>,
exit_evt: EventFd, exit_evt: EventFd,
state: Option<BlockState>, state: Option<BlockState>,
queue_affinity: BTreeMap<u16, Vec<usize>>, queue_affinity: BTreeMap<u16, Box<[usize]>>,
sparse: bool, sparse: bool,
disable_sector0_writes: bool, disable_sector0_writes: bool,
lock_granularity: LockGranularityChoice, lock_granularity: LockGranularityChoice,
@@ -862,7 +862,9 @@ impl Block {
(disk_nsectors, avail_features, 0, config, false) (disk_nsectors, avail_features, 0, config, false)
}; };
let serial = serial.map_or_else(|| build_serial(&disk_path), Vec::from); let serial = serial
.map_or_else(|| build_serial(&disk_path), Vec::from)
.into_boxed_slice();
Ok(Block { Ok(Block {
common: VirtioCommon { common: VirtioCommon {
+73 -69
View File
@@ -889,7 +889,7 @@ impl PlatformConfig {
let oem_strings = parser let oem_strings = parser
.convert::<StringList>("oem_strings") .convert::<StringList>("oem_strings")
.map_err(Error::ParsePlatform)? .map_err(Error::ParsePlatform)?
.map(|v| v.0); .map(|v| v.0.into_boxed_slice());
let iommufd = parser let iommufd = parser
.convert::<Toggle>("iommufd") .convert::<Toggle>("iommufd")
.map_err(Error::ParsePlatform)? .map_err(Error::ParsePlatform)?
@@ -1390,7 +1390,7 @@ impl DiskConfig {
v.0.iter() v.0.iter()
.map(|(e1, e2)| VirtQueueAffinity { .map(|(e1, e2)| VirtQueueAffinity {
queue_index: *e1, queue_index: *e1,
host_cpus: e2.clone(), host_cpus: e2.clone().into_boxed_slice(),
}) })
.collect() .collect()
}); });
@@ -2469,7 +2469,7 @@ impl NumaConfig {
let memory_zones = parser let memory_zones = parser
.convert::<StringList>("memory_zones") .convert::<StringList>("memory_zones")
.map_err(Error::ParseNuma)? .map_err(Error::ParseNuma)?
.map(|v| v.0); .map(|v| v.0.into_boxed_slice());
let pci_segments = parser let pci_segments = parser
.convert::<IntegerList>("pci_segments") .convert::<IntegerList>("pci_segments")
.map_err(Error::ParseNuma)? .map_err(Error::ParseNuma)?
@@ -3250,14 +3250,14 @@ impl VmConfig {
} }
pub fn parse(vm_params: VmParams) -> Result<Self> { pub fn parse(vm_params: VmParams) -> Result<Self> {
let mut rate_limit_groups: Option<Vec<RateLimiterGroupConfig>> = None; let mut rate_limit_groups: Option<Box<[RateLimiterGroupConfig]>> = None;
if let Some(rate_limit_group_list) = &vm_params.rate_limit_groups { if let Some(rate_limit_group_list) = &vm_params.rate_limit_groups {
let mut rate_limit_group_config_list = Vec::new(); let mut rate_limit_group_config_list = Vec::new();
for item in rate_limit_group_list.iter() { for item in rate_limit_group_list.iter() {
let rate_limit_group_config = RateLimiterGroupConfig::parse(item)?; let rate_limit_group_config = RateLimiterGroupConfig::parse(item)?;
rate_limit_group_config_list.push(rate_limit_group_config); rate_limit_group_config_list.push(rate_limit_group_config);
} }
rate_limit_groups = Some(rate_limit_group_config_list); rate_limit_groups = Some(rate_limit_group_config_list.into_boxed_slice());
} }
let mut disks: Option<Vec<DiskConfig>> = None; let mut disks: Option<Vec<DiskConfig>> = None;
@@ -3369,26 +3369,26 @@ impl VmConfig {
vsock = Some(vsock_config); vsock = Some(vsock_config);
} }
let mut pci_segments: Option<Vec<PciSegmentConfig>> = None; let mut pci_segments: Option<Box<[PciSegmentConfig]>> = None;
if let Some(pci_segment_list) = &vm_params.pci_segments { if let Some(pci_segment_list) = &vm_params.pci_segments {
let mut pci_segment_config_list = Vec::new(); let mut pci_segment_config_list = Vec::new();
for item in pci_segment_list.iter() { for item in pci_segment_list.iter() {
let pci_segment_config = PciSegmentConfig::parse(item)?; let pci_segment_config = PciSegmentConfig::parse(item)?;
pci_segment_config_list.push(pci_segment_config); pci_segment_config_list.push(pci_segment_config);
} }
pci_segments = Some(pci_segment_config_list); pci_segments = Some(pci_segment_config_list.into_boxed_slice());
} }
let platform = vm_params.platform.map(PlatformConfig::parse).transpose()?; let platform = vm_params.platform.map(PlatformConfig::parse).transpose()?;
let mut numa: Option<Vec<NumaConfig>> = None; let mut numa: Option<Box<[NumaConfig]>> = None;
if let Some(numa_list) = &vm_params.numa { if let Some(numa_list) = &vm_params.numa {
let mut numa_config_list = Vec::new(); let mut numa_config_list = Vec::new();
for item in numa_list.iter() { for item in numa_list.iter() {
let numa_config = NumaConfig::parse(item)?; let numa_config = NumaConfig::parse(item)?;
numa_config_list.push(numa_config); numa_config_list.push(numa_config);
} }
numa = Some(numa_config_list); numa = Some(numa_config_list.into_boxed_slice());
} }
#[cfg(not(feature = "igvm"))] #[cfg(not(feature = "igvm"))]
@@ -3426,13 +3426,14 @@ impl VmConfig {
#[cfg(feature = "guest_debug")] #[cfg(feature = "guest_debug")]
let gdb = vm_params.gdb; let gdb = vm_params.gdb;
let mut landlock_rules: Option<Vec<LandlockConfig>> = None; let mut landlock_rules: Option<Box<[LandlockConfig]>> = None;
if let Some(ll_rules) = vm_params.landlock_rules { if let Some(ll_rules) = vm_params.landlock_rules {
landlock_rules = Some( landlock_rules = Some(
ll_rules ll_rules
.iter() .iter()
.map(|rule| LandlockConfig::parse(rule)) .map(|rule| LandlockConfig::parse(rule))
.collect::<Result<Vec<LandlockConfig>>>()?, .collect::<Result<Vec<LandlockConfig>>>()?
.into_boxed_slice(),
); );
} }
@@ -4085,24 +4086,24 @@ mod unit_tests {
assert_eq!( assert_eq!(
DiskConfig::parse("path=/path/to_file,queue_affinity=[0@[1],1@[2],2@[3,4],3@[5-8]]")?, DiskConfig::parse("path=/path/to_file,queue_affinity=[0@[1],1@[2],2@[3,4],3@[5-8]]")?,
DiskConfig { DiskConfig {
queue_affinity: Some(vec![ queue_affinity: Some(Box::new([
VirtQueueAffinity { VirtQueueAffinity {
queue_index: 0, queue_index: 0,
host_cpus: vec![1], host_cpus: Box::new([1]),
}, },
VirtQueueAffinity { VirtQueueAffinity {
queue_index: 1, queue_index: 1,
host_cpus: vec![2], host_cpus: Box::new([2]),
}, },
VirtQueueAffinity { VirtQueueAffinity {
queue_index: 2, queue_index: 2,
host_cpus: vec![3, 4], host_cpus: Box::new([3, 4]),
}, },
VirtQueueAffinity { VirtQueueAffinity {
queue_index: 3, queue_index: 3,
host_cpus: vec![5, 6, 7, 8], host_cpus: Box::new([5, 6, 7, 8]),
} }
]), ])),
..disk_fixture() ..disk_fixture()
} }
); );
@@ -4615,14 +4616,14 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
memory_zones=[mem0],pci_segments=[0]"; memory_zones=[mem0],pci_segments=[0]";
let expected_standard = NumaConfig { let expected_standard = NumaConfig {
guest_numa_id: 1, guest_numa_id: 1,
cpus: Some(vec![2, 3]), cpus: Some(Box::new([2, 3])),
distances: Some(vec![NumaDistance { distances: Some(Box::new([NumaDistance {
destination: 0, destination: 0,
distance: 20, distance: 20,
}]), }])),
device_id: None, device_id: None,
memory_zones: Some(vec!["mem0".to_string()]), memory_zones: Some(Box::new(["mem0".to_string()])),
pci_segments: Some(vec![0]), pci_segments: Some(Box::new([0])),
}; };
assert_eq!(NumaConfig::parse(standard_input)?, expected_standard); assert_eq!(NumaConfig::parse(standard_input)?, expected_standard);
// Successful generic initiator config parse // Successful generic initiator config parse
@@ -4630,13 +4631,13 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let expected_gi = NumaConfig { let expected_gi = NumaConfig {
guest_numa_id: 2, guest_numa_id: 2,
cpus: None, cpus: None,
distances: Some(vec![NumaDistance { distances: Some(Box::new([NumaDistance {
destination: 0, destination: 0,
distance: 30, distance: 30,
}]), }])),
device_id: Some("vfio1".to_string()), device_id: Some("vfio1".to_string()),
memory_zones: None, memory_zones: None,
pci_segments: Some(vec![1]), pci_segments: Some(Box::new([1])),
}; };
assert_eq!(NumaConfig::parse(gi_input)?, expected_gi); assert_eq!(NumaConfig::parse(gi_input)?, expected_gi);
Ok(()) Ok(())
@@ -4648,10 +4649,10 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let config = NumaConfig { let config = NumaConfig {
guest_numa_id: 0, guest_numa_id: 0,
cpus: None, cpus: None,
distances: Some(vec![NumaDistance { distances: Some(Box::new([NumaDistance {
destination: 1, destination: 1,
distance: 20, distance: 20,
}]), }])),
memory_zones: None, memory_zones: None,
device_id: Some("vfio0".to_string()), device_id: Some("vfio0".to_string()),
pci_segments: None, pci_segments: None,
@@ -4679,7 +4680,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
// device_id and cpus specified // device_id and cpus specified
let config = NumaConfig { let config = NumaConfig {
guest_numa_id: 0, guest_numa_id: 0,
cpus: Some(vec![0, 1]), cpus: Some(Box::new([0, 1])),
distances: None, distances: None,
device_id: Some("vfio0".to_string()), device_id: Some("vfio0".to_string()),
memory_zones: None, memory_zones: None,
@@ -4696,7 +4697,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
cpus: None, cpus: None,
distances: None, distances: None,
device_id: Some("vfio0".to_string()), device_id: Some("vfio0".to_string()),
memory_zones: Some(vec!["mem0".to_string()]), memory_zones: Some(Box::new(["mem0".to_string()])),
pci_segments: None, pci_segments: None,
}; };
assert!(config.validate().is_err()); assert!(config.validate().is_err());
@@ -4707,13 +4708,13 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
// No device_id // No device_id
let config = NumaConfig { let config = NumaConfig {
guest_numa_id: 0, guest_numa_id: 0,
cpus: Some(vec![0, 1]), cpus: Some(Box::new([0, 1])),
distances: Some(vec![NumaDistance { distances: Some(Box::new([NumaDistance {
destination: 1, destination: 1,
distance: 20, distance: 20,
}]), }])),
device_id: None, device_id: None,
memory_zones: Some(vec!["mem0".to_string()]), memory_zones: Some(Box::new(["mem0".to_string()])),
pci_segments: None, pci_segments: None,
}; };
config.validate().unwrap(); config.validate().unwrap();
@@ -5424,14 +5425,17 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut still_valid_config = valid_config.clone(); let mut still_valid_config = valid_config.clone();
still_valid_config.platform = Some(PlatformConfig { still_valid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
still_valid_config.validate().unwrap(); still_valid_config.validate().unwrap();
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.platform = Some(PlatformConfig { invalid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![MAX_NUM_PCI_SEGMENTS + 1, MAX_NUM_PCI_SEGMENTS + 2]), iommu_segments: Some(Box::new([
MAX_NUM_PCI_SEGMENTS + 1,
MAX_NUM_PCI_SEGMENTS + 2,
])),
..platform_fixture() ..platform_fixture()
}); });
assert_eq!( assert_eq!(
@@ -5453,7 +5457,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut still_valid_config = valid_config.clone(); let mut still_valid_config = valid_config.clone();
still_valid_config.platform = Some(PlatformConfig { still_valid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
still_valid_config.disks = Some(vec![DiskConfig { still_valid_config.disks = Some(vec![DiskConfig {
@@ -5468,7 +5472,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut still_valid_config = valid_config.clone(); let mut still_valid_config = valid_config.clone();
still_valid_config.platform = Some(PlatformConfig { still_valid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
still_valid_config.net = Some(vec![NetConfig { still_valid_config.net = Some(vec![NetConfig {
@@ -5483,7 +5487,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut still_valid_config = valid_config.clone(); let mut still_valid_config = valid_config.clone();
still_valid_config.platform = Some(PlatformConfig { still_valid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
still_valid_config.pmem = Some(vec![PmemConfig { still_valid_config.pmem = Some(vec![PmemConfig {
@@ -5498,7 +5502,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut still_valid_config = valid_config.clone(); let mut still_valid_config = valid_config.clone();
still_valid_config.platform = Some(PlatformConfig { still_valid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
still_valid_config.devices = Some(vec![DeviceConfig { still_valid_config.devices = Some(vec![DeviceConfig {
@@ -5513,7 +5517,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut still_valid_config = valid_config.clone(); let mut still_valid_config = valid_config.clone();
still_valid_config.platform = Some(PlatformConfig { still_valid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
still_valid_config.vsock = Some(VsockConfig { still_valid_config.vsock = Some(VsockConfig {
@@ -5529,7 +5533,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.platform = Some(PlatformConfig { invalid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
invalid_config.disks = Some(vec![DiskConfig { invalid_config.disks = Some(vec![DiskConfig {
@@ -5547,7 +5551,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.platform = Some(PlatformConfig { invalid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
invalid_config.net = Some(vec![NetConfig { invalid_config.net = Some(vec![NetConfig {
@@ -5566,7 +5570,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.platform = Some(PlatformConfig { invalid_config.platform = Some(PlatformConfig {
num_pci_segments: MAX_NUM_PCI_SEGMENTS, num_pci_segments: MAX_NUM_PCI_SEGMENTS,
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
invalid_config.pmem = Some(vec![PmemConfig { invalid_config.pmem = Some(vec![PmemConfig {
@@ -5584,7 +5588,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.platform = Some(PlatformConfig { invalid_config.platform = Some(PlatformConfig {
num_pci_segments: MAX_NUM_PCI_SEGMENTS, num_pci_segments: MAX_NUM_PCI_SEGMENTS,
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
invalid_config.devices = Some(vec![DeviceConfig { invalid_config.devices = Some(vec![DeviceConfig {
@@ -5601,7 +5605,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.platform = Some(PlatformConfig { invalid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
invalid_config.vsock = Some(VsockConfig { invalid_config.vsock = Some(VsockConfig {
@@ -5620,7 +5624,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.memory.shared = true; invalid_config.memory.shared = true;
invalid_config.platform = Some(PlatformConfig { invalid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
invalid_config.user_devices = Some(vec![UserDeviceConfig { invalid_config.user_devices = Some(vec![UserDeviceConfig {
@@ -5637,7 +5641,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.platform = Some(PlatformConfig { invalid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
invalid_config.vdpa = Some(vec![VdpaConfig { invalid_config.vdpa = Some(vec![VdpaConfig {
@@ -5655,7 +5659,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.memory.shared = true; invalid_config.memory.shared = true;
invalid_config.platform = Some(PlatformConfig { invalid_config.platform = Some(PlatformConfig {
iommu_segments: Some(vec![1, 2, 3]), iommu_segments: Some(Box::new([1, 2, 3])),
..platform_fixture() ..platform_fixture()
}); });
invalid_config.fs = Some(vec![FsConfig { invalid_config.fs = Some(vec![FsConfig {
@@ -5675,81 +5679,81 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
num_pci_segments: 2, num_pci_segments: 2,
..platform_fixture() ..platform_fixture()
}); });
invalid_config.numa = Some(vec![ invalid_config.numa = Some(Box::new([
NumaConfig { NumaConfig {
guest_numa_id: 0, guest_numa_id: 0,
cpus: Some(vec![0]), cpus: Some(Box::new([0])),
pci_segments: Some(vec![1]), pci_segments: Some(Box::new([1])),
..numa_fixture() ..numa_fixture()
}, },
NumaConfig { NumaConfig {
guest_numa_id: 1, guest_numa_id: 1,
cpus: Some(vec![1]), cpus: Some(Box::new([1])),
pci_segments: Some(vec![1]), pci_segments: Some(Box::new([1])),
..numa_fixture() ..numa_fixture()
}, },
]); ]));
assert_eq!( assert_eq!(
invalid_config.validate(), invalid_config.validate(),
Err(ValidationError::PciSegmentReused(1, 0, 1)) Err(ValidationError::PciSegmentReused(1, 0, 1))
); );
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.pci_segments = Some(vec![PciSegmentConfig { invalid_config.pci_segments = Some(Box::new([PciSegmentConfig {
pci_segment: 0, pci_segment: 0,
mmio32_aperture_weight: 1, mmio32_aperture_weight: 1,
mmio64_aperture_weight: 0, mmio64_aperture_weight: 0,
}]); }]));
assert_eq!( assert_eq!(
invalid_config.validate(), invalid_config.validate(),
Err(ValidationError::InvalidPciSegmentApertureWeight(0)) Err(ValidationError::InvalidPciSegmentApertureWeight(0))
); );
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.pci_segments = Some(vec![PciSegmentConfig { invalid_config.pci_segments = Some(Box::new([PciSegmentConfig {
pci_segment: 0, pci_segment: 0,
mmio32_aperture_weight: 0, mmio32_aperture_weight: 0,
mmio64_aperture_weight: 1, mmio64_aperture_weight: 1,
}]); }]));
assert_eq!( assert_eq!(
invalid_config.validate(), invalid_config.validate(),
Err(ValidationError::InvalidPciSegmentApertureWeight(0)) Err(ValidationError::InvalidPciSegmentApertureWeight(0))
); );
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.numa = Some(vec![ invalid_config.numa = Some(Box::new([
NumaConfig { NumaConfig {
guest_numa_id: 0, guest_numa_id: 0,
cpus: Some(vec![0]), cpus: Some(Box::new([0])),
..numa_fixture() ..numa_fixture()
}, },
NumaConfig { NumaConfig {
guest_numa_id: 1, guest_numa_id: 1,
cpus: Some(vec![1]), cpus: Some(Box::new([1])),
pci_segments: Some(vec![0]), pci_segments: Some(Box::new([0])),
..numa_fixture() ..numa_fixture()
}, },
]); ]));
assert_eq!( assert_eq!(
invalid_config.validate(), invalid_config.validate(),
Err(ValidationError::DefaultPciSegmentInvalidNode(1)) Err(ValidationError::DefaultPciSegmentInvalidNode(1))
); );
let mut invalid_config = valid_config.clone(); let mut invalid_config = valid_config.clone();
invalid_config.numa = Some(vec![ invalid_config.numa = Some(Box::new([
NumaConfig { NumaConfig {
guest_numa_id: 0, guest_numa_id: 0,
cpus: Some(vec![0]), cpus: Some(Box::new([0])),
pci_segments: Some(vec![0]), pci_segments: Some(Box::new([0])),
..numa_fixture() ..numa_fixture()
}, },
NumaConfig { NumaConfig {
guest_numa_id: 1, guest_numa_id: 1,
cpus: Some(vec![1]), cpus: Some(Box::new([1])),
pci_segments: Some(vec![1]), pci_segments: Some(Box::new([1])),
..numa_fixture() ..numa_fixture()
}, },
]); ]));
assert_eq!( assert_eq!(
invalid_config.validate(), invalid_config.validate(),
Err(ValidationError::InvalidPciSegment(1)) Err(ValidationError::InvalidPciSegment(1))
+12 -12
View File
@@ -122,7 +122,7 @@ pub struct PlatformConfig {
#[serde(default = "default_platformconfig_num_pci_segments")] #[serde(default = "default_platformconfig_num_pci_segments")]
pub num_pci_segments: u16, pub num_pci_segments: u16,
#[serde(default)] #[serde(default)]
pub iommu_segments: Option<Vec<u16>>, pub iommu_segments: Option<Box<[u16]>>,
#[serde(default = "default_platformconfig_iommu_address_width_bits")] #[serde(default = "default_platformconfig_iommu_address_width_bits")]
pub iommu_address_width_bits: u8, pub iommu_address_width_bits: u8,
#[serde(default)] #[serde(default)]
@@ -130,7 +130,7 @@ pub struct PlatformConfig {
#[serde(default)] #[serde(default)]
pub uuid: Option<String>, pub uuid: Option<String>,
#[serde(default)] #[serde(default)]
pub oem_strings: Option<Vec<String>>, pub oem_strings: Option<Box<[String]>>,
#[cfg(feature = "tdx")] #[cfg(feature = "tdx")]
#[serde(default)] #[serde(default)]
pub tdx: bool, pub tdx: bool,
@@ -270,7 +270,7 @@ pub struct RateLimiterGroupConfig {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct VirtQueueAffinity { pub struct VirtQueueAffinity {
pub queue_index: u16, pub queue_index: u16,
pub host_cpus: Vec<usize>, pub host_cpus: Box<[usize]>,
} }
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)]
@@ -314,7 +314,7 @@ pub struct DiskConfig {
#[serde(default)] #[serde(default)]
pub serial: Option<String>, pub serial: Option<String>,
#[serde(default)] #[serde(default)]
pub queue_affinity: Option<Vec<VirtQueueAffinity>>, pub queue_affinity: Option<Box<[VirtQueueAffinity]>>,
#[serde(default)] #[serde(default)]
pub backing_files: bool, pub backing_files: bool,
#[serde(default = "default_diskconfig_sparse")] #[serde(default = "default_diskconfig_sparse")]
@@ -782,13 +782,13 @@ pub struct NumaDistance {
pub struct NumaConfig { pub struct NumaConfig {
pub guest_numa_id: u32, pub guest_numa_id: u32,
#[serde(default)] #[serde(default)]
pub cpus: Option<Vec<u32>>, pub cpus: Option<Box<[u32]>>,
#[serde(default)] #[serde(default)]
pub distances: Option<Vec<NumaDistance>>, pub distances: Option<Box<[NumaDistance]>>,
#[serde(default)] #[serde(default)]
pub memory_zones: Option<Vec<String>>, pub memory_zones: Option<Box<[String]>>,
#[serde(default)] #[serde(default)]
pub pci_segments: Option<Vec<u16>>, pub pci_segments: Option<Box<[u16]>>,
#[serde(default)] #[serde(default)]
pub device_id: Option<String>, pub device_id: Option<String>,
} }
@@ -1020,7 +1020,7 @@ pub struct VmConfig {
#[serde(default)] #[serde(default)]
pub memory: MemoryConfig, pub memory: MemoryConfig,
pub payload: Option<PayloadConfig>, pub payload: Option<PayloadConfig>,
pub rate_limit_groups: Option<Vec<RateLimiterGroupConfig>>, pub rate_limit_groups: Option<Box<[RateLimiterGroupConfig]>>,
pub disks: Option<Vec<DiskConfig>>, pub disks: Option<Vec<DiskConfig>>,
pub net: Option<Vec<NetConfig>>, pub net: Option<Vec<NetConfig>>,
#[serde(default)] #[serde(default)]
@@ -1047,13 +1047,13 @@ pub struct VmConfig {
pub pvpanic: bool, pub pvpanic: bool,
#[serde(default)] #[serde(default)]
pub iommu: bool, pub iommu: bool,
pub numa: Option<Vec<NumaConfig>>, pub numa: Option<Box<[NumaConfig]>>,
#[serde(default)] #[serde(default)]
pub watchdog: bool, pub watchdog: bool,
#[cfg(feature = "guest_debug")] #[cfg(feature = "guest_debug")]
#[serde(default)] #[serde(default)]
pub gdb: bool, pub gdb: bool,
pub pci_segments: Option<Vec<PciSegmentConfig>>, pub pci_segments: Option<Box<[PciSegmentConfig]>>,
pub platform: Option<PlatformConfig>, pub platform: Option<PlatformConfig>,
pub tpm: Option<TpmConfig>, pub tpm: Option<TpmConfig>,
// Preserved FDs are the ones that share the same life-time as its holding // Preserved FDs are the ones that share the same life-time as its holding
@@ -1068,7 +1068,7 @@ pub struct VmConfig {
pub preserved_fds: Option<Vec<i32>>, pub preserved_fds: Option<Vec<i32>>,
#[serde(default)] #[serde(default)]
pub landlock_enable: bool, pub landlock_enable: bool,
pub landlock_rules: Option<Vec<LandlockConfig>>, pub landlock_rules: Option<Box<[LandlockConfig]>>,
#[cfg(feature = "ivshmem")] #[cfg(feature = "ivshmem")]
pub ivshmem: Option<IvshmemConfig>, pub ivshmem: Option<IvshmemConfig>,
} }