diff --git a/src/main.rs b/src/main.rs index 2e70913f8..27e67d772 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 687175f6e..1f95c82e8 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -2093,11 +2093,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) @@ -2714,6 +2730,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 146f4e56c..723cd4e79 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -2136,6 +2136,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 f9740e57d..d26a85c06 100644 --- a/vmm/src/vm_config.rs +++ b/vmm/src/vm_config.rs @@ -596,4 +596,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>, }