[libvirt] [PATCH v2 1/2] add hostdev passthrough common library

Jim Fehlig jfehlig at suse.com
Mon Jun 10 21:53:26 UTC 2013


Chunyan Liu wrote:
> Write separate module for hostdev passthrough common library so that it could be
> used by all hypervisor drivers and maintain a global hostdev state.
>
> Changes to v1:
> *  add scsi part to common library 
> *  instead of hardcode, check for <driver name='kvm/vfio/xen'/> setting, call
>    virPCIDeviceSetStubDriver to set stub driver. For libxl driver, a <driver
>    name='xen' /> is needed.      
> *  rebase to current libvirt changes
>
>
> Signed-off-by: Chunyan Liu <cyliu at suse.com>
> ---
>  po/POTFILES.in               |    1 +
>  src/Makefile.am              |    1 +
>  src/conf/domain_conf.c       |    3 +-
>  src/conf/domain_conf.h       |    1 +
>  src/libvirt.c                |    5 +
>  src/libvirt_private.syms     |   22 +-
>  src/util/virhostdevmanager.c | 1486 ++++++++++++++++++++++++++++++++++++++++++
>  src/util/virhostdevmanager.h |  109 +++
>  src/util/virpci.c            |   17 +-
>  src/util/virpci.h            |    7 +-
>  src/util/virscsi.c           |   18 +-
>  src/util/virscsi.h           |    4 +-
>  src/util/virusb.c            |   19 +-
>  src/util/virusb.h            |    4 +-
>  14 files changed, 1671 insertions(+), 26 deletions(-)
>  create mode 100644 src/util/virhostdevmanager.c
>  create mode 100644 src/util/virhostdevmanager.h
>
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index f3ea4da..a7c21bf 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -188,6 +188,7 @@ src/util/viruri.c
>  src/util/virusb.c
>  src/util/virutil.c
>  src/util/virxml.c
> +src/util/virhostdevmanager.c
>  src/vbox/vbox_MSCOMGlue.c
>  src/vbox/vbox_XPCOMCGlue.c
>  src/vbox/vbox_driver.c
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 6c626ac..0f09fa5 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -130,6 +130,7 @@ UTIL_SOURCES =							\
>  		util/virutil.c util/virutil.h			\
>  		util/viruuid.c util/viruuid.h			\
>  		util/virxml.c util/virxml.h			\
> +                util/virhostdevmanager.c util/virhostdevmanager.h \
>  		$(NULL)
>  
>  
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index f0ca9d5..5065d30 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -594,7 +594,8 @@ VIR_ENUM_IMPL(virDomainHostdevSubsysPciBackend,
>                VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST,
>                "default",
>                "kvm",
> -              "vfio")
> +              "vfio",
> +              "xen")
>  
>  VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST,
>                "storage",
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index c176a4c..d24ab79 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -394,6 +394,7 @@ typedef enum {
>      VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, /* currently kvm, could change */
>      VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM,    /* force legacy kvm style */
>      VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO,   /* force vfio */
> +    VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN,    /* force xen */
>  
>      VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST
>  } virDomainHostdevSubsysPciBackendType;
> diff --git a/src/libvirt.c b/src/libvirt.c
> index 30f9646..1a3032a 100644
> --- a/src/libvirt.c
> +++ b/src/libvirt.c
> @@ -65,6 +65,7 @@
>  #include "virthread.h"
>  #include "virstring.h"
>  #include "virutil.h"
> +#include "virhostdevmanager.h"
>  
>  #ifdef WITH_TEST
>  # include "test/test_driver.h"
> @@ -827,6 +828,7 @@ int virStateInitialize(bool privileged,
>      if (virInitialize() < 0)
>          return -1;
>  
> +    virHostdevManagerInit();
>      for (i = 0 ; i < virStateDriverTabCount ; i++) {
>          if (virStateDriverTab[i]->stateInitialize) {
>              VIR_DEBUG("Running global init for %s state driver",
> @@ -858,6 +860,9 @@ int virStateCleanup(void) {
>              virStateDriverTab[i]->stateCleanup() < 0)
>              ret = -1;
>      }
> +
> +    virHostdevManagerCleanup();
> + 
>      return ret;
>  }
>  
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index cc734da..9967fa0 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1345,6 +1345,27 @@ virHookInitialize;
>  virHookPresent;
>  
>  
> +#util/virhostdevmanager.h
> +virFreeHostdevNameList;
> +virGetActivePciHostdevs;
> +virGetActiveScsiHostdevs;
> +virGetActiveUsbHostdevs;
> +virGetDomainActivePciHostdevs;
> +virGetDomainActiveScsiHostdevs;
> +virGetDomainActiveUsbHostdevs;
> +virHostdevManagerCleanup;
> +virHostdevManagerGetDefault;
> +virHostdevManagerInit;
> +virHostdevManagerPrepareHostdevs;
> +virHostdevManagerPreparePciHostdevs;
> +virHostdevManagerPrepareScsiHostdevs;
> +virHostdevManagerPrepareUsbHostdevs;
> +virHostdevManagerReAttachHostdevs;
> +virHostdevManagerReAttachPciHostdevs;
> +virHostdevManagerReAttachScsiHostdevs;
> +virHostdevManagerReAttachUsbHostdevs;
> +
> +
>  # util/viridentity.h
>  virIdentityGetAttr;
>  virIdentityIsEqual;
> @@ -1992,7 +2013,6 @@ virXPathULong;
>  virXPathULongHex;
>  virXPathULongLong;
>  
> -
>   

Spurious removal of a line here.

>  # Let emacs know we want case-insensitive sorting
>  # Local Variables:
>  # sort-fold-case: t
> diff --git a/src/util/virhostdevmanager.c b/src/util/virhostdevmanager.c
> new file mode 100644
> index 0000000..310c943
> --- /dev/null
> +++ b/src/util/virhostdevmanager.c
> @@ -0,0 +1,1486 @@
> +/*
> + * Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library.  If not, see
> + * <http://www.gnu.org/licenses/>.
> + *
> + * Author: Chunyan Liu <cyliu at suse.com>
> + */
> +
> +#include <config.h>
> +
> +#include "virhostdevmanager.h"
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#include "viralloc.h"
> +#include "virstring.h"
> +#include "virfile.h"
> +#include "virerror.h"
> +#include "virlog.h"
> +#include "virpci.h"
> +#include "virusb.h"
> +#include "virscsi.h"
> +#include "virnetdev.h"
> +
> +/* For virReportOOMError()  and virReportSystemError() */
> +#define VIR_FROM_THIS VIR_FROM_NONE
> +
> +struct _virHostdevManager{
> +    char *stateDir;
> +
> +    virPCIDeviceListPtr activePciHostdevs;
> +    virPCIDeviceListPtr inactivePciHostdevs;
> +    virUSBDeviceListPtr activeUsbHostdevs;
> +    virSCSIDeviceListPtr activeScsiHostdevs;
> +};
> +
> +static virHostdevManagerPtr hostdevMgr;
> +
> +int virHostdevManagerInit(void)
>   

Much of libvirt uses the pattern

int
virHostdevManagerInit(void)

We should do the same here.

> +{
> +    char ebuf[1024];
> +    if (VIR_ALLOC(hostdevMgr) < 0)
> +        goto out_of_memory;
> +
> +    if ((hostdevMgr->activePciHostdevs = virPCIDeviceListNew()) == NULL)
> +        goto error;
> +
> +    if ((hostdevMgr->activeUsbHostdevs = virUSBDeviceListNew()) == NULL)
> +        goto error;
> +
> +    if ((hostdevMgr->inactivePciHostdevs = virPCIDeviceListNew()) == NULL)
> +        goto error;
> +
> +    if ((hostdevMgr->activeScsiHostdevs = virSCSIDeviceListNew()) == NULL)
> +        goto error;
> +
> +    if (virAsprintf(&hostdevMgr->stateDir,
> +		    "%s",HOSTDEV_STATE_DIR) == -1)		   
> +        goto out_of_memory;
> +
> +    if (virFileMakePath(hostdevMgr->stateDir) < 0) {
> +            VIR_ERROR(_("Failed to create state dir '%s': %s"),
> +                      hostdevMgr->stateDir, virStrerror(errno, ebuf, sizeof(ebuf)));
> +	goto error;
> +    }
> +
> +    return 0;
> +
> +out_of_memory:
> +    virReportOOMError();
> +error:
> +    return -1;
> +}
> +
> +void virHostdevManagerCleanup(void)
> +{
> +    if(!hostdevMgr)
>   

Space after 'if'.

> +        return;
> +
> +    virObjectUnref(hostdevMgr->activePciHostdevs);
> +    virObjectUnref(hostdevMgr->inactivePciHostdevs);
> +    virObjectUnref(hostdevMgr->activeUsbHostdevs);
> +    virObjectUnref(hostdevMgr->activeScsiHostdevs);
> +
> +    VIR_FREE(hostdevMgr->stateDir);
> +}
> +
> +virHostdevManagerPtr virHostdevManagerGetDefault(void)
> +{
> +    return hostdevMgr;
> +}
> +
> +static int
> +virDomainHostdevPciSysfsPath(virDomainHostdevDefPtr hostdev, char **sysfs_path)
> +{
> +    virPCIDeviceAddress config_address;
> +
> +    config_address.domain = hostdev->source.subsys.u.pci.addr.domain;
> +    config_address.bus = hostdev->source.subsys.u.pci.addr.bus;
> +    config_address.slot = hostdev->source.subsys.u.pci.addr.slot;
> +    config_address.function = hostdev->source.subsys.u.pci.addr.function;
> +
> +    return virPCIDeviceAddressGetSysfsFile(&config_address, sysfs_path);
> +}
> +
> +static int
> +virDomainHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev)
> +{
> +    char *sysfs_path = NULL;
> +    int ret = -1;
> +
> +    if (virDomainHostdevPciSysfsPath(hostdev, &sysfs_path) < 0)
> +        return ret;
> +
> +    ret = virPCIIsVirtualFunction(sysfs_path);
> +
> +    VIR_FREE(sysfs_path);
> +
> +    return ret;
> +}
> +
> +static int
> +virDomainHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev,
> +                           int *vf)
>   

Another libvirt pattern is to put each param on its own line if they all
don't fit on one, e.g.

virDomainHostdevNetDevice(virDomainHostdeDefPtr hostdev,
char **linkdev,
int *vf)

> +{
> +    int ret = -1;
> +    char *sysfs_path = NULL;
> +
> +    if (virDomainHostdevPciSysfsPath(hostdev, &sysfs_path) < 0)
> +        return ret;
> +
> +    if (virPCIIsVirtualFunction(sysfs_path) == 1) {
> +        if (virPCIGetVirtualFunctionInfo(sysfs_path, linkdev,
> +                                         vf) < 0)
> +            goto cleanup;
> +    } else {
> +        if (virPCIGetNetName(sysfs_path, linkdev) < 0)
> +            goto cleanup;
> +        *vf = -1;
> +    }
> +
> +    ret = 0;
> +
> +cleanup:
> +    VIR_FREE(sysfs_path);
> +
> +    return ret;
> +}
> +
> +static int
> +virDomainHostdevNetConfigVirtPortProfile(const char *linkdev, int vf,
> +                                          virNetDevVPortProfilePtr virtPort,
> +                                          const virMacAddrPtr macaddr,
> +                                          const unsigned char *uuid,
> +                                          int associate)
>   

Whitespace is off a bit on the lines with additional params.

> +{
> +    int ret = -1;
> +
> +    if (!virtPort)
> +        return ret;
> +
> +    switch (virtPort->virtPortType) {
> +    case VIR_NETDEV_VPORT_PROFILE_NONE:
> +    case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
> +    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
> +    case VIR_NETDEV_VPORT_PROFILE_LAST:
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                       _("virtualport type %s is "
> +                         "currently not supported on interfaces of type "
> +                         "hostdev"),
> +                       virNetDevVPortTypeToString(virtPort->virtPortType));
> +        break;
> +
> +    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
> +        if (associate)
> +            ret = virNetDevVPortProfileAssociate(NULL, virtPort, macaddr,
> +                                                 linkdev, vf, uuid,
> +                                                 VIR_NETDEV_VPORT_PROFILE_OP_CREATE, false);
> +        else
> +            ret = virNetDevVPortProfileDisassociate(NULL, virtPort,
> +                                                    macaddr, linkdev, vf,
> +                                                    VIR_NETDEV_VPORT_PROFILE_OP_DESTROY);
> +        break;
> +    }
> +
> +    return ret;
> +}
> +
> +static int
> +virDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
> +                                  const unsigned char *uuid,
> +                                  char *stateDir)
>   

Whitespace is off a bit on the lines with additional params.

> +{
> +    char *linkdev = NULL;
> +    virNetDevVlanPtr vlan;
> +    virNetDevVPortProfilePtr virtPort;
> +    int ret = -1;
> +    int vf = -1;
> +    int vlanid = -1;
> +    int port_profile_associate = 1;
> +    int isvf;
> +
> +    isvf = virDomainHostdevIsVirtualFunction(hostdev);
> +    if (isvf <= 0) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("Interface type hostdev is currently supported on"
> +                         " SR-IOV Virtual Functions only"));
> +        return ret;
> +    }
> +
> +    if (virDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
> +        return ret;
> +
> +    vlan = virDomainNetGetActualVlan(hostdev->parent.data.net);
> +    virtPort = virDomainNetGetActualVirtPortProfile(
> +                                 hostdev->parent.data.net);
> +    if (virtPort) {
> +        if (vlan) {
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                           _("direct setting of the vlan tag is not allowed "
> +                             "for hostdev devices using %s mode"),
> +                           virNetDevVPortTypeToString(virtPort->virtPortType));
> +            goto cleanup;
> +        }
> +        ret = virDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
> +                            virtPort, &hostdev->parent.data.net->mac, uuid,
> +                            port_profile_associate);
> +    } else {
> +        /* Set only mac and vlan */
> +        if (vlan) {
> +            if (vlan->nTags != 1 || vlan->trunk) {
> +                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                               _("vlan trunking is not supported "
> +                                 "by SR-IOV network devices"));
> +                goto cleanup;
> +            }
> +            if (vf == -1) {
> +                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                               _("vlan can only be set for SR-IOV VFs, but "
> +                                 "%s is not a VF"), linkdev);
> +                goto cleanup;
> +            }
> +            vlanid = vlan->tag[0];
> +        } else  if (vf >= 0) {
> +            vlanid = 0; /* assure any current vlan tag is reset */
> +        }
> +
> +        ret = virNetDevReplaceNetConfig(linkdev, vf,
> +                                        &hostdev->parent.data.net->mac,
> +                                        vlanid, stateDir);
> +    }
> +cleanup:
> +    VIR_FREE(linkdev);
> +    return ret;
> +}
> +
> +static int
> +virDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
> +                                  char *stateDir)
>   

Whitespace off here too.

> +{
> +    char *linkdev = NULL;
> +    virNetDevVPortProfilePtr virtPort;
> +    int ret = -1;
> +    int vf = -1;
> +    int port_profile_associate = 0;
> +    int isvf;
> +
> +    isvf = virDomainHostdevIsVirtualFunction(hostdev);
> +    if (isvf <= 0) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("Interface type hostdev is currently supported on"
> +                         " SR-IOV Virtual Functions only"));
> +        return ret;
> +    }
> +
> +    if (virDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
> +        return ret;
> +
> +    virtPort = virDomainNetGetActualVirtPortProfile(
> +                                 hostdev->parent.data.net);
> +    if (virtPort)
> +        ret = virDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort,
> +                                          &hostdev->parent.data.net->mac, NULL,
> +                                          port_profile_associate);
> +    else
> +        ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir);
> +
> +    VIR_FREE(linkdev);
> +
> +    return ret;
> +}
> +
> +static virPCIDeviceListPtr
> +virHostdevManagerGetPciHostDeviceList(virDomainHostdevDefPtr *hostdevs, 
> +                                      int nhostdevs)
> +{
> +    virPCIDeviceListPtr list;
> +    int i;
> +
> +    if (!(list = virPCIDeviceListNew()))
> +        return NULL;
> +
> +    for (i = 0 ; i < nhostdevs ; i++) {
>   

Extra spaces here before the ';'.

> +        virDomainHostdevDefPtr hostdev = hostdevs[i];
> +        virPCIDevicePtr dev;
> +
> +        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
> +            continue;
> +        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
> +            continue;
> +
> +        dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain,
> +                              hostdev->source.subsys.u.pci.addr.bus,
> +                              hostdev->source.subsys.u.pci.addr.slot,
> +                              hostdev->source.subsys.u.pci.addr.function);
> +        if (!dev) {
> +            virObjectUnref(list);
> +            return NULL;
> +        }
> +
> +        if (virPCIDeviceListAdd(list, dev) < 0) {
> +            virPCIDeviceFree(dev);
> +            virObjectUnref(list);
> +            return NULL;
> +        }
> +
> +        virPCIDeviceSetManaged(dev, hostdev->managed);
> +
> +        switch (hostdev->source.subsys.u.pci.backend) {
> +            case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
> +                 virPCIDeviceSetStubDriver(dev, "vfio-pci");
> +                 break;
> +            case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN :
>   

Extra space here before ':'.

> +                 virPCIDeviceSetStubDriver(dev, "pciback");
> +                 break;
> +            default:
> +                 virPCIDeviceSetStubDriver(dev, "pci-stub");
> +                 break;
> +        }
> +    }
> +
> +    return list;
> +}
> +
> +int
> +virHostdevManagerPreparePciHostdevs(virHostdevManagerPtr mgr,
> +                                    const char *drv_name, 
> +                                    const char *dom_name,
> +                                    const unsigned char *uuid,
> +                                    virDomainHostdevDefPtr *hostdevs,
> +                                    int nhostdevs,
> +		                            unsigned int flags)
>   

Mixture of tabs and spaces on the 'unsigned int flags' line.

> +{
> +    virPCIDeviceListPtr pcidevs;
> +    int last_processed_hostdev_vf = -1;
> +    int i;
> +    int ret = -1;
> +
> +    virObjectLock(mgr->activePciHostdevs);
> +    virObjectLock(mgr->inactivePciHostdevs);
> +
> +    if (!(pcidevs = virHostdevManagerGetPciHostDeviceList(hostdevs, nhostdevs)))
> +        goto cleanup;
> +
> +    /* We have to use 9 loops here. *All* devices must
> +     * be detached before we reset any of them, because
> +     * in some cases you have to reset the whole PCI,
> +     * which impacts all devices on it. Also, all devices
> +     * must be reset before being marked as active.
> +     */
> +
> +    /* Loop 1: validate that non-managed device isn't in use, eg
> +     * by checking that device is either un-bound, or bound
> +     * to stub driver
> +     */
> +
> +    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
> +        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
> +        virPCIDevicePtr other;
> +        bool strict_acs_check = (flags & VIR_STRICT_ACS_CHECK)?true:false;
>   

Need some extra whitespace here, e.g.

bool strict_acs_check = (flags & VIR_STRICT_ACS_CHECK) ? true: false;

> +
> +        if (!virPCIDeviceIsAssignable(dev, strict_acs_check)) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("PCI device %s is not assignable"),
> +                           virPCIDeviceGetName(dev));
> +            goto cleanup;
> +        }
> +        /* The device is in use by other active domain if
> +         * the dev is in list activePciHostdevs.
> +         */
> +        if ((other = virPCIDeviceListFind(mgr->activePciHostdevs, dev))) {
> +            char *other_drvname = NULL;
> +            char *other_domname = NULL;
> +            virPCIDeviceGetUsedBy(other, &other_drvname, &other_domname);
> +
> +            if (other_drvname && other_domname)
> +                virReportError(VIR_ERR_OPERATION_INVALID,
> +                               _("PCI device %s is in use by driver %s,domain %s"),
> +                               virPCIDeviceGetName(dev), other_drvname,
> +                               other_domname);
> +            else
> +                virReportError(VIR_ERR_OPERATION_INVALID,
> +                               _("PCI device %s is already in use"),
> +                               virPCIDeviceGetName(dev));
> +            VIR_FREE(other_drvname);
> +            VIR_FREE(other_domname); 
> +            goto cleanup;
> +        }
> +    }
> +
> +    /* Loop 2: detach managed devices */
> +    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
> +        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
> +        if (virPCIDeviceGetManaged(dev) &&
> +            virPCIDeviceDetach(dev, mgr->activePciHostdevs, NULL, NULL) < 0)
> +            goto reattachdevs;
> +    }
> +
> +    /* Loop 3: Now that all the PCI hostdevs have been detached, we
> +     * can safely reset them */
> +    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
> +        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
> +        if (virPCIDeviceReset(dev, mgr->activePciHostdevs,
> +                              mgr->inactivePciHostdevs) < 0)
> +            goto reattachdevs;
> +    }
> +
> +    /* Loop 4: For SRIOV network devices, Now that we have detached the
> +     * the network device, set the netdev config */
> +    for (i = 0; i < nhostdevs; i++) {
> +         virDomainHostdevDefPtr hostdev = hostdevs[i];
> +         if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
> +             continue;
> +         if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
> +             continue;
> +         if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
> +             hostdev->parent.data.net) {
> +             if (virDomainHostdevNetConfigReplace(hostdev, uuid,
> +                                                   mgr->stateDir) < 0) {
> +                 goto resetvfnetconfig;
> +             }
> +         }
> +         last_processed_hostdev_vf = i;
> +    }
> +
> +    /* Loop 5: Now mark all the devices as active */
> +    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
> +        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
> +        if (virPCIDeviceListAdd(mgr->activePciHostdevs, dev) < 0)
> +            goto inactivedevs;
> +    }
> +
> +    /* Loop 6: Now remove the devices from inactive list. */
> +    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
> +         virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
> +         virPCIDeviceListDel(mgr->inactivePciHostdevs, dev);
> +    }
> +
> +    /* Loop 7: Now set the used_by_domain of the device in
> +     * driver->activePciHostdevs as domain name.
> +     */
> +    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
> +        virPCIDevicePtr dev, activeDev;
> +
> +        dev = virPCIDeviceListGet(pcidevs, i);
> +        activeDev = virPCIDeviceListFind(mgr->activePciHostdevs, dev);
> +
> +        if (activeDev)
> +            virPCIDeviceSetUsedBy(activeDev, drv_name, dom_name);
> +    }
> +
> +    /* Loop 8: Now set the original states for hostdev def */
> +    for (i = 0; i < nhostdevs; i++) {
> +        virPCIDevicePtr dev;
> +        virPCIDevicePtr pcidev;
> +        virDomainHostdevDefPtr hostdev = hostdevs[i];
> +
> +        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
> +            continue;
> +        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
> +            continue;
> +
> +        dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain,
> +                              hostdev->source.subsys.u.pci.addr.bus,
> +                              hostdev->source.subsys.u.pci.addr.slot,
> +                              hostdev->source.subsys.u.pci.addr.function);
> +
> +        /* original states "unbind_from_stub", "remove_slot",
> +         * "reprobe" were already set by pciDettachDevice in
> +         * loop 2.
> +         */
> +        if ((pcidev = virPCIDeviceListFind(pcidevs, dev))) {
> +            hostdev->origstates.states.pci.unbind_from_stub =
> +                virPCIDeviceGetUnbindFromStub(pcidev);
> +            hostdev->origstates.states.pci.remove_slot =
> +                virPCIDeviceGetRemoveSlot(pcidev);
> +            hostdev->origstates.states.pci.reprobe =
> +                virPCIDeviceGetReprobe(pcidev);
> +        }
> +
> +        virPCIDeviceFree(dev);
> +    }
> +
> +    /* Loop 9: Now steal all the devices from pcidevs */
> +    while (virPCIDeviceListCount(pcidevs) > 0)
> +        virPCIDeviceListStealIndex(pcidevs, 0);
> +
> +    ret = 0;
> +    goto cleanup;
> +
> +inactivedevs:
> +    /* Only steal all the devices from driver->activePciHostdevs. We will
> +     * free them in virObjectUnref().
> +     */
> +    while (virPCIDeviceListCount(pcidevs) > 0) {
> +        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, 0);
> +        virPCIDeviceListSteal(mgr->activePciHostdevs, dev);
> +    }
> +
> +resetvfnetconfig:
> +    for (i = 0; i < last_processed_hostdev_vf; i++) {
> +         virDomainHostdevDefPtr hostdev = hostdevs[i];
> +         if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
> +             hostdev->parent.data.net) {
> +             virDomainHostdevNetConfigRestore(hostdev, mgr->stateDir);
> +         }
> +    }
> +
> +reattachdevs:
> +    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
> +        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
> +        virPCIDeviceReattach(dev, mgr->activePciHostdevs, NULL);
> +    }
> +
> +cleanup:
> +    virObjectUnlock(mgr->activePciHostdevs);
> +    virObjectUnlock(mgr->inactivePciHostdevs);
> +    virObjectUnref(pcidevs);
> +    return ret;
> +}
> +
> +static int
> +virFindHostdevUSBDevice(virDomainHostdevDefPtr hostdev,
> +                         bool mandatory,
> +                         virUSBDevicePtr *usb)
>   

Whitespace off here in the parameter alignment.

> +{
> +    unsigned vendor = hostdev->source.subsys.u.usb.vendor;
> +    unsigned product = hostdev->source.subsys.u.usb.product;
> +    unsigned bus = hostdev->source.subsys.u.usb.bus;
> +    unsigned device = hostdev->source.subsys.u.usb.device;
> +    bool autoAddress = hostdev->source.subsys.u.usb.autoAddress;
> +    int rc;
> +
> +    *usb = NULL;
> +
> +    if (vendor && bus) {
> +        rc = virUSBDeviceFind(vendor, product, bus, device,
> +                              NULL,
> +                              autoAddress ? false : mandatory,
> +                              usb);
> +        if (rc < 0) {
> +            return -1;
> +        } else if (!autoAddress) {
> +            goto out;
> +        } else {
> +            VIR_INFO("USB device %x:%x could not be found at previous"
> +                     " address (bus:%u device:%u)",
> +                     vendor, product, bus, device);
> +        }
> +    }
> +
> +    /* When vendor is specified, its USB address is either unspecified or the
> +     * device could not be found at the USB device where it had been
> +     * automatically found before.
> +     */
> +    if (vendor) {
> +        virUSBDeviceListPtr devs;
> +
> +        rc = virUSBDeviceFindByVendor(vendor, product, NULL, mandatory, &devs);
> +        if (rc < 0)
> +            return -1;
> +
> +        if (rc == 1) {
> +            *usb = virUSBDeviceListGet(devs, 0);
> +            virUSBDeviceListSteal(devs, *usb);
> +        }
> +        virObjectUnref(devs);
> +
> +        if (rc == 0) {
> +            goto out;
> +        } else if (rc > 1) {
> +            if (autoAddress) {
> +                virReportError(VIR_ERR_OPERATION_FAILED,
> +                               _("Multiple USB devices for %x:%x were found,"
> +                                 " but none of them is at bus:%u device:%u"),
> +                               vendor, product, bus, device);
> +            } else {
> +                virReportError(VIR_ERR_OPERATION_FAILED,
> +                               _("Multiple USB devices for %x:%x, "
> +                                 "use <address> to specify one"),
> +                               vendor, product);
> +            }
> +            return -1;
> +        }
> +
> +        hostdev->source.subsys.u.usb.bus = virUSBDeviceGetBus(*usb);
> +        hostdev->source.subsys.u.usb.device = virUSBDeviceGetDevno(*usb);
> +        hostdev->source.subsys.u.usb.autoAddress = true;
> +
> +        if (autoAddress) {
> +            VIR_INFO("USB device %x:%x found at bus:%u device:%u (moved"
> +                     " from bus:%u device:%u)",
> +                     vendor, product,
> +                     hostdev->source.subsys.u.usb.bus,
> +                     hostdev->source.subsys.u.usb.device,
> +                     bus, device);
> +        }
> +    } else if (!vendor && bus) {
> +        if (virUSBDeviceFindByBus(bus, device, NULL, mandatory, usb) < 0)
> +            return -1;
> +    }
> +
> +out:
> +    if (!*usb)
> +        hostdev->missing = true;
> +    return 0;
> +}
> +
> +static int 
> +virHostdevManagerMarkUsbHostdevs(virHostdevManagerPtr mgr,
> +                                 const char *drv_name, 
> +                                 const char *dom_name,
> +                                 virUSBDeviceListPtr list)
> +{
> +    int i, j;
> +    unsigned int count;
> +    virUSBDevicePtr tmp;
> +
> +    virObjectLock(mgr->activeUsbHostdevs);
> +    count = virUSBDeviceListCount(list);
> +
> +    for (i = 0; i < count; i++) {
> +        virUSBDevicePtr usb = virUSBDeviceListGet(list, i);
> +        if ((tmp = virUSBDeviceListFind(mgr->activeUsbHostdevs, usb))) {
> +            char *other_drvname = NULL;
> +            char *other_domname = NULL;
> +            virUSBDeviceGetUsedBy(tmp, &other_drvname, &other_domname);
> +
> +            if (other_drvname && other_domname)
> +                virReportError(VIR_ERR_OPERATION_INVALID,
> +                               _("USB device %s is in use by driver %s,domain %s"),
> +                               virUSBDeviceGetName(tmp), other_drvname,
> +                               other_domname);
> +            else
> +                virReportError(VIR_ERR_OPERATION_INVALID,
> +                               _("USB device %s is already in use"),
> +                               virUSBDeviceGetName(tmp));
> +            VIR_FREE(other_drvname);
> +            VIR_FREE(other_domname);
> +            goto error;
> +        }
> +
> +        virUSBDeviceSetUsedBy(usb, drv_name, dom_name);
> +        VIR_DEBUG("Adding %03d.%03d driver= %s dom=%s to activeUsbHostdevs",
> +                  virUSBDeviceGetBus(usb), virUSBDeviceGetDevno(usb),drv_name, dom_name);
> +        /*
> +         * The caller is responsible to steal these usb devices
> +         * from the virUSBDeviceList that passed in on success,
> +         * perform rollback on failure.
> +         */
> +        if (virUSBDeviceListAdd(mgr->activeUsbHostdevs, usb) < 0)
> +            goto error;
> +    }
> +
> +    virObjectUnlock(mgr->activeUsbHostdevs);
> +    return 0;
> +
> +error:
> +    for (j = 0; j < i; j++) {
> +        tmp = virUSBDeviceListGet(list, i);
> +        virUSBDeviceListSteal(mgr->activeUsbHostdevs, tmp);
> +    }
> +    virObjectUnlock(mgr->activeUsbHostdevs);
> +    return -1;
> +}
> +
> +int virHostdevManagerPrepareUsbHostdevs(virHostdevManagerPtr mgr,
> +                                        const char *driver,
> +                                        virDomainDefPtr def,
> +                                        bool coldBoot)
> +{
> +    int i, ret = -1;
> +    virUSBDeviceListPtr list;
> +    virUSBDevicePtr tmp;
> +    virDomainHostdevDefPtr *hostdevs = def->hostdevs;
> +    int nhostdevs = def->nhostdevs;
> +
> +    /* To prevent situation where USB device is assigned to two domains
> +     * we need to keep a list of currently assigned USB devices.
> +     * This is done in several loops which cannot be joined into one
> +     * big loop.
> +     */
> +    if (!(list = virUSBDeviceListNew()))
> +        goto cleanup;
> +
> +    /* Loop 1: build temporary list
> +     */
> +    for (i = 0 ; i < nhostdevs ; i++) {
>   

Extra space before ';'.

> +        virDomainHostdevDefPtr hostdev = hostdevs[i];
> +        bool required = true;
> +        virUSBDevicePtr usb;
> +
> +        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
> +            continue;
> +        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
> +            continue;
> +
> +        if (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_OPTIONAL ||
> +            (hostdev->startupPolicy == VIR_DOMAIN_STARTUP_POLICY_REQUISITE &&
> +             !coldBoot))
> +            required = false;
> +
> +        if (virFindHostdevUSBDevice(hostdev, required, &usb) < 0)
> +            goto cleanup;
> +
> +        if (usb && virUSBDeviceListAdd(list, usb) < 0) {
> +            virUSBDeviceFree(usb);
> +            goto cleanup;
> +        }
> +    }
> +
> +    /* Mark devices in temporary list as used by @name
> +     * and add them do driver list. However, if something goes
> +     * wrong, perform rollback.
> +     */
> +    if (virHostdevManagerMarkUsbHostdevs(mgr, driver, def->name, list) < 0)
> +        goto cleanup;
> +
> +    /* Loop 2: Temporary list was successfully merged with
> +     * driver list, so steal all items to avoid freeing them
> +     * in cleanup label.
> +     */
> +    while (virUSBDeviceListCount(list) > 0) {
> +        tmp = virUSBDeviceListGet(list, 0);
> +        virUSBDeviceListSteal(list, tmp);
> +    }
> +
> +    ret = 0;
> +
> +cleanup:
> +    virObjectUnref(list);
> +    return ret;
> +}
> +
> +int
> +virHostdevManagerPrepareScsiHostdevs(virHostdevManagerPtr mgr,
> +                                    const char *drv_name,
> +                                    const char *dom_name,
> +                                    virDomainHostdevDefPtr *hostdevs,
> +                                    int nhostdevs)
>   

Whitespace off here in the parameter alignment.

> +{
> +    int i, j, count;
> +    virSCSIDeviceListPtr list;
> +    virSCSIDevicePtr tmp;
> +
> +    /* To prevent situation where SCSI device is assigned to two domains
> +     * we need to keep a list of currently assigned SCSI devices.
> +     */
> +    if (!(list = virSCSIDeviceListNew()))
> +        goto cleanup;
> +
> +    /* Loop 1: build temporary list */
> +    for (i = 0 ; i < nhostdevs ; i++) {
>   

Extra space before ';'.

> +        virDomainHostdevDefPtr hostdev = hostdevs[i];
> +        virSCSIDevicePtr scsi;
> +
> +        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
> +            hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
> +            continue;
> +
> +        if (hostdev->managed) {
> +            virReportError(VIR_ERR_XML_ERROR, "%s",
> +                           _("SCSI host device doesn't support managed mode"));
> +            goto cleanup;
> +        }
> +
> +        if (!(scsi = virSCSIDeviceNew(hostdev->source.subsys.u.scsi.adapter,
> +                                      hostdev->source.subsys.u.scsi.bus,
> +                                      hostdev->source.subsys.u.scsi.target,
> +                                      hostdev->source.subsys.u.scsi.unit,
> +                                      hostdev->readonly)))
> +            goto cleanup;
> +
> +        if (scsi && virSCSIDeviceListAdd(list, scsi) < 0) {
> +            virSCSIDeviceFree(scsi);
> +            goto cleanup;
> +        }
> +    }
> +
> +    /* Loop 2: Mark devices in temporary list as used by 
> +     * and add them to driver list. However, if something goes
> +     * wrong, perform rollback.
> +     */
> +    virObjectLock(mgr->activeScsiHostdevs);
> +    count = virSCSIDeviceListCount(list);
> +
> +    for (i = 0; i < count; i++) {
> +        virSCSIDevicePtr scsi = virSCSIDeviceListGet(list, i);
> +        if ((tmp = virSCSIDeviceListFind(mgr->activeScsiHostdevs, scsi))) {
> +            char *other_drvname = NULL;
> +            char *other_domname = NULL;
> +            virSCSIDeviceGetUsedBy(tmp, &other_drvname, &other_domname);
> +
> +            if (other_drvname && other_domname)
> +                virReportError(VIR_ERR_OPERATION_INVALID,
> +                               _("SCSI device %s is in use by driver %s domain %s"),
> +                               virSCSIDeviceGetName(tmp), other_drvname, other_domname);
> +            else
> +                virReportError(VIR_ERR_OPERATION_INVALID,
> +                               _("SCSI device %s is already in use"),
> +                               virSCSIDeviceGetName(tmp));
> +            goto error;
> +        }
> +
> +        virSCSIDeviceSetUsedBy(scsi, drv_name, dom_name);
> +        VIR_DEBUG("Adding %s to activeScsiHostdevs", virSCSIDeviceGetName(scsi));
> +
> +        if (virSCSIDeviceListAdd(mgr->activeScsiHostdevs, scsi) < 0)
> +            goto error;
> +    }
> +
> +    virObjectUnlock(mgr->activeScsiHostdevs);
> +
> +    /* Loop 3: Temporary list was successfully merged with
> +     * driver list, so steal all items to avoid freeing them
> +     * when freeing temporary list.
> +     */
> +    while (virSCSIDeviceListCount(list) > 0) {
> +        tmp = virSCSIDeviceListGet(list, 0);
> +        virSCSIDeviceListSteal(list, tmp);
> +    }
> +
> +    virObjectUnref(list);
> +    return 0;
> +
> +error:
> +    for (j = 0; j < i; j++) {
> +        tmp = virSCSIDeviceListGet(list, i);
> +        virSCSIDeviceListSteal(mgr->activeScsiHostdevs, tmp);
> +    }
> +    virObjectUnlock(mgr->activeScsiHostdevs);
> +cleanup:
> +    virObjectUnref(list);
> +    return -1;
> +}
> +
> +
> +int virHostdevManagerPrepareHostdevs(virHostdevManagerPtr mgr,
> +                                     const char *driver,
> +                                     virDomainDefPtr def,
> +                                     unsigned int flags)
> +{
> +    if (!def->nhostdevs)
> +        return 0;
> +
> +    if (flags & VIR_SP_PCI_HOSTDEV) {
> +        if(virHostdevManagerPreparePciHostdevs(mgr, driver, def->name, def->uuid, 
> +                                 def->hostdevs, def->nhostdevs, flags) < 0)
> +            return -1;
> +    }
> +
> +    if (flags & VIR_SP_USB_HOSTDEV) {
> +        bool coldBoot = (flags & VIR_COLD_BOOT)?true:false;
> +        if(virHostdevManagerPrepareUsbHostdevs(mgr, driver, def, coldBoot) < 0)
> +            return -1;
> +    }
> +
> +    if (flags & VIR_SP_SCSI_HOSTDEV) {
> +        if (virHostdevManagerPrepareScsiHostdevs(mgr, driver, def->name,
> +                                      def->hostdevs, def->nhostdevs) < 0)
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +/*
> + * Pre-condition: mgr->inactivePciHostdevs & mgr->activePciHostdevs
> + * are locked
> + */
> +static void
> +virReattachPciDevice(virHostdevManagerPtr mgr, virPCIDevicePtr dev, const char *driver)
> +{
> +    /* If the device is not managed and was attached to guest
> +     * successfully, it must have been inactive.
> +     */
> +    if (!virPCIDeviceGetManaged(dev)) {
> +        if (virPCIDeviceListAdd(mgr->inactivePciHostdevs, dev) < 0)
> +            virPCIDeviceFree(dev);
> +        return;
> +    }
> +
> +    /* Wait for device cleanup if it is qemu/kvm */
> +    if (STREQ(driver, "QEMU") &&
> +        STREQ(virPCIDeviceGetStubDriver(dev), "pci-stub")) {
> +        int retries = 100;
> +        while (virPCIDeviceWaitForCleanup(dev, "kvm_assigned_device")
> +               && retries) {
> +            usleep(100*1000);
> +            retries--;
> +        }
> +    }
> +
> +    if (virPCIDeviceReattach(dev, mgr->activePciHostdevs,
> +                             mgr->inactivePciHostdevs) < 0) {
> +        virErrorPtr err = virGetLastError();
> +        VIR_ERROR(_("Failed to re-attach PCI device: %s"),
> +                  err ? err->message : _("unknown error"));
> +        virResetError(err);
> +    }
> +    virPCIDeviceFree(dev);
> +}
> +
> +/*
> + * Pre-condition: mgr->activePciHostdevs is locked
> + */
> +static virPCIDeviceListPtr
> +virGetActivePciHostDeviceList(virHostdevManagerPtr mgr,
> +                              virDomainHostdevDefPtr *hostdevs,
> +                              int nhostdevs)
> +{
> +    virPCIDeviceListPtr list;
> +    int i;
> +
> +    if (!(list = virPCIDeviceListNew()))
> +        return NULL;
> +
> +    for (i = 0 ; i < nhostdevs ; i++) {
>   

Extra space before ';'.

> +        virDomainHostdevDefPtr hostdev = hostdevs[i];
> +        virPCIDevicePtr dev;
> +        virPCIDevicePtr activeDev;
> +
> +        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
> +            continue;
> +        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
> +            continue;
> +
> +        dev = virPCIDeviceNew(hostdev->source.subsys.u.pci.addr.domain,
> +                              hostdev->source.subsys.u.pci.addr.bus,
> +                              hostdev->source.subsys.u.pci.addr.slot,
> +                              hostdev->source.subsys.u.pci.addr.function);
> +        if (!dev) {
> +            virObjectUnref(list);
> +            return NULL;
> +        }
> +
> +        if ((activeDev = virPCIDeviceListFind(mgr->activePciHostdevs, dev))) {
> +            if (virPCIDeviceListAdd(list, activeDev) < 0) {
> +                virPCIDeviceFree(dev);
> +                virObjectUnref(list);
> +                return NULL;
> +            }
> +        }
> +
> +        virPCIDeviceFree(dev);
> +    }
> +
> +    return list;
> +}
> +
> +void
> +virHostdevManagerReAttachPciHostdevs(virHostdevManagerPtr mgr,
> +                                          const char *drv_name,
> +                                          const char *dom_name,
> +                                          virDomainHostdevDefPtr *hostdevs,
> +                                          int nhostdevs)
>   

Whitespace off here in the parameter alignment.

> +{
> +    virPCIDeviceListPtr pcidevs;
> +    int i;
> +
> +    virObjectLock(mgr->activePciHostdevs);
> +    virObjectLock(mgr->inactivePciHostdevs);
> +
> +    if (!(pcidevs = virGetActivePciHostDeviceList(mgr,
> +                                                  hostdevs,
> +                                                  nhostdevs))) {
> +        virErrorPtr err = virGetLastError();
> +        VIR_ERROR(_("Failed to allocate PCI device list: %s"),
> +                  err ? err->message : _("unknown error"));
> +        virResetError(err);
> +        goto cleanup;
> +    }
> +
> +    /* Again 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
> +     */
> +    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
> +        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
> +        virPCIDevicePtr activeDev = NULL;
> +
> +        /* Never delete the dev from list driver->activePciHostdevs
> +         * if it's used by other domain.
> +         */
> +        activeDev = virPCIDeviceListFind(mgr->activePciHostdevs, dev);
> +        if (activeDev) {
> +            char *usedby_drvname = NULL;
> +            char *usedby_domname = NULL;
> +            virPCIDeviceGetUsedBy(activeDev, &usedby_drvname, &usedby_domname);
> +            if (STRNEQ_NULLABLE(drv_name, usedby_drvname) &&
> +                STRNEQ_NULLABLE(dom_name, usedby_domname)) {
> +                virPCIDeviceListSteal(pcidevs, dev);
> +                continue;
> +            }
> +            VIR_FREE(usedby_drvname);
> +            VIR_FREE(usedby_domname);
> +        }
> +
> +        /* virObjectUnref() will take care of freeing the dev. */
> +        virPCIDeviceListSteal(mgr->activePciHostdevs, dev);
> +    }
> +
> +    /*
> +     * For SRIOV net host devices, unset mac and port profile before
> +     * reset and reattach device
> +     */
> +    for (i = 0; i < nhostdevs; i++) {
> +         virDomainHostdevDefPtr hostdev = hostdevs[i];
> +         if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
> +             continue;
> +         if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
> +             continue;
> +         if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
> +             hostdev->parent.data.net) {
> +             virDomainHostdevNetConfigRestore(hostdev, mgr->stateDir);
> +         }
> +    }
> +
> +    for (i = 0; i < virPCIDeviceListCount(pcidevs); i++) {
> +        virPCIDevicePtr dev = virPCIDeviceListGet(pcidevs, i);
> +        if (virPCIDeviceReset(dev, mgr->activePciHostdevs,
> +                              mgr->inactivePciHostdevs) < 0) {
> +            virErrorPtr err = virGetLastError();
> +            VIR_ERROR(_("Failed to reset PCI device: %s"),
> +                      err ? err->message : _("unknown error"));
> +            virResetError(err);
> +        }
> +    }
> +
> +    while (virPCIDeviceListCount(pcidevs) > 0) {
> +        virPCIDevicePtr dev = virPCIDeviceListStealIndex(pcidevs, 0);
> +        virReattachPciDevice(mgr, dev, drv_name);
> +    }
> +
> +    virObjectUnref(pcidevs);
> +cleanup:
> +    virObjectUnlock(mgr->activePciHostdevs);
> +    virObjectUnlock(mgr->inactivePciHostdevs);
> +}
> +
> +void
> +virHostdevManagerReAttachUsbHostdevs(virHostdevManagerPtr mgr,
> +                                 const char *drv_name,
> +                                 const char *dom_name,
> +                                 virDomainHostdevDefPtr *hostdevs,
> +                                 int nhostdevs)
>   

Whitespace off here in the parameter alignment.

> +{
> +    int i;
> +
> +    virObjectLock(mgr->activeUsbHostdevs);
> +    for (i = 0; i < nhostdevs; i++) {
> +        virDomainHostdevDefPtr hostdev = hostdevs[i];
> +        virUSBDevicePtr usb, tmp;
> +
> +        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
> +            continue;
> +        if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
> +            continue;
> +        if (hostdev->missing)
> +            continue;
> +
> +        usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus,
> +                              hostdev->source.subsys.u.usb.device,
> +                              NULL);
> +
> +        if (!usb) {
> +            VIR_WARN("Unable to reattach USB device %03d.%03d on driver %s domain %s",
> +                     hostdev->source.subsys.u.usb.bus,
> +                     hostdev->source.subsys.u.usb.device,
> +                     drv_name, dom_name);
> +            continue;
> +        }
> +
> +        /* Delete only those USB devices which belongs
> +         * to domain. Therefore we want to steal only 
> +         * those devices from the list which were taken
> +         * by domain */
> +
> +        tmp = virUSBDeviceListFind(mgr->activeUsbHostdevs, usb);
> +        virUSBDeviceFree(usb);
> +
> +        if (!tmp) {
> +            VIR_WARN("Unable to find device %03d.%03d "
> +                     "in list of active USB devices",
> +                     hostdev->source.subsys.u.usb.bus,
> +                     hostdev->source.subsys.u.usb.device);
> +            continue;
> +        }
> +
> +        char *usedby_drvname = NULL;
> +        char *usedby_domname = NULL;
> +        virUSBDeviceGetUsedBy(tmp, &usedby_drvname, &usedby_domname);
> +        if (STREQ_NULLABLE(drv_name, usedby_drvname) &&
> +            STREQ_NULLABLE(dom_name, usedby_domname)) {
> +            VIR_DEBUG("Removing %03d.%03d dom=%s:%s",
> +                      hostdev->source.subsys.u.usb.bus,
> +                      hostdev->source.subsys.u.usb.device,
> +                      drv_name, dom_name);
> +            virUSBDeviceListDel(mgr->activeUsbHostdevs, tmp);
> +        }
> +        VIR_FREE(usedby_drvname);
> +        VIR_FREE(usedby_domname);
> + 
> +    }
> +    virObjectUnlock(mgr->activeUsbHostdevs);
> +}
> +
> +void
> +virHostdevManagerReAttachScsiHostdevs(virHostdevManagerPtr mgr,
> +                                      const char *drv_name,
> +                                      const char *dom_name,
> +                                      virDomainHostdevDefPtr *hostdevs,
> +                                      int nhostdevs)
> +{
> +    int i;
> +
> +    virObjectLock(mgr->activeScsiHostdevs);
> +    for (i = 0; i < nhostdevs; i++) {
> +        virDomainHostdevDefPtr hostdev = hostdevs[i];
> +        virSCSIDevicePtr scsi, tmp;
> +        char *used_by_drvname;
> +        char *used_by_domname;
> +
> +        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
> +            hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
> +            continue;
> +
> +        if (!(scsi = virSCSIDeviceNew(hostdev->source.subsys.u.scsi.adapter,
> +                                      hostdev->source.subsys.u.scsi.bus,
> +                                      hostdev->source.subsys.u.scsi.target,
> +                                      hostdev->source.subsys.u.scsi.unit,
> +                                      hostdev->readonly))) {
> +            VIR_WARN("Unable to reattach SCSI device %s:%d:%d:%d on driver %s domain %s",
> +                     hostdev->source.subsys.u.scsi.adapter,
> +                     hostdev->source.subsys.u.scsi.bus,
> +                     hostdev->source.subsys.u.scsi.target,
> +                     hostdev->source.subsys.u.scsi.unit,
> +                     drv_name, dom_name);
> +            continue;
> +        }
> +
> +        tmp = virSCSIDeviceListFind(mgr->activeScsiHostdevs, scsi);
> +        virSCSIDeviceFree(scsi);
> +
> +        if (!tmp) {
> +            VIR_WARN("Unable to find device %s:%d:%d:%d "
> +                     "in list of active SCSI devices",
> +                     hostdev->source.subsys.u.scsi.adapter,
> +                     hostdev->source.subsys.u.scsi.bus,
> +                     hostdev->source.subsys.u.scsi.target,
> +                     hostdev->source.subsys.u.scsi.unit);
> +            continue;
> +        }
> +
> +        virSCSIDeviceGetUsedBy(tmp, &used_by_drvname, &used_by_domname);
> +        if (STREQ_NULLABLE(used_by_drvname, drv_name) &&
> +            STREQ_NULLABLE(used_by_domname, dom_name)) {
> +            VIR_DEBUG("Removing %s:%d:%d:%d driver:%s dom:%s from activeScsiHostdevs",
> +                      hostdev->source.subsys.u.scsi.adapter,
> +                      hostdev->source.subsys.u.scsi.bus,
> +                      hostdev->source.subsys.u.scsi.target,
> +                      hostdev->source.subsys.u.scsi.unit,
> +                      drv_name, dom_name);
> +
> +            virSCSIDeviceListDel(mgr->activeScsiHostdevs, tmp);
> +        }
> +    }
> +    virObjectUnlock(mgr->activeScsiHostdevs);
> +}
> +
> +void virHostdevManagerReAttachHostdevs(virHostdevManagerPtr mgr,
> +                                       const char *driver,
> +                                       virDomainDefPtr def,
> +                                       unsigned int flags)
> +{
> +    if (!def->nhostdevs)
> +        return;
> +
> +    if (flags & VIR_SP_PCI_HOSTDEV) {
> +        virHostdevManagerReAttachPciHostdevs(mgr, driver, def->name, def->hostdevs, def->nhostdevs);
> +    }
> +
> +    if (flags & VIR_SP_USB_HOSTDEV) {
> +        virHostdevManagerReAttachUsbHostdevs(mgr, driver, def->name, def->hostdevs, def->nhostdevs);
> +    }
> +
> +    if (flags & VIR_SP_SCSI_HOSTDEV) {
> +        virHostdevManagerReAttachScsiHostdevs(mgr, driver, def->name, def->hostdevs, def->nhostdevs);
> +    }
> +}
> +
> +
> +/*After using any of the above four *Get* APIs, virFreeHostdevNameList should
> + *be called to free memory.
> + */
> +void virFreeHostdevNameList(virHostdevNameListPtr list){
> +    int i;
> +
> +    if (list && list->names) {
> +        for (i = 0; i < list->nnames; i++) {
> +            if (list->names[i])
> +                VIR_FREE(list->names[i]);
> +        }
> +        VIR_FREE(list->names);
> +    }
> +    VIR_FREE(list);
> +}
> +
> +virHostdevNameListPtr
> +virGetActivePciHostdevs(virHostdevManagerPtr mgr)
> +{
> +    int i,count;
> +    virHostdevNameListPtr list = NULL;
> +    virObjectLock(mgr->activePciHostdevs);
> +
> +    count = virPCIDeviceListCount(mgr->activePciHostdevs);
> +    if (count > 0) {
> +        if (VIR_ALLOC_N(list, 1) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +
> +        if (VIR_ALLOC_N(list->names,count) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +        list->nnames = 0;
> +
> +        for (i = 0; i < count; i++) {
> +            virPCIDevicePtr dev = virPCIDeviceListGet(mgr->activePciHostdevs, i);
> +            list->names[list->nnames++] = strdup(virPCIDeviceGetName(dev));
>   

You will need to change this to use VIR_STRDUP().

> +        }
> +    }
> +
> +cleanup:
> +    virFreeHostdevNameList(list);
> +    virObjectUnlock(mgr->activePciHostdevs);
> +    return list;
> +}
> +
> +virHostdevNameListPtr
> +virGetActiveUsbHostdevs(virHostdevManagerPtr mgr)
> +{
> +    int i,count;
>   

int i, count;

> +    virHostdevNameListPtr list = NULL;
> +    virObjectLock(mgr->activeUsbHostdevs);
> +
> +    count = virUSBDeviceListCount(mgr->activeUsbHostdevs);
> +    if (count > 0) {
> +        if (VIR_ALLOC_N(list, 1) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +
> +        if (VIR_ALLOC_N(list->names,count) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +        list->nnames = 0;
> +
> +        for (i = 0; i < count; i++) {
> +            virUSBDevicePtr usb = virUSBDeviceListGet(mgr->activeUsbHostdevs, i);
> +            list->names[list->nnames++] = strdup(virUSBDeviceGetName(usb));
>   

VIR_STRDUP().

> +        }
> +    }
> +
> +cleanup:
> +    virFreeHostdevNameList(list);
> +    virObjectUnlock(mgr->activeUsbHostdevs);
> +    return list;
> +}
> +
> +virHostdevNameListPtr
> +virGetActiveScsiHostdevs(virHostdevManagerPtr mgr)
> +{
> +    int i,count;
> +    virHostdevNameListPtr list = NULL;
> +    virObjectLock(mgr->activeScsiHostdevs);
> +
> +    count = virSCSIDeviceListCount(mgr->activeScsiHostdevs);
> +    if (count > 0) {
> +        if (VIR_ALLOC_N(list, 1) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +
> +        if (VIR_ALLOC_N(list->names,count) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +        list->nnames = 0;
> +
> +        for (i = 0; i < count; i++) {
> +            virSCSIDevicePtr dev = virSCSIDeviceListGet(mgr->activeScsiHostdevs, i);
> +            list->names[list->nnames++] = strdup(virSCSIDeviceGetName(dev));
>   

VIR_STRDUP().

> +        }
> +    }
> +
> +cleanup:
> +    virFreeHostdevNameList(list);
> +    virObjectUnlock(mgr->activeScsiHostdevs);
> +    return list;
> +}
> +
> +virHostdevNameListPtr
> +virGetDomainActivePciHostdevs(virHostdevManagerPtr mgr,
> +                              const char *drv_name,
> +                              const char *dom_name)
> +{
> +    int i;
> +    size_t count;
> +    virHostdevNameListPtr list = NULL;
> +    virObjectLock(mgr->activePciHostdevs);
> +
> +    count = virPCIDeviceListCount(mgr->activePciHostdevs);
> +    if (count > 0) {
> +        if (VIR_ALLOC_N(list, 1) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +
> +        if (VIR_ALLOC_N(list->names,count) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +        list->nnames = 0;
> +
> +        for (i = 0; i < count; i++) {
> +            virPCIDevicePtr dev = virPCIDeviceListGet(mgr->activePciHostdevs, i);
> +            char *usedby_drvname = NULL;
> +            char *usedby_domname = NULL;
> +            virPCIDeviceGetUsedBy(dev, &usedby_drvname, &usedby_domname);
> +            if (STRNEQ(drv_name, usedby_drvname) &&
> +                STRNEQ(dom_name, usedby_domname)) {
> +                list->names[list->nnames++] = strdup(virPCIDeviceGetName(dev));
>   

VIR_STRDUP().

> +            }
> +            VIR_FREE(usedby_drvname);
> +            VIR_FREE(usedby_domname);
> +        }
> +
> +        VIR_SHRINK_N(list->names, count, count - list->nnames);
> +    }
> +
> +cleanup:
> +    virFreeHostdevNameList(list);
> +    virObjectUnlock(mgr->activePciHostdevs);
> +    return list;
> +}
> +
> +virHostdevNameListPtr
> +virGetDomainActiveUsbHostdevs(virHostdevManagerPtr mgr,
> +                              const char *drv_name,
> +                              const char *dom_name)
> +{
> +    int i;
> +    size_t count;
> +    virHostdevNameListPtr list = NULL;
> +    virObjectLock(mgr->activeUsbHostdevs);
> +    
> +    count = virUSBDeviceListCount(mgr->activeUsbHostdevs);
> +    if (count > 0) {
> +        if (VIR_ALLOC_N(list, 1) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +
> +        if (VIR_ALLOC_N(list->names,count) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +        list->nnames = 0;
> +
> +        for (i = 0; i < count; i++) {
> +            virUSBDevicePtr usb = virUSBDeviceListGet(mgr->activeUsbHostdevs, i);
> +            char *usedby_drvname = NULL;
> +            char *usedby_domname = NULL;
> +            virUSBDeviceGetUsedBy(usb, &usedby_drvname, &usedby_domname);
> +            if (STRNEQ(drv_name, usedby_drvname) &&
> +                STRNEQ(dom_name, usedby_domname)) {
> +                list->names[list->nnames++] = strdup(virUSBDeviceGetName(usb));
>   

VIR_STRDUP().

> +            }
> +            VIR_FREE(usedby_drvname);
> +            VIR_FREE(usedby_domname);
> +        }
> +
> +        VIR_SHRINK_N(list->names, count, count - list->nnames);
> +    }
> +
> +cleanup:
> +    virFreeHostdevNameList(list);
> +    virObjectUnlock(mgr->activeUsbHostdevs);
> +    return list;
> +}
> +
> +virHostdevNameListPtr
> +virGetDomainActiveScsiHostdevs(virHostdevManagerPtr mgr,
> +                              const char *drv_name,
> +                              const char *dom_name)
>   

Whitespace off here in the parameter alignment.

> +{
> +    int i;
> +    size_t count;
> +    virHostdevNameListPtr list = NULL;
> +    virObjectLock(mgr->activeScsiHostdevs);
> +    
> +    count = virSCSIDeviceListCount(mgr->activeScsiHostdevs);
> +    if (count > 0) {
> +        if (VIR_ALLOC_N(list, 1) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +
> +        if (VIR_ALLOC_N(list->names,count) < 0) {
> +            virReportError(VIR_ERR_OPERATION_INVALID,
> +                           _("Fail to alloc memory"));
> +            goto cleanup;
> +        }
> +        list->nnames = 0;
> +
> +        for (i = 0; i < count; i++) {
> +            virSCSIDevicePtr dev = virSCSIDeviceListGet(mgr->activeScsiHostdevs, i);
> +            char *usedby_drvname = NULL;
> +            char *usedby_domname = NULL;
> +            virSCSIDeviceGetUsedBy(dev, &usedby_drvname, &usedby_domname);
> +            if (STRNEQ(drv_name, usedby_drvname) &&
> +                STRNEQ(dom_name, usedby_domname)) {
> +                list->names[list->nnames++] = strdup(virSCSIDeviceGetName(dev));
>   

VIR_STRDUP().

> +            }
> +            VIR_FREE(usedby_drvname);
> +            VIR_FREE(usedby_domname);
> +        }
> +
> +        VIR_SHRINK_N(list->names, count, count - list->nnames);
> +    }
> +
> +cleanup:
> +    virFreeHostdevNameList(list);
> +    virObjectUnlock(mgr->activeScsiHostdevs);
> +    return list;
> +}
> diff --git a/src/util/virhostdevmanager.h b/src/util/virhostdevmanager.h
> new file mode 100644
> index 0000000..9f26b9f
> --- /dev/null
> +++ b/src/util/virhostdevmanager.h
> @@ -0,0 +1,109 @@
> +/*
> + * Copyright (C) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library.  If not, see
> + * <http://www.gnu.org/licenses/>.
> + *
> + * Author: Chunyan Liu <cyliu at suse.com>
> + */
> +
> +#ifndef __VIR_HOSTDEV_MANAGER_H__
> +# define __VIR_HOSTDEV_MANAGER_H__
> +
> +# include "internal.h"
> +# include "configmake.h"
> +# include "conf/domain_conf.h"
> +
> +# define HOSTDEV_STATE_DIR LOCALSTATEDIR "/run/libvirt/hostdevmanager"
> +
> +typedef enum {
> +    VIR_SP_PCI_HOSTDEV       = (1 << 0), /* support pci passthrough */
> +    VIR_SP_USB_HOSTDEV       = (1 << 1), /* support usb passthrough */
> +    VIR_SP_SCSI_HOSTDEV      = (1 << 2), /* support scsi passthrough */
> +
> +    VIR_COLD_BOOT            = (1 << 8), /* cold boot */
> +    VIR_STRICT_ACS_CHECK     = (1 << 9), /* strict acs check */
> +} virHostdevManagerFlag;
> +
> +typedef struct _virHostdevManager virHostdevManager;
> +typedef virHostdevManager *virHostdevManagerPtr;
> +
> +struct virHostdevNameList {
> +    char **names;
> +    size_t nnames;
> +};
> +typedef struct virHostdevNameList *virHostdevNameListPtr;
> +
> +int virHostdevManagerInit(void);
> +void virHostdevManagerCleanup(void);
> +virHostdevManagerPtr virHostdevManagerGetDefault(void);
> +
> +int virHostdevManagerPrepareHostdevs(virHostdevManagerPtr mgr,
> +                                     const char *driver,
> +                                     virDomainDefPtr def, 
> +                                     unsigned int flags);
> +void virHostdevManagerReAttachHostdevs(virHostdevManagerPtr mgr,
> +                                       const char *driver,
> +                                       virDomainDefPtr def,
> +                                       unsigned int flags);
> +int virHostdevManagerPreparePciHostdevs(virHostdevManagerPtr mgr,
> +                                        const char *drv_name,
> +                                        const char *dom_name,
> +                                        const unsigned char *uuid,
> +                                        virDomainHostdevDefPtr *hostdevs,
> +                                        int nhostdevs,
> +                                        unsigned int flags);
> +int virHostdevManagerPrepareUsbHostdevs(virHostdevManagerPtr mgr,
> +                                        const char *driver,
> +                                        virDomainDefPtr def,
> +                                        bool coldBoot);
> +int virHostdevManagerPrepareScsiHostdevs(virHostdevManagerPtr mgr,
> +                                         const char *drv_name,
> +                                         const char *dom_name,
> +                                         virDomainHostdevDefPtr *hostdevs,
> +                                         int nhostdevs);
> +void virHostdevManagerReAttachPciHostdevs(virHostdevManagerPtr mgr,
> +                                          const char *drv_name,
> +                                          const char *dom_name,
> +                                          virDomainHostdevDefPtr *hostdevs,
> +                                          int nhostdevs);
> +void virHostdevManagerReAttachUsbHostdevs(virHostdevManagerPtr mgr,
> +                                          const char *drv_name,
> +                                          const char *dom_name,
> +                                          virDomainHostdevDefPtr *hostdevs,
> +                                          int nhostdevs);
> +void virHostdevManagerReAttachScsiHostdevs(virHostdevManagerPtr mgr,
> +                                           const char *drv_name,
> +                                           const char *dom_name,
> +                                           virDomainHostdevDefPtr *hostdevs,
> +                                           int nhostdevs);
> +
> +virHostdevNameListPtr virGetActivePciHostdevs(virHostdevManagerPtr mgr);
> +virHostdevNameListPtr virGetActiveUsbHostdevs(virHostdevManagerPtr mgr);
> +virHostdevNameListPtr virGetActiveScsiHostdevs(virHostdevManagerPtr mgr);
> +virHostdevNameListPtr virGetDomainActivePciHostdevs(virHostdevManagerPtr mgr,
> +                                                    const char *drv_name,
> +                                                    const char *dom_name);
> +virHostdevNameListPtr virGetDomainActiveUsbHostdevs(virHostdevManagerPtr mgr,
> +                                                    const char *drv_name,
> +                                                    const char *dom_name);
> +virHostdevNameListPtr virGetDomainActiveScsiHostdevs(virHostdevManagerPtr mgr,
> +                                                    const char *drv_name,
> +                                                    const char *dom_name);
> +/*After using any of the above four *Get* APIs, virFreeHostdevNameList should
> + *be called to free memory.
> + */
> +void virFreeHostdevNameList(virHostdevNameListPtr list);
> +
> +#endif /* __VIR_HOSTDEV_MANAGER_H__ */
> diff --git a/src/util/virpci.c b/src/util/virpci.c
> index 5865613..7fe0921 100644
> --- a/src/util/virpci.c
> +++ b/src/util/virpci.c
> @@ -62,7 +62,10 @@ struct _virPCIDevice {
>      char          name[PCI_ADDR_LEN]; /* domain:bus:slot.function */
>      char          id[PCI_ID_LEN];     /* product vendor */
>      char          *path;
> -    const char    *used_by;           /* The domain which uses the device */
> +
> +    /* The driver:domain which uses the device */
> +    const char    *used_by_drvname;
> +    const char    *used_by_domname;
>  
>      unsigned int  pcie_cap_pos;
>      unsigned int  pci_pm_cap_pos;
> @@ -1553,15 +1556,17 @@ virPCIDeviceSetReprobe(virPCIDevicePtr dev, bool reprobe)
>  }
>  
>  void
> -virPCIDeviceSetUsedBy(virPCIDevicePtr dev, const char *name)
> +virPCIDeviceSetUsedBy(virPCIDevicePtr dev, const char *drv_name, const char *dom_name)
>  {
> -    dev->used_by = name;
> +    dev->used_by_drvname = drv_name;
> +    dev->used_by_domname = dom_name;
>  }
>  
> -const char *
> -virPCIDeviceGetUsedBy(virPCIDevicePtr dev)
> +void
> +virPCIDeviceGetUsedBy(virPCIDevicePtr dev, char **drv_name, char **dom_name)
>  {
> -    return dev->used_by;
> +    *drv_name = strdup(dev->used_by_drvname);
> +    *dom_name = strdup(dev->used_by_domname);
>   

VIR_STRDUP(). Also, should this function return an int, so callers can
easily check for errors?

>  }
>  
>  void virPCIDeviceReattachInit(virPCIDevicePtr pci)
> diff --git a/src/util/virpci.h b/src/util/virpci.h
> index 7bcadb4..294cb0e 100644
> --- a/src/util/virpci.h
> +++ b/src/util/virpci.h
> @@ -66,8 +66,11 @@ void virPCIDeviceSetStubDriver(virPCIDevicePtr dev,
>                                 const char *driver);
>  const char *virPCIDeviceGetStubDriver(virPCIDevicePtr dev);
>  void virPCIDeviceSetUsedBy(virPCIDevice *dev,
> -                           const char *used_by);
> -const char *virPCIDeviceGetUsedBy(virPCIDevice *dev);
> +                           const char *drv_name,
> +                           const char *dom_name);
> +void virPCIDeviceGetUsedBy(virPCIDevice *dev,
> +                            char **drv_name,
> +                            char **dom_name);
>  unsigned int virPCIDeviceGetUnbindFromStub(virPCIDevicePtr dev);
>  void  virPCIDeviceSetUnbindFromStub(virPCIDevice *dev,
>                                      bool unbind);
> diff --git a/src/util/virscsi.c b/src/util/virscsi.c
> index d6685fa..3993ac4 100644
> --- a/src/util/virscsi.c
> +++ b/src/util/virscsi.c
> @@ -55,7 +55,10 @@ struct _virSCSIDevice {
>      char *name; /* adapter:bus:target:unit */
>      char *id;   /* model:vendor */
>      char *sg_path; /* e.g. /dev/sg2 */
> -    const char *used_by; /* name of the domain using this dev */
> +
> +    /* driver:domain using this dev */
> +    const char *used_by_drvname;
> +    const char *used_by_domname;
>  
>      bool readonly;
>  };
> @@ -234,15 +237,18 @@ virSCSIDeviceFree(virSCSIDevicePtr dev)
>  
>  void
>  virSCSIDeviceSetUsedBy(virSCSIDevicePtr dev,
> -                       const char *name)
> +                       const char *drvname,
> +                       const char *domname)
>  {
> -    dev->used_by = name;
> +    dev->used_by_drvname = drvname;
> +    dev->used_by_domname = domname;
>  }
>  
> -const char *
> -virSCSIDeviceGetUsedBy(virSCSIDevicePtr dev)
> +void
> +virSCSIDeviceGetUsedBy(virSCSIDevicePtr dev, char **drvname, char **domname)
>  {
> -    return dev->used_by;
> +    *drvname = strdup(dev->used_by_drvname);
> +    *domname = strdup(dev->used_by_domname);
>   

Same comment here about VIR_STRDUP() and function returning an int.

>  }
>  
>  const char *
> diff --git a/src/util/virscsi.h b/src/util/virscsi.h
> index 8268cdf..4ae225d 100644
> --- a/src/util/virscsi.h
> +++ b/src/util/virscsi.h
> @@ -45,8 +45,8 @@ virSCSIDevicePtr virSCSIDeviceNew(const char *adapter,
>                                    bool readonly);
>  
>  void virSCSIDeviceFree(virSCSIDevicePtr dev);
> -void virSCSIDeviceSetUsedBy(virSCSIDevicePtr dev, const char *name);
> -const char *virSCSIDeviceGetUsedBy(virSCSIDevicePtr dev);
> +void virSCSIDeviceSetUsedBy(virSCSIDevicePtr dev, const char *drvname, const char *domname);
> +void virSCSIDeviceGetUsedBy(virSCSIDevicePtr dev, char **drvname, char **domname);
>  const char *virSCSIDeviceGetName(virSCSIDevicePtr dev);
>  unsigned int virSCSIDeviceGetAdapter(virSCSIDevicePtr dev);
>  unsigned int virSCSIDeviceGetBus(virSCSIDevicePtr dev);
> diff --git a/src/util/virusb.c b/src/util/virusb.c
> index 27ba9c7..043206e 100644
> --- a/src/util/virusb.c
> +++ b/src/util/virusb.c
> @@ -55,7 +55,10 @@ struct _virUSBDevice {
>      char          name[USB_ADDR_LEN]; /* domain:bus:slot.function */
>      char          id[USB_ID_LEN];     /* product vendor */
>      char          *path;
> -    const char    *used_by;           /* name of the domain using this dev */
> +
> +    /* driver:domain using this dev */
> +    const char    *used_by_drvname;
> +    const char    *used_by_domname;
>  };
>  
>  struct _virUSBDeviceList {
> @@ -383,16 +386,20 @@ virUSBDeviceFree(virUSBDevicePtr dev)
>      VIR_FREE(dev);
>  }
>  
> -
>  void virUSBDeviceSetUsedBy(virUSBDevicePtr dev,
> -                           const char *name)
> +                           const char *drv_name,
> +                           const char *dom_name)
>  {
> -    dev->used_by = name;
> +    dev->used_by_drvname = drv_name;
> +    dev->used_by_domname = dom_name;
>  }
>  
> -const char * virUSBDeviceGetUsedBy(virUSBDevicePtr dev)
> +void virUSBDeviceGetUsedBy(virUSBDevicePtr dev,
> +                           char **drv_name,
> +                           char **dom_name)
>  {
> -    return dev->used_by;
> +    *drv_name = strdup(dev->used_by_drvname);
> +    *dom_name = strdup(dev->used_by_domname);
>   

Same comment here about VIR_STRDUP() and function returning an int.

>  }
>  
>  const char *virUSBDeviceGetName(virUSBDevicePtr dev)
> diff --git a/src/util/virusb.h b/src/util/virusb.h
> index aa59d12..16e48e5 100644
> --- a/src/util/virusb.h
> +++ b/src/util/virusb.h
> @@ -60,8 +60,8 @@ int virUSBDeviceFind(unsigned int vendor,
>                       virUSBDevicePtr *usb);
>  
>  void virUSBDeviceFree(virUSBDevicePtr dev);
> -void virUSBDeviceSetUsedBy(virUSBDevicePtr dev, const char *name);
> -const char *virUSBDeviceGetUsedBy(virUSBDevicePtr dev);
> +void virUSBDeviceSetUsedBy(virUSBDevicePtr dev, const char *drv_name, const char *dom_name);
> +void virUSBDeviceGetUsedBy(virUSBDevicePtr dev, char **drv_name, char **dom_name);
>  const char *virUSBDeviceGetName(virUSBDevicePtr dev);
>  
>  unsigned int virUSBDeviceGetBus(virUSBDevicePtr dev);
>   

FYI, you will have to add the changes to the qemu and LXC drivers to
this patch since each commit should at least compile for bisectability.

Regards,
Jim




More information about the libvir-list mailing list