From 5ba5046e974d8ec449b1520f0a1a5fe98939a965 Mon Sep 17 00:00:00 2001 From: Pavel Mores Date: Tue, 2 Jun 2026 12:09:04 +0200 Subject: [PATCH 1/2] runtime-rs: fix default_memory annonation processing The annotation value is implicitly in MiB but when presented to the byte-unit crate this is interpreted as bytes. When a common value like 2048, meant to mean 2048 MiB but interpreted as 2048 B, is then converted to MiB the result is zero which is less than the minimal allowable memory and the runtime fails to launch. This is fixed by adding a detection whether the annotation value contains units or not. If it doesn't it's first converted to MiB and the rest of the processing then goes like before. This way we allow for the implicit MiB units when no units are given, thus keeping compatibility with existing go shim behaviour, while also allowing for any legal units to be given as well. We take the opportunity to add some unit tests as well. Signed-off-by: Pavel Mores --- src/libs/kata-types/src/annotations/mod.rs | 106 +++++++++++++++------ 1 file changed, 76 insertions(+), 30 deletions(-) diff --git a/src/libs/kata-types/src/annotations/mod.rs b/src/libs/kata-types/src/annotations/mod.rs index b4453a2230..983369ca51 100644 --- a/src/libs/kata-types/src/annotations/mod.rs +++ b/src/libs/kata-types/src/annotations/mod.rs @@ -813,37 +813,24 @@ impl Annotation { } // Hypervisor Memory related annotations KATA_ANNO_CFG_HYPERVISOR_DEFAULT_MEMORY => { - match byte_unit::Byte::parse_str(value, true) { - Ok(mem_bytes) => { - let memory_size = mem_bytes - .get_adjusted_unit(byte_unit::Unit::MiB) - .get_value() - as u32; - info!(sl!(), "get mem {} from annotations: {}", memory_size, value); - if memory_size - < get_hypervisor_plugin(hypervisor_name) - .unwrap() - .get_min_memory() - { - return Err(io::Error::new( - io::ErrorKind::InvalidData, - format!( - "memory specified in annotation {} is less than minimum limitation {}", - memory_size, - get_hypervisor_plugin(hypervisor_name) - .unwrap() - .get_min_memory() - ), - )); - } - hv.memory_info.default_memory = memory_size; - } - Err(error) => { - error!( - sl!(), - "failed to parse byte from string {} error {:?}", value, error - ); + if let Some(memory_size) = convert_to_megabytes(value)? { + if memory_size + < get_hypervisor_plugin(hypervisor_name) + .unwrap() + .get_min_memory() + { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + format!( + "memory specified in annotation {} is less than minimum limitation {}", + memory_size, + get_hypervisor_plugin(hypervisor_name) + .unwrap() + .get_min_memory() + ), + )); } + hv.memory_info.default_memory = memory_size; } } KATA_ANNO_CFG_HYPERVISOR_MEMORY_SLOTS => match self.get_value::(key) { @@ -1225,3 +1212,62 @@ impl Annotation { Ok(()) } } + +fn convert_to_megabytes(mem_size_str: &str) -> Result> { + match byte_unit::Byte::parse_str(mem_size_str, true) { + Ok(mut mem_size) => { + let no_suffix_given = mem_size_str + .trim() + .chars() + .all(|c: char| c.is_ascii_digit()); + if no_suffix_given { + // NOTE the error is apparently unreachable at the moment: + // Byte::from_u64_with_unit() doesn't fail unless its argument + // is too big, however that same too big arg will fail to + // Byte::parse_str() in the first place. (Obviously we still + // need to handle it anyway.) + mem_size = + byte_unit::Byte::from_u64_with_unit(mem_size.as_u64(), byte_unit::Unit::MiB) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + format!("failed to convert {} to MiB", mem_size.as_u64()), + ))?; + } + let memory_size = mem_size.get_adjusted_unit(byte_unit::Unit::MiB).get_value() as u32; + Ok(Some(memory_size)) + } + Err(error) => { + error!( + sl!(), + "failed to parse byte from string {} error {:?}", mem_size_str, error + ); + Ok(None) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_memory_no_unit() { + let result = convert_to_megabytes("2048"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Some(2048)); + } + + #[test] + fn parse_memory_with_units() { + let result = convert_to_megabytes("2 GiB"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Some(2048)); + } + + #[test] + fn parse_memory_parse_error() { + let result = convert_to_megabytes("2048r"); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), None); + } +} From 9b31e06c209f17fe0538121adcdd7a061f915a57 Mon Sep 17 00:00:00 2001 From: Pavel Mores Date: Tue, 16 Jun 2026 13:10:48 +0200 Subject: [PATCH 2/2] runtime-rs: bump the byte-unit dependency version The unit tests added by the previous commit exposed a malfunction of the byte-unit crate on big-endian systems(*), causing s390x CI to fail. Bump the dependency's version to include a fix. Signed-off-by: Pavel Mores --- Cargo.lock | 6 +++--- src/libs/kata-types/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a6f8c29d1..b7ee4189c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -846,9 +846,9 @@ checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byte-unit" -version = "5.2.0" +version = "5.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6d47a4e2961fb8721bcfc54feae6455f2f64e7054f9bc67e875f0e77f4c58d" +checksum = "37bcaa4a0975bed4a760af3efe4368825098ce5f9d37a30c5a021d635dc63d8f" dependencies = [ "rust_decimal", "schemars", @@ -2788,7 +2788,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.10", "tokio", "tower-service", "tracing", diff --git a/src/libs/kata-types/Cargo.toml b/src/libs/kata-types/Cargo.toml index e6202e6486..e3cd01ea37 100644 --- a/src/libs/kata-types/Cargo.toml +++ b/src/libs/kata-types/Cargo.toml @@ -14,7 +14,7 @@ edition = "2018" bitmask-enum = "2.1.0" anyhow = "1.0" base64 = "0.13.0" -byte-unit = "5.1.6" +byte-unit = "5.2.3" glob = "0.3.0" lazy_static = "1.4.0" num_cpus = "1.13.1"