From e65cca3bf55ea51c34a1cb9c7a23ed9f59e15d88 Mon Sep 17 00:00:00 2001 From: CMGS Date: Thu, 14 May 2026 10:15:51 +0800 Subject: [PATCH] vmm: roll back mem64/IO allocator on failed move_bar After free(old_base), if allocate(new_base) fails the allocator treats old_base as free even though the MMIO/PIO bus still maps the device there. Subsequent allocations pick old_base, mmio_bus.insert hits the live mapping and returns Overlap. Restore old_base on the failure path in both the Memory*BitRegion and IoRegion branches before bubbling the error up. PR #7950 added restore_bar_addr() so the BAR config register stays consistent on failed move_bar(); this completes the same picture for the allocator side. Signed-off-by: CMGS --- vmm/src/device_manager.rs | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index bca1f50c7..8c8348c28 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -729,9 +729,24 @@ impl DeviceRelocation for AddressManager { let mut sys_allocator = self.allocator.lock().unwrap(); // Update system allocator sys_allocator.free_io_addresses(GuestAddress(old_base), len as GuestUsize); - sys_allocator + if sys_allocator .allocate_io_addresses(Some(GuestAddress(new_base)), len as GuestUsize, None) - .ok_or_else(|| io::Error::other("failed allocating new IO range"))?; + .is_none() + { + if sys_allocator + .allocate_io_addresses( + Some(GuestAddress(old_base)), + len as GuestUsize, + None, + ) + .is_none() + { + error!( + "Failed to restore old IO range 0x{old_base:x} after rejected move_bar" + ); + } + return Err(io::Error::other("failed allocating new IO range")); + } // Update PIO bus self.io_bus @@ -753,10 +768,24 @@ impl DeviceRelocation for AddressManager { && old_base <= pci_mmio_allocator.end().0 { pci_mmio_allocator.free(GuestAddress(old_base), len as GuestUsize); - - pci_mmio_allocator + if pci_mmio_allocator .allocate(Some(GuestAddress(new_base)), len as GuestUsize, Some(len)) - .ok_or_else(|| io::Error::other("failed allocating new MMIO range"))?; + .is_none() + { + if pci_mmio_allocator + .allocate( + Some(GuestAddress(old_base)), + len as GuestUsize, + Some(len), + ) + .is_none() + { + error!( + "Failed to restore old MMIO range 0x{old_base:x} after rejected move_bar" + ); + } + return Err(io::Error::other("failed allocating new MMIO range")); + } break; }