]> xenbits.xensource.com Git - libvirt.git/commitdiff
hostdev: Detect untracked inactive devices
authorAndrea Bolognani <abologna@redhat.com>
Thu, 17 Mar 2016 16:41:31 +0000 (17:41 +0100)
committerAndrea Bolognani <abologna@redhat.com>
Wed, 23 Mar 2016 09:58:11 +0000 (10:58 +0100)
Unmanaged devices are attached to guests in two steps: first,
the device is detached from the host and marked as inactive;
subsequently, it is marked as active and attached to the guest.

If the daemon is restarted between these two operations, we lose
track of the inactive device.

Steps 5 and 6 of virHostdevPreparePCIDevices() already subtly
take care of this situation, but some planned changes will make
it so that's no longer the case. Plus, explicit is always better
than implicit.

src/util/virhostdev.c

index e0d6465903b1584c076618441998fa7011d051d7..e6b9c1ba9332860730d3ef3386c5a432322e7a3c 100644 (file)
@@ -560,7 +560,8 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr mgr,
         }
     }
 
-    /* Step 2: detach managed devices (i.e. bind to appropriate stub driver) */
+    /* Step 2: detach managed devices and make sure unmanaged devices
+     *         have already been taken care of */
     for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
         virPCIDevicePtr pci = virPCIDeviceListGet(pcidevs, i);
 
@@ -577,8 +578,48 @@ virHostdevPreparePCIDevices(virHostdevManagerPtr mgr,
                                    mgr->inactivePCIHostdevs) < 0)
                 goto reattachdevs;
         } else {
-            VIR_DEBUG("Not detaching unmanaged PCI device %s",
-                      virPCIDeviceGetName(pci));
+            char *driverPath;
+            char *driverName;
+            int stub;
+
+            /* Unmanaged devices should already have been marked as
+             * inactive: if that's the case, we can simply move on */
+            if (virPCIDeviceListFind(mgr->inactivePCIHostdevs, pci)) {
+                VIR_DEBUG("Not detaching unmanaged PCI device %s",
+                          virPCIDeviceGetName(pci));
+                continue;
+            }
+
+            /* If that's not the case, though, it might be because the
+             * daemon has been restarted, causing us to lose track of the
+             * device. Try and recover by marking the device as inactive
+             * if it happens to be bound to a known stub driver.
+             *
+             * FIXME Get rid of this once a proper way to keep track of
+             *       information about active / inactive device across
+             *       daemon restarts has been implemented */
+
+            if (virPCIDeviceGetDriverPathAndName(pci,
+                                                 &driverPath, &driverName) < 0)
+                goto reattachdevs;
+
+            stub = virPCIStubDriverTypeFromString(driverName);
+
+            VIR_FREE(driverPath);
+            VIR_FREE(driverName);
+
+            if (stub > VIR_PCI_STUB_DRIVER_NONE &&
+                stub < VIR_PCI_STUB_DRIVER_LAST) {
+
+                /* The device is bound to a known stub driver: store this
+                 * information and add a copy to the inactive list */
+                virPCIDeviceSetStubDriver(pci, stub);
+
+                VIR_DEBUG("Adding PCI device %s to inactive list",
+                          virPCIDeviceGetName(pci));
+                if (virPCIDeviceListAddCopy(mgr->inactivePCIHostdevs, pci) < 0)
+                    goto reattachdevs;
+            }
         }
     }