From 53f209af447f5396e5d757793bee2cef82da36bf Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Tue, 6 Sep 2022 10:29:32 +0800 Subject: [PATCH] libs/kata-types: adjust default_vcpus correctly With default_maxvcpus = 0 and default_vcpus = 1 settings, the default_vcpus will be set to 0 and leads to starting fail. The default_maxvcpus is not set correctly when it is set to 0, and the default_vcpus is set to 0. The correct action is setting default_maxvcpus to the max number of CPUs or MAX_DRAGONBALL_VCPUS, and the default_vcpus should be set to the desired value if the valuse is between 0 and default_maxvcpus. Fixes: #5110 Signed-off-by: Bin Liu --- .../kata-types/src/config/hypervisor/mod.rs | 124 ++++++++++++++---- 1 file changed, 102 insertions(+), 22 deletions(-) diff --git a/src/libs/kata-types/src/config/hypervisor/mod.rs b/src/libs/kata-types/src/config/hypervisor/mod.rs index d749b73dfe..ae7acb1354 100644 --- a/src/libs/kata-types/src/config/hypervisor/mod.rs +++ b/src/libs/kata-types/src/config/hypervisor/mod.rs @@ -301,35 +301,39 @@ impl CpuInfo { pub fn adjust_config(&mut self) -> Result<()> { let features: Vec<&str> = self.cpu_features.split(',').map(|v| v.trim()).collect(); self.cpu_features = features.join(","); + + let cpus = num_cpus::get() as u32; + + // adjust default_maxvcpus + if self.default_maxvcpus == 0 || self.default_maxvcpus > cpus { + self.default_maxvcpus = cpus; + } + + // adjust default_vcpus + if self.default_vcpus < 0 || self.default_vcpus as u32 > cpus { + self.default_vcpus = cpus as i32; + } else if self.default_vcpus == 0 { + self.default_vcpus = default::DEFAULT_GUEST_VCPUS as i32; + } + + if self.default_vcpus > self.default_maxvcpus as i32 { + self.default_vcpus = self.default_maxvcpus as i32; + } + Ok(()) } /// Validate the configuration information. pub fn validate(&self) -> Result<()> { + if self.default_vcpus > self.default_maxvcpus as i32 { + return Err(eother!( + "The default_vcpus({}) is greater than default_maxvcpus({})", + self.default_vcpus, + self.default_maxvcpus + )); + } Ok(()) } - - /// Get default number of guest vCPUs. - pub fn get_default_vcpus(&self) -> u32 { - let cpus = num_cpus::get() as u32; - if self.default_vcpus < 0 || self.default_vcpus as u32 > cpus { - cpus - } else if self.default_vcpus == 0 { - default::DEFAULT_GUEST_VCPUS - } else { - self.default_vcpus as u32 - } - } - - /// Get default maximal number of guest vCPUs. - pub fn get_default_max_vcpus(&self) -> u32 { - let cpus = num_cpus::get() as u32; - if self.default_maxvcpus == 0 || self.default_maxvcpus > cpus { - cpus - } else { - self.default_maxvcpus - } - } } /// Configuration information for debug @@ -1106,4 +1110,80 @@ mod tests { String::from("boo=far a b=c foo bar baz=faz") ); } + + #[test] + fn test_cpu_info_adjust_config() { + // get CPU cores of the test node + let node_cpus = num_cpus::get() as u32; + let default_vcpus = default::DEFAULT_GUEST_VCPUS as i32; + + struct TestData<'a> { + desc: &'a str, + input: &'a mut CpuInfo, + output: CpuInfo, + } + + let tests = &mut [ + TestData { + desc: "all with default values", + input: &mut CpuInfo { + cpu_features: "".to_string(), + default_vcpus: 0, + default_maxvcpus: 0, + }, + output: CpuInfo { + cpu_features: "".to_string(), + default_vcpus: default_vcpus as i32, + default_maxvcpus: node_cpus, + }, + }, + TestData { + desc: "all with big values", + input: &mut CpuInfo { + cpu_features: "a,b,c".to_string(), + default_vcpus: 9999999, + default_maxvcpus: 9999999, + }, + output: CpuInfo { + cpu_features: "a,b,c".to_string(), + default_vcpus: node_cpus as i32, + default_maxvcpus: node_cpus, + }, + }, + TestData { + desc: "default_vcpus lager than default_maxvcpus", + input: &mut CpuInfo { + cpu_features: "a, b ,c".to_string(), + default_vcpus: -1, + default_maxvcpus: 1, + }, + output: CpuInfo { + cpu_features: "a,b,c".to_string(), + default_vcpus: 1, + default_maxvcpus: 1, + }, + }, + ]; + + for (_, tc) in tests.iter_mut().enumerate() { + // we can ensure that unwrap will not panic + tc.input.adjust_config().unwrap(); + + assert_eq!( + tc.input.cpu_features, tc.output.cpu_features, + "test[{}] cpu_features", + tc.desc + ); + assert_eq!( + tc.input.default_vcpus, tc.output.default_vcpus, + "test[{}] default_vcpus", + tc.desc + ); + assert_eq!( + tc.input.default_maxvcpus, tc.output.default_maxvcpus, + "test[{}] default_maxvcpus", + tc.desc + ); + } + } }