|
|
99cbc7 |
From 004c83f00eca921bded4786f24e962174dc71c05 Mon Sep 17 00:00:00 2001
|
|
|
99cbc7 |
Message-Id: <004c83f00eca921bded4786f24e962174dc71c05@dist-git>
|
|
|
99cbc7 |
From: Laine Stump <laine@laine.org>
|
|
|
99cbc7 |
Date: Thu, 11 Apr 2019 15:14:32 -0400
|
|
|
99cbc7 |
Subject: [PATCH] qemu_hotplug: eliminate multiple identical
|
|
|
99cbc7 |
qemuDomainDetachHost*Device() functions
|
|
|
99cbc7 |
MIME-Version: 1.0
|
|
|
99cbc7 |
Content-Type: text/plain; charset=UTF-8
|
|
|
99cbc7 |
Content-Transfer-Encoding: 8bit
|
|
|
99cbc7 |
|
|
|
99cbc7 |
There are separate Detach functions for PCI, USB, SCSI, Vhost, and
|
|
|
99cbc7 |
Mediated hostdevs, but the functions are all 100% the same code,
|
|
|
99cbc7 |
except that the PCI function checks for the guest side of the device
|
|
|
99cbc7 |
being a PCI Multifunction device, while the other 4 check that the
|
|
|
99cbc7 |
device's alias != NULL.
|
|
|
99cbc7 |
|
|
|
99cbc7 |
The check for multifunction PCI devices should be done for *all*
|
|
|
99cbc7 |
devices that are connected to the PCI bus in the guest, not just PCI
|
|
|
99cbc7 |
hostdevs, and qemuIsMultiFunctionDevice() conveniently returns false
|
|
|
99cbc7 |
if the queried device doesn't connect with PCI, so it is safe to make
|
|
|
99cbc7 |
this check for all hostdev devices. (It also needs to be done for many
|
|
|
99cbc7 |
other device types, but that will be addressed in a future patch).
|
|
|
99cbc7 |
|
|
|
99cbc7 |
Likewise, since all hostdevs are detached by calling
|
|
|
99cbc7 |
qemuDomainDeleteDevice(), which requires the device's alias, checking
|
|
|
99cbc7 |
for a valid alias is a reasonable thing for PCI hostdevs too.
|
|
|
99cbc7 |
|
|
|
99cbc7 |
Signed-off-by: Laine Stump <laine@laine.org>
|
|
|
99cbc7 |
ACKed-by: Peter Krempa <pkrempa@redhat.com>
|
|
|
99cbc7 |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
99cbc7 |
(cherry picked from commit 287415e219fa2e477ae011ece275ab15a4be1d73)
|
|
|
99cbc7 |
|
|
|
99cbc7 |
Partially-Resolves: https://bugzilla.redhat.com/1658198
|
|
|
99cbc7 |
Signed-off-by: Laine Stump <laine@redhat.com>
|
|
|
99cbc7 |
Signed-off-by: Laine Stump <laine@laine.org>
|
|
|
99cbc7 |
Message-Id: <20190411191453.24055-21-laine@redhat.com>
|
|
|
99cbc7 |
Acked-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
99cbc7 |
---
|
|
|
99cbc7 |
src/qemu/qemu_hotplug.c | 134 +++++++++-------------------------------
|
|
|
99cbc7 |
1 file changed, 29 insertions(+), 105 deletions(-)
|
|
|
99cbc7 |
|
|
|
99cbc7 |
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
|
|
|
99cbc7 |
index 2bfb5f8d54..b6fcaadd55 100644
|
|
|
99cbc7 |
--- a/src/qemu/qemu_hotplug.c
|
|
|
99cbc7 |
+++ b/src/qemu/qemu_hotplug.c
|
|
|
99cbc7 |
@@ -4947,96 +4947,6 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
|
|
|
99cbc7 |
return ret;
|
|
|
99cbc7 |
}
|
|
|
99cbc7 |
|
|
|
99cbc7 |
-static int
|
|
|
99cbc7 |
-qemuDomainDetachHostPCIDevice(virDomainObjPtr vm,
|
|
|
99cbc7 |
- virDomainHostdevDefPtr detach,
|
|
|
99cbc7 |
- bool async)
|
|
|
99cbc7 |
-{
|
|
|
99cbc7 |
- virDomainHostdevSubsysPCIPtr pcisrc = &detach->source.subsys.u.pci;
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- if (qemuIsMultiFunctionDevice(vm->def, detach->info)) {
|
|
|
99cbc7 |
- virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
99cbc7 |
- _("cannot hot unplug multifunction PCI device: %.4x:%.2x:%.2x.%.1x"),
|
|
|
99cbc7 |
- pcisrc->addr.domain, pcisrc->addr.bus,
|
|
|
99cbc7 |
- pcisrc->addr.slot, pcisrc->addr.function);
|
|
|
99cbc7 |
- return -1;
|
|
|
99cbc7 |
- }
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- if (!async)
|
|
|
99cbc7 |
- qemuDomainMarkDeviceForRemoval(vm, detach->info);
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- return qemuDomainDeleteDevice(vm, detach->info->alias);
|
|
|
99cbc7 |
-}
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
-static int
|
|
|
99cbc7 |
-qemuDomainDetachHostUSBDevice(virDomainObjPtr vm,
|
|
|
99cbc7 |
- virDomainHostdevDefPtr detach,
|
|
|
99cbc7 |
- bool async)
|
|
|
99cbc7 |
-{
|
|
|
99cbc7 |
- if (!detach->info->alias) {
|
|
|
99cbc7 |
- virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
99cbc7 |
- "%s", _("device cannot be detached without a device alias"));
|
|
|
99cbc7 |
- return -1;
|
|
|
99cbc7 |
- }
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- if (!async)
|
|
|
99cbc7 |
- qemuDomainMarkDeviceForRemoval(vm, detach->info);
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- return qemuDomainDeleteDevice(vm, detach->info->alias);
|
|
|
99cbc7 |
-}
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
-static int
|
|
|
99cbc7 |
-qemuDomainDetachHostSCSIDevice(virDomainObjPtr vm,
|
|
|
99cbc7 |
- virDomainHostdevDefPtr detach,
|
|
|
99cbc7 |
- bool async)
|
|
|
99cbc7 |
-{
|
|
|
99cbc7 |
- if (!detach->info->alias) {
|
|
|
99cbc7 |
- virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
99cbc7 |
- "%s", _("device cannot be detached without a device alias"));
|
|
|
99cbc7 |
- return -1;
|
|
|
99cbc7 |
- }
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- if (!async)
|
|
|
99cbc7 |
- qemuDomainMarkDeviceForRemoval(vm, detach->info);
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- return qemuDomainDeleteDevice(vm, detach->info->alias);
|
|
|
99cbc7 |
-}
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
-static int
|
|
|
99cbc7 |
-qemuDomainDetachSCSIVHostDevice(virDomainObjPtr vm,
|
|
|
99cbc7 |
- virDomainHostdevDefPtr detach,
|
|
|
99cbc7 |
- bool async)
|
|
|
99cbc7 |
-{
|
|
|
99cbc7 |
- if (!detach->info->alias) {
|
|
|
99cbc7 |
- virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
99cbc7 |
- "%s", _("device cannot be detached without a device alias"));
|
|
|
99cbc7 |
- return -1;
|
|
|
99cbc7 |
- }
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- if (!async)
|
|
|
99cbc7 |
- qemuDomainMarkDeviceForRemoval(vm, detach->info);
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- return qemuDomainDeleteDevice(vm, detach->info->alias);
|
|
|
99cbc7 |
-}
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
-static int
|
|
|
99cbc7 |
-qemuDomainDetachMediatedDevice(virDomainObjPtr vm,
|
|
|
99cbc7 |
- virDomainHostdevDefPtr detach,
|
|
|
99cbc7 |
- bool async)
|
|
|
99cbc7 |
-{
|
|
|
99cbc7 |
- if (!detach->info->alias) {
|
|
|
99cbc7 |
- virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
99cbc7 |
- _("device cannot be detached without a device alias"));
|
|
|
99cbc7 |
- return -1;
|
|
|
99cbc7 |
- }
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- if (!async)
|
|
|
99cbc7 |
- qemuDomainMarkDeviceForRemoval(vm, detach->info);
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
- return qemuDomainDeleteDevice(vm, detach->info->alias);
|
|
|
99cbc7 |
-}
|
|
|
99cbc7 |
-
|
|
|
99cbc7 |
|
|
|
99cbc7 |
static int
|
|
|
99cbc7 |
qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
|
|
|
99cbc7 |
@@ -5046,25 +4956,30 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
|
|
|
99cbc7 |
{
|
|
|
99cbc7 |
int ret = -1;
|
|
|
99cbc7 |
|
|
|
99cbc7 |
- if (qemuAssignDeviceHostdevAlias(vm->def, &detach->info->alias, -1) < 0)
|
|
|
99cbc7 |
+ if (qemuIsMultiFunctionDevice(vm->def, detach->info)) {
|
|
|
99cbc7 |
+ virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
99cbc7 |
+ _("cannot hot unplug multifunction PCI device with guest address: "
|
|
|
99cbc7 |
+ "%.4x:%.2x:%.2x.%.1x"),
|
|
|
99cbc7 |
+ detach->info->addr.pci.domain, detach->info->addr.pci.bus,
|
|
|
99cbc7 |
+ detach->info->addr.pci.slot, detach->info->addr.pci.function);
|
|
|
99cbc7 |
return -1;
|
|
|
99cbc7 |
+ }
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ if (!detach->info->alias) {
|
|
|
99cbc7 |
+ virReportError(VIR_ERR_OPERATION_FAILED,
|
|
|
99cbc7 |
+ "%s", _("device cannot be detached without a device alias"));
|
|
|
99cbc7 |
+ return -1;
|
|
|
99cbc7 |
+ }
|
|
|
99cbc7 |
|
|
|
99cbc7 |
switch (detach->source.subsys.type) {
|
|
|
99cbc7 |
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
|
|
|
99cbc7 |
- ret = qemuDomainDetachHostPCIDevice(vm, detach, async);
|
|
|
99cbc7 |
- break;
|
|
|
99cbc7 |
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
|
|
|
99cbc7 |
- ret = qemuDomainDetachHostUSBDevice(vm, detach, async);
|
|
|
99cbc7 |
- break;
|
|
|
99cbc7 |
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
|
|
|
99cbc7 |
- ret = qemuDomainDetachHostSCSIDevice(vm, detach, async);
|
|
|
99cbc7 |
- break;
|
|
|
99cbc7 |
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
|
|
|
99cbc7 |
- ret = qemuDomainDetachSCSIVHostDevice(vm, detach, async);
|
|
|
99cbc7 |
- break;
|
|
|
99cbc7 |
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
|
|
|
99cbc7 |
- ret = qemuDomainDetachMediatedDevice(vm, detach, async);
|
|
|
99cbc7 |
- break;
|
|
|
99cbc7 |
+ /* we support detach of all these types of hostdev */
|
|
|
99cbc7 |
+ break;
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
default:
|
|
|
99cbc7 |
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
|
|
99cbc7 |
_("hot unplug is not supported for hostdev subsys type '%s'"),
|
|
|
99cbc7 |
@@ -5072,14 +4987,23 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
|
|
|
99cbc7 |
return -1;
|
|
|
99cbc7 |
}
|
|
|
99cbc7 |
|
|
|
99cbc7 |
- if (ret < 0) {
|
|
|
99cbc7 |
+ if (!async)
|
|
|
99cbc7 |
+ qemuDomainMarkDeviceForRemoval(vm, detach->info);
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ if (qemuDomainDeleteDevice(vm, detach->info->alias) < 0) {
|
|
|
99cbc7 |
if (virDomainObjIsActive(vm))
|
|
|
99cbc7 |
virDomainAuditHostdev(vm, detach, "detach", false);
|
|
|
99cbc7 |
- } else if (!async &&
|
|
|
99cbc7 |
- (ret = qemuDomainWaitForDeviceRemoval(vm)) == 1) {
|
|
|
99cbc7 |
- ret = qemuDomainRemoveHostDevice(driver, vm, detach);
|
|
|
99cbc7 |
+ goto cleanup;
|
|
|
99cbc7 |
}
|
|
|
99cbc7 |
|
|
|
99cbc7 |
+ if (async) {
|
|
|
99cbc7 |
+ ret = 0;
|
|
|
99cbc7 |
+ } else {
|
|
|
99cbc7 |
+ if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
|
|
|
99cbc7 |
+ ret = qemuDomainRemoveHostDevice(driver, vm, detach);
|
|
|
99cbc7 |
+ }
|
|
|
99cbc7 |
+
|
|
|
99cbc7 |
+ cleanup:
|
|
|
99cbc7 |
if (!async)
|
|
|
99cbc7 |
qemuDomainResetDeviceRemoval(vm);
|
|
|
99cbc7 |
|
|
|
99cbc7 |
--
|
|
|
99cbc7 |
2.21.0
|
|
|
99cbc7 |
|