]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Fix race condition when detaching a device
authorPierre LIBEAU <pierre.libeau@corp.ovh.com>
Wed, 31 Aug 2022 12:22:51 +0000 (14:22 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Wed, 12 Oct 2022 12:08:42 +0000 (14:08 +0200)
If QEMU replies to device_del command with "DeviceNotFound"
error, then libvirt doesn't clean the device from the live
configuration.

This is because qemuMonitorDelDevice() returns -2 to
qemuDomainDeleteDevice() and instead of calling
qemuDomainRemoveDevice() the qemuDomainDetachDeviceLive() jumps
right onto cleanup label.

Resolves: https://gitlab.com/libvirt/libvirt/-/issues/359
Signed-off-by: Pierre LIBEAU <pierre.libeau@corp.ovh.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/qemu/qemu_hotplug.c

index 00727f6ddc950e5dc9c070d3bb8756770256133b..f5d12b4fb3561d54a76a45c70ccf10a48c1cf857 100644 (file)
@@ -93,6 +93,8 @@ qemuDomainResetDeviceRemoval(virDomainObj *vm);
  *
  * Returns: 0 on success,
  *         -1 otherwise.
+ *         -2 device does not exist in qemu, but it still
+ *            exists in libvirt
  */
 static int
 qemuDomainDeleteDevice(virDomainObj *vm,
@@ -124,7 +126,6 @@ qemuDomainDeleteDevice(virDomainObj *vm,
              * domain XML is queried right after detach API the
              * device would still be there.  */
             VIR_DEBUG("Detaching of device %s failed and no event arrived", alias);
-            rc = 0;
         }
     }
 
@@ -5864,6 +5865,7 @@ qemuDomainDetachDeviceLive(virDomainObj *vm,
     virDomainDeviceDef detach = { .type = match->type };
     virDomainDeviceInfo *info = NULL;
     int ret = -1;
+    int rc;
 
     switch ((virDomainDeviceType)match->type) {
         /*
@@ -6053,7 +6055,10 @@ qemuDomainDetachDeviceLive(virDomainObj *vm,
     if (!async)
         qemuDomainMarkDeviceForRemoval(vm, info);
 
-    if (qemuDomainDeleteDevice(vm, info->alias) < 0) {
+    rc = qemuDomainDeleteDevice(vm, info->alias);
+    if (rc < 0) {
+        if (rc == -2)
+            ret = qemuDomainRemoveDevice(driver, vm, &detach);
         if (virDomainObjIsActive(vm))
             qemuDomainRemoveAuditDevice(vm, &detach, false);
         goto cleanup;