From 21f02f410dcce8f3502c0bd422b8967e3cd048db Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Tue, 19 May 2026 10:22:27 +0200 Subject: [PATCH] vmm: clear restore snapshot after device creation A restore snapshot is only construction input. The restore path should use it while rebuilding the VM from saved state, then discard it before later VM lifecycle operations run. Keeping it around is observable after a restored VM changes its device set. For example, a VM can be restored from a snapshot, live-migrated, and then hot-remove a device on the destination. The restored device tree no longer contains that device, but DeviceManager still carries the original device snapshot. That stale snapshot can affect later hotplug. Every added device eventually reaches a constructor that calls state_from_id(self.snapshot.as_ref(), id) or an equivalent snapshot lookup. If the stale snapshot still contains an entry with the newly added device name, the new device is created with old saved state even though the matching device was already removed from the live device tree. Clear the DeviceManager snapshot after hypervisor-specific initialization has rebuilt the interrupt controller and devices. From that point onward, device operations should behave as normal runtime operations, not as restore operations. Co-developed-by: Thomas Prescher Co-developed-by: Leander Kohler On-behalf-of: SAP philipp.schuster@sap.com Signed-off-by: Philipp Schuster --- vmm/src/device_manager.rs | 5 +++++ vmm/src/vm.rs | 3 +++ 2 files changed, 8 insertions(+) diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 8911e8e405..ce224272b8 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1524,6 +1524,11 @@ impl DeviceManager { Ok(()) } + /// Drop restore-only state once all devices have consumed it. + pub(crate) fn clear_restore_snapshot(&mut self) { + self.snapshot = None; + } + #[cfg(feature = "fw_cfg")] pub fn create_fw_cfg_device(&mut self) -> Result<(), DeviceManagerError> { let fw_cfg = Arc::new(Mutex::new(devices::legacy::FwCfg::new( diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 96928b4c1f..9daf5ff8dd 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -639,6 +639,9 @@ impl Vm { snapshot, )?; + // Remove any snapshot artifacts after the hypervisor-specific init. + device_manager.lock().unwrap().clear_restore_snapshot(); + // Load kernel and initramfs files #[cfg(feature = "tdx")] let kernel = config