From 15d1f1d7fdd7b0698ace412c2398fbc3d515bcba Mon Sep 17 00:00:00 2001 From: Pascal Scholz Date: Tue, 24 Feb 2026 14:39:45 +0100 Subject: [PATCH] vmm: Refactor locking in `AddressManager::move_bar` The current implementation performs multiple operations on allocators in a row, with the single goal of updating the allocator. For each of these operations, the `Mutex` guarding the respective allocator is locked anew which introduces room for race conditions. Instead of locking the mutex multiple times, we should lock it once to perform the whole move. Signed-off-by: Pascal Scholz On-behalf-of: SAP pascal.scholz@sap.com --- vmm/src/device_manager.rs | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index f22696c7f..52e4cddfa 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -743,15 +743,10 @@ impl DeviceRelocation for AddressManager { ) -> std::result::Result<(), std::io::Error> { match region_type { PciBarRegionType::IoRegion => { + let mut sys_allocator = self.allocator.lock().unwrap(); // Update system allocator - self.allocator - .lock() - .unwrap() - .free_io_addresses(GuestAddress(old_base), len as GuestUsize); - - self.allocator - .lock() - .unwrap() + sys_allocator.free_io_addresses(GuestAddress(old_base), len as GuestUsize); + sys_allocator .allocate_io_addresses(Some(GuestAddress(new_base)), len as GuestUsize, None) .ok_or_else(|| io::Error::other("failed allocating new IO range"))?; @@ -761,26 +756,22 @@ impl DeviceRelocation for AddressManager { .map_err(io::Error::other)?; } PciBarRegionType::Memory32BitRegion | PciBarRegionType::Memory64BitRegion => { - let allocators = if region_type == PciBarRegionType::Memory32BitRegion { + let pci_mmio_allocators = if region_type == PciBarRegionType::Memory32BitRegion { &self.pci_mmio32_allocators } else { &self.pci_mmio64_allocators }; - // Find the specific allocator that this BAR was allocated from and use it for new one - for allocator in allocators { - let allocator_base = allocator.lock().unwrap().base(); - let allocator_end = allocator.lock().unwrap().end(); + // Find the specific allocator that this BAR was allocated from and use it for a new one + for pci_mmio_allocator_mutex in pci_mmio_allocators { + let mut pci_mmio_allocator = pci_mmio_allocator_mutex.lock().unwrap(); - if old_base >= allocator_base.0 && old_base <= allocator_end.0 { - allocator - .lock() - .unwrap() - .free(GuestAddress(old_base), len as GuestUsize); + if old_base >= pci_mmio_allocator.base().0 + && old_base <= pci_mmio_allocator.end().0 + { + pci_mmio_allocator.free(GuestAddress(old_base), len as GuestUsize); - allocator - .lock() - .unwrap() + pci_mmio_allocator .allocate(Some(GuestAddress(new_base)), len as GuestUsize, Some(len)) .ok_or_else(|| io::Error::other("failed allocating new MMIO range"))?;