[libvirt] [PATCH 2/2] hostdev: fix net config restore error

Martin Kletzander mkletzan at redhat.com
Tue Mar 31 09:46:01 UTC 2015


On Thu, Mar 26, 2015 at 10:23:47PM +0800, Huanle Han wrote:
>Fix for such a case:
>1. Domain A and B xml contain the same SRIOV net hostdev(<interface
>type='hostdev' /> with same pci address).
>2. virsh start A (Successfully, and configure the SRIOV net with
>custom mac)
>3. virsh start B (Fail because of the hostdev used by domain A or other
>reason.)
>In step 3, 'virHostdevNetConfigRestore' is called for the hostdev
>which is still used by domain A. It makes the mac/vlan of the SRIOV net
>change.
>

Makes perfect sense, thanks for finding that out.

>Code Change in this fix:
>1. As the pci used by other domain have been removed from
>'pcidevs' in previous loop, we only restore the nic config for
>the hostdev still in 'pcidevs'(used by this domain)
>2. wrap a function 'virHostdevIsPCINetDevice', which detect whether the
>hostdev is a pci net device or not.
>3. update the comments to make it more clear
>
>Signed-off-by: Huanle Han <hanxueluo at gmail.com>
>---
> src/util/virhostdev.c | 52 ++++++++++++++++++++++++++++++++++++---------------
> 1 file changed, 37 insertions(+), 15 deletions(-)
>
>diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
>index 83f567d..b04bae2 100644
>--- a/src/util/virhostdev.c
>+++ b/src/util/virhostdev.c
>@@ -350,6 +350,14 @@ virHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev,
>     return ret;
> }
>
>+static int
>+virHostdevIsPCINetDevice(virDomainHostdevDefPtr hostdev)
>+{
>+    return hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
>+        hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
>+        hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
>+        hostdev->parent.data.net;
>+}
>
> static int
> virHostdevNetConfigVirtPortProfile(const char *linkdev, int vf,
>@@ -481,10 +489,7 @@ virHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
>     /* This is only needed for PCI devices that have been defined
>      * using <interface type='hostdev'>. For all others, it is a NOP.
>      */
>-    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
>-        hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI ||
>-        hostdev->parent.type != VIR_DOMAIN_DEVICE_NET ||
>-        !hostdev->parent.data.net)
>+    if (!virHostdevIsPCINetDevice(hostdev))
>        return 0;
>
>     isvf = virHostdevIsVirtualFunction(hostdev);
>@@ -781,19 +786,20 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr,
>         goto cleanup;
>     }
>
>-    /* Again 4 loops; mark all devices as inactive before reset
>+    /* Here are 4 loops; mark all devices as inactive before reset
>      * them and reset all the devices before re-attach.
>      * Attach mac and port profile parameters to devices
>      */
>+
>+    /* Loop 1: delete the copy of the dev from pcidevs if it's used by
>+     * other domain. Or delete it from activePCIHostDevs if it had
>+     * been used by this domain.
>+     */
>     i = 0;
>     while (i < virPCIDeviceListCount(pcidevs)) {
>         virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
>         virPCIDevicePtr activeDev = NULL;
>
>-        /* delete the copy of the dev from pcidevs if it's used by
>-         * other domain. Or delete it from activePCIHostDevs if it had
>-         * been used by this domain.
>-         */
>         activeDev = virPCIDeviceListFind(hostdev_mgr->activePCIHostdevs, dev);
>         if (activeDev) {
>             const char *usedby_drvname;
>@@ -814,14 +820,27 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr,
>      * pcidevs, but has been removed from activePCIHostdevs.
>      */
>
>-    /*
>-     * For SRIOV net host devices, unset mac and port profile before
>-     * reset and reattach device
>+    /* Loop 2: before reset and reattach device,
>+     * unset mac and port profile for SRIOV net host devices used by this domain
>      */

The comments were formatted as a sentence, it would be nice to keep it
that way.

>-    for (i = 0; i < nhostdevs; i++)
>-        virHostdevNetConfigRestore(hostdevs[i], hostdev_mgr->stateDir,
>-                                   oldStateDir);
>+    for (i = 0; i < nhostdevs; i++) {
>+        virDomainHostdevDefPtr hostdev = hostdevs[i];
>
>+        if (virHostdevIsPCINetDevice(hostdev)) {
>+            virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
>+            virPCIDevicePtr dev = NULL;
>+            dev = virPCIDeviceNew(pcisrc->addr.domain, pcisrc->addr.bus,
>+                                  pcisrc->addr.slot, pcisrc->addr.function);
>+

The daemon will crash if this function returns NULL.  There should be
check for that, but it shouldn't be fatal, so we can clean up as much
as possible (see Loop 3 for example on how to handle that).

>+            if (virPCIDeviceListFind(pcidevs, dev)) {
>+                virHostdevNetConfigRestore(hostdev, hostdev_mgr->stateDir,
>+                                           oldStateDir);
>+            }
>+            virPCIDeviceFree(dev);
>+        }
>+    }
>+
>+    /* Loop 3: reset pci device used by this domain */
>     for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
>         virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
>
>@@ -834,6 +853,9 @@ virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr,
>         }
>     }
>
>+    /* Loop 4: reattach pci devices used by this domain
>+     * and steal all the devices from pcidevs
>+     */
>     while (virPCIDeviceListCount(pcidevs) > 0) {
>         virPCIDevicePtr dev = virPCIDeviceListStealIndex(pcidevs, 0);
>         virHostdevReattachPCIDevice(dev, hostdev_mgr);
>--
>1.9.1
>

Other than that, the patch looks fine.

Martin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20150331/d2480cf0/attachment-0001.sig>


More information about the libvir-list mailing list