[libvirt] [PATCH 3/7] hostdev: Use common reattach code in virHostdevPCINodeDeviceReAttach()

Andrea Bolognani abologna at redhat.com
Tue Jan 19 15:36:05 UTC 2016


This ensures the behavior for reattach is consistent, no matter how it
was triggered (eg. 'virsh nodedev-reattach', 'virsh detach-device' or
shutdown of a domain that is configured to use hostdevs).
---
 src/util/virhostdev.c | 45 +++++++++++++++++++++++++++++++++++++++------
 1 file changed, 39 insertions(+), 6 deletions(-)

diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
index 267aa55..74c43f2 100644
--- a/src/util/virhostdev.c
+++ b/src/util/virhostdev.c
@@ -1625,10 +1625,24 @@ virHostdevPCINodeDeviceDetach(virHostdevManagerPtr hostdev_mgr,
     return ret;
 }
 
+/**
+ * virHostdevPCINodeDeviceReAttach:
+ * @hostdev_mgr: hostdev manager
+ * @pci: PCI device
+ *
+ * Reattach a specific PCI device to the host.
+ *
+ * This function makes sure the device is not in use before reattaching it
+ * to the host; if the device has already been reattached to the host, the
+ * operation is considered successful.
+ *
+ * Returns: 0 on success, <0 on failure
+ */
 int
 virHostdevPCINodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr,
                                 virPCIDevicePtr pci)
 {
+    virPCIDeviceListPtr pcidevs = NULL;
     struct virHostdevIsPCINodeDeviceUsedData data = {hostdev_mgr, NULL,
                                                      false};
     int ret = -1;
@@ -1637,18 +1651,37 @@ virHostdevPCINodeDeviceReAttach(virHostdevManagerPtr hostdev_mgr,
     virObjectLock(hostdev_mgr->inactivePCIHostdevs);
 
     if (virHostdevIsPCINodeDeviceUsed(virPCIDeviceGetAddress(pci), &data))
-        goto out;
+        goto cleanup;
 
-    virPCIDeviceReattachInit(pci);
+    /* We want this function to be idempotent, so if the device has already
+     * been removed from the inactive list (and is not active either, as
+     * per the check above) just return right away */
+    if (!virPCIDeviceListFind(hostdev_mgr->inactivePCIHostdevs, pci)) {
+        VIR_DEBUG("PCI device %s is already attached to the host",
+                  virPCIDeviceGetName(pci));
+        ret = 0;
+        goto cleanup;
+    }
 
-    if (virPCIDeviceReattach(pci, hostdev_mgr->activePCIHostdevs,
-                             hostdev_mgr->inactivePCIHostdevs) < 0)
-        goto out;
+    /* Create a temporary device list */
+    if (!(pcidevs = virPCIDeviceListNew()))
+        goto cleanup;
+    if (virPCIDeviceListAddCopy(pcidevs, pci) < 0)
+        goto cleanup;
+
+    /* Reattach the device. We don't want to skip unmanaged devices in
+     * this case, because the user explicitly asked for the device to
+     * be reattached to the host driver */
+    if (reattachPCIDevices(hostdev_mgr, pcidevs, false) < 0)
+        goto cleanup;
 
     ret = 0;
- out:
+
+ cleanup:
+    virObjectUnref(pcidevs);
     virObjectUnlock(hostdev_mgr->inactivePCIHostdevs);
     virObjectUnlock(hostdev_mgr->activePCIHostdevs);
+
     return ret;
 }
 
-- 
2.5.0




More information about the libvir-list mailing list