mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: Reject removal of already removed devices
A hot-unplug leaves the PCI node in the device tree until the guest acknowledges the ejection, but VmConfig drops the device entry immediately. Move the config removal into DeviceManager::remove_device() and fail when it returns false, so a second remove-device request cannot reuse the stale device-tree node. Assisted-by: OpenAI:Codex-GPT-5 Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
@@ -5023,20 +5023,24 @@ impl DeviceManager {
|
|||||||
match device_type {
|
match device_type {
|
||||||
VirtioDeviceType::Net => {
|
VirtioDeviceType::Net => {
|
||||||
let mut config = self.config.lock().unwrap();
|
let mut config = self.config.lock().unwrap();
|
||||||
let nets = config.net.as_deref_mut().unwrap();
|
if let Some(fds) = config
|
||||||
let net_dev_cfg = nets
|
.net
|
||||||
.iter_mut()
|
.as_deref_mut()
|
||||||
.find(|net| net.pci_common.id.as_deref() == Some(id))
|
.and_then(|nets| {
|
||||||
// unwrap: the device could not have been removed without an ID
|
nets.iter_mut()
|
||||||
.unwrap();
|
.find(|net| net.pci_common.id.as_deref() == Some(id))
|
||||||
let fds = net_dev_cfg.fds.take().unwrap_or(Vec::new());
|
})
|
||||||
|
.map(|net_dev_cfg| net_dev_cfg.fds.take().unwrap_or_default())
|
||||||
debug!("Closing preserved FDs from virtio-net device: id={id}, fds={fds:?}");
|
{
|
||||||
for fd in fds {
|
debug!(
|
||||||
config.preserved_fds.as_mut().unwrap().remove(&fd);
|
"Closing preserved FDs from virtio-net device: id={id}, fds={fds:?}"
|
||||||
// SAFETY: We are closing the only remaining instance of this FD.
|
);
|
||||||
unsafe {
|
for fd in fds {
|
||||||
libc::close(fd);
|
config.preserved_fds.as_mut().unwrap().remove(&fd);
|
||||||
|
// SAFETY: We are closing the only remaining instance of this FD.
|
||||||
|
unsafe {
|
||||||
|
libc::close(fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5050,11 +5054,15 @@ impl DeviceManager {
|
|||||||
// Cleanup externally-provided VFIO cdev FDs: remove the preserved
|
// Cleanup externally-provided VFIO cdev FDs: remove the preserved
|
||||||
// original from VmConfig and close it.
|
// original from VmConfig and close it.
|
||||||
let mut config = self.config.lock().unwrap();
|
let mut config = self.config.lock().unwrap();
|
||||||
if let Some(devices) = config.devices.as_deref_mut()
|
if let Some(fd) = config
|
||||||
&& let Some(device_cfg) = devices
|
.devices
|
||||||
.iter_mut()
|
.as_deref_mut()
|
||||||
.find(|d| d.pci_common.id.as_deref() == Some(id))
|
.and_then(|devices| {
|
||||||
&& let Some(fd) = device_cfg.fd.take()
|
devices
|
||||||
|
.iter_mut()
|
||||||
|
.find(|d| d.pci_common.id.as_deref() == Some(id))
|
||||||
|
})
|
||||||
|
.and_then(|device_cfg| device_cfg.fd.take())
|
||||||
{
|
{
|
||||||
debug!("Closing preserved FD from VFIO device: id={id}, fd={fd}");
|
debug!("Closing preserved FD from VFIO device: id={id}, fd={fd}");
|
||||||
let fd_removed = config.preserved_fds.as_mut().unwrap().remove(&fd);
|
let fd_removed = config.preserved_fds.as_mut().unwrap().remove(&fd);
|
||||||
@@ -5069,6 +5077,10 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.config.lock().unwrap().remove_device(id) {
|
||||||
|
return Err(DeviceManagerError::UnknownDeviceId(id.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
// Update the PCID bitmap
|
// Update the PCID bitmap
|
||||||
self.pci_segments[pci_segment_id as usize].pci_devices_down |= 1 << pci_device_bdf.device();
|
self.pci_segments[pci_segment_id as usize].pci_devices_down |= 1 << pci_device_bdf.device();
|
||||||
|
|
||||||
|
|||||||
@@ -2236,10 +2236,6 @@ impl Vm {
|
|||||||
.remove_device(id)
|
.remove_device(id)
|
||||||
.map_err(Error::DeviceManager)?;
|
.map_err(Error::DeviceManager)?;
|
||||||
|
|
||||||
// Update VmConfig by removing the device. This is important to
|
|
||||||
// ensure the device would not be created in case of a reboot.
|
|
||||||
self.config.lock().unwrap().remove_device(id);
|
|
||||||
|
|
||||||
self.device_manager
|
self.device_manager
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
Reference in New Issue
Block a user