diff --git a/src/main.rs b/src/main.rs index ded127202..5acab28c3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -722,6 +722,7 @@ mod unit_tests { gdb: false, platform: None, tpm: None, + preserved_fds: None, }; assert_eq!(expected_vm_config, result_vm_config); diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 7af624fc3..4091763cb 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -2191,11 +2191,27 @@ impl VmConfig { gdb, platform, tpm, + preserved_fds: None, }; config.validate().map_err(Error::Validation)?; Ok(config) } + /// # Safety + /// To use this safely, the caller must guarantee that the input + /// fds are all valid. + pub unsafe fn add_preserved_fds(&mut self, mut fds: Vec) { + if fds.is_empty() { + return; + } + + if let Some(preserved_fds) = &self.preserved_fds { + fds.append(&mut preserved_fds.clone()); + } + + self.preserved_fds = Some(fds); + } + #[cfg(feature = "tdx")] pub fn is_tdx_enabled(&self) -> bool { self.platform.as_ref().map(|p| p.tdx).unwrap_or(false) @@ -2812,6 +2828,7 @@ mod tests { gdb: false, platform: None, tpm: None, + preserved_fds: None, }; assert!(valid_config.validate().is_ok()); diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 112be7e25..ec12c9002 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -2100,6 +2100,7 @@ mod unit_tests { gdb: false, platform: None, tpm: None, + preserved_fds: None, })) } diff --git a/vmm/src/vm_config.rs b/vmm/src/vm_config.rs index 376f2057d..f83d14db6 100644 --- a/vmm/src/vm_config.rs +++ b/vmm/src/vm_config.rs @@ -593,4 +593,10 @@ pub struct VmConfig { pub gdb: bool, pub platform: Option, pub tpm: Option, + // Preseved FDs are the ones that share the same life-time as its holding + // VmConfig instance, such as FDs for creating TAP devices. + // Perserved FDs will stay open as long as the holding VmConfig instance is + // valid, and will be closed when the holding VmConfig instance is destroyed. + #[serde(skip)] + pub preserved_fds: Option>, }