mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: device_manager: reject duplicate socket in add_user_device
Calling vm.add-user-device a second time with a socket path already in use makes the VMM thread block indefinitely inside vfio_user::Client::new(). libvfio-user servers (SPDK, the reference libvfio-user daemon) accept a single active client per socket, so the second connect(2) succeeds at the OS level but the handshake recvmsg(2) waits for a response that never arrives. All subsequent API requests queue behind the stuck VMM event loop and also hang (vm.info, vmm.ping, vm.remove-device). The VM itself keeps running on vcpu threads, making the symptom confusing: the guest looks healthy, only the API is unreachable. This is easy to hit from management software that uses an idempotent reconcile / ensure pattern for user devices. Reject the call up-front when another user_device already has the same socket path, returning an HTTP 500 with a descriptive UserDeviceSocketInUse error in milliseconds instead of hanging. Signed-off-by: Max Makarov <maxpain@linux.com>
This commit is contained in:
committed by
Rob Bradford
parent
e2c51042d3
commit
cdfedfaab2
@@ -657,6 +657,10 @@ pub enum DeviceManagerError {
|
||||
#[error("Invalid identifier: {0}")]
|
||||
InvalidIdentifier(String),
|
||||
|
||||
/// vfio-user socket path already in use by another user device.
|
||||
#[error("vfio-user socket path already in use: {0:?}")]
|
||||
UserDeviceSocketInUse(std::path::PathBuf),
|
||||
|
||||
/// Error activating virtio device
|
||||
#[error("Error activating virtio device")]
|
||||
VirtioActivate(#[source] ActivateError),
|
||||
@@ -4707,6 +4711,17 @@ impl DeviceManager {
|
||||
) -> DeviceManagerResult<PciDeviceInfo> {
|
||||
self.validate_identifier(&device_cfg.pci_common.id)?;
|
||||
|
||||
// Reject duplicate socket up-front: libvfio-user servers accept a
|
||||
// single client, so a second Client::new() on the same socket blocks
|
||||
// indefinitely in the handshake recvmsg() and hangs the VMM thread.
|
||||
if let Some(existing) = &self.config.lock().unwrap().user_devices
|
||||
&& existing.iter().any(|d| d.socket == device_cfg.socket)
|
||||
{
|
||||
return Err(DeviceManagerError::UserDeviceSocketInUse(
|
||||
device_cfg.socket.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
let (bdf, device_name) = self.add_vfio_user_device(device_cfg)?;
|
||||
|
||||
// Update the PCIU bitmap
|
||||
|
||||
Reference in New Issue
Block a user