[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 6/7] Allow calling virHostdevPreparePCIDevices twice for same device



The Multifunction PCI devices cant be hotplugged when the other
functions are bound to host driver. So, detach them all together
once as part of preparation for Multifunction hotplug. The second
attempt should just verify if the device was prepared for the
same domain and if yes, return.

Signed-off-by: Shivaprasad G Bhat <sbhat linux vnet ibm com>
---
 src/qemu/qemu_hotplug.c |   14 +++++++++++++-
 src/util/virhostdev.c   |   16 ++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 5b822f9..24f1731 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1193,9 +1193,21 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
     int backend;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     unsigned int flags = 0;
+    size_t i;
+    virPCIDeviceAddress hostdevaddr = hostdev->source.subsys.u.pci.addr;
+
+    for (i = 0; i < vm->def->nhostdevs; i++) {
+         virPCIDeviceAddress curaddr = vm->def->hostdevs[i]->source.subsys.u.pci.addr;
+         if (virPCIDeviceAddressEqual(&curaddr, &hostdevaddr)) {
+             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("PCI device already assigned to "
+                             "currrent domain"));
+             goto cleanup;
+         }
+    }
 
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
-        return -1;
+        goto cleanup;
 
     if (!cfg->relaxedACS)
         flags |= VIR_HOSTDEV_STRICT_ACS_CHECK;
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
index 980e590..3f84f82 100644
--- a/src/util/virhostdev.c
+++ b/src/util/virhostdev.c
@@ -542,9 +542,25 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr mgr,
      *         have already been taken care of */
     for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
         virPCIDevicePtr pci = virPCIDeviceListGet(pcidevs, i);
+        virPCIDevicePtr actual;
 
         if (virPCIDeviceGetManaged(pci)) {
 
+            /* Its possible that the device attempted to be prepared from
+             * two paths once from the Multifunction device preparation
+             * and again before the hotplug. Let this function  pass if the
+             * device is already in the active list assigned to current domain.
+             */
+            if (mgr->activePCIHostdevs &&
+                (actual = virPCIDeviceListFind(mgr->activePCIHostdevs, pci))) {
+                const char *actual_drvname = NULL;
+                const char *actual_domname = NULL;
+                virPCIDeviceGetUsedBy(actual, &actual_drvname, &actual_domname);
+                if (actual_domname && dom_name &&
+                    STREQ(actual_domname, dom_name))
+                    ret = 0;
+                    goto cleanup;
+            }
             /* We can't look up the actual device because it has not been
              * created yet: virPCIDeviceDetach() will insert a copy of 'pci'
              * into the list of inactive devices, and that copy will be the


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]