]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: prevent attempts to detach a device on a controller with hotplug='off'
authorLaine Stump <laine@redhat.com>
Thu, 14 May 2020 18:01:47 +0000 (14:01 -0400)
committerLaine Stump <laine@redhat.com>
Mon, 18 May 2020 18:18:48 +0000 (14:18 -0400)
Although the original patches to support controllers with
hotplug='off' were checking during hotplug/attach requests that the
device was being plugged into a PCI controller that didn't have
hotplug disabled, but I forgot to do the same for device detach (the
main impetus for adding the feature was to prevent unplugs originating
from within the guest, so it slipped my mind). So although the guest
OS was ultimately unable to honor the unplug request, libvirt could
still be used to make such a request, and since device attach/detach
are asynchronous operations, the caller to libvirt would receive a
success status back (the device would stubbornly/correctly remain in
the domain status XML however)

This patch remedies that, by looking at the controller for the device
in the detach request, and immediately failing the operation if that
controller has hotplug=off.

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
src/qemu/qemu_hotplug.c

index ab5a7aef84dbcc9bde072273c5c5bb1686633fe5..5608566d6935cdb3048f671d49d2f98fa5c167de 100644 (file)
@@ -5891,6 +5891,36 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
         return -1;
     }
 
+    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+
+        virDomainControllerDefPtr controller;
+        int controllerIdx = virDomainControllerFind(vm->def,
+                                                    VIR_DOMAIN_CONTROLLER_TYPE_PCI,
+                                                    info->addr.pci.bus);
+        if (controllerIdx < 0) {
+            virReportError(VIR_ERR_OPERATION_FAILED,
+                           _("cannot hot unplug %s device with PCI guest address: "
+                             VIR_PCI_DEVICE_ADDRESS_FMT
+                             " - controller not found"),
+                           virDomainDeviceTypeToString(detach.type),
+                           info->addr.pci.domain, info->addr.pci.bus,
+                           info->addr.pci.slot, info->addr.pci.function);
+            return -1;
+        }
+
+        controller = vm->def->controllers[controllerIdx];
+        if (controller->opts.pciopts.hotplug == VIR_TRISTATE_SWITCH_OFF) {
+            virReportError(VIR_ERR_OPERATION_FAILED,
+                           _("cannot hot unplug %s device with PCI guest address: "
+                             VIR_PCI_DEVICE_ADDRESS_FMT
+                             " - not allowed by controller"),
+                           virDomainDeviceTypeToString(detach.type),
+                           info->addr.pci.domain, info->addr.pci.bus,
+                           info->addr.pci.slot, info->addr.pci.function);
+            return -1;
+        }
+    }
+
     /*
      * Issue the qemu monitor command to delete the device (based on
      * its alias), and optionally wait a short time in case the