[libvirt] [PATCH v4 3/9] util: Management routines for scsi_host devices

Eric Farman farman at linux.vnet.ibm.com
Tue Nov 22 03:58:17 UTC 2016


For a new hostdev type='scsi_host' we have a number of
required functions for managing, adding, and removing the
host device to/from guests.  Provide the basic infrastructure
for these tasks.

The name "SCSIVHost" (and its variants) is chosen to avoid
conflicts with existing code named "SCSIHost" to refer to
a hostdev type='scsi' protcol='none'.

Signed-off-by: Eric Farman <farman at linux.vnet.ibm.com>
---
 po/POTFILES.in           |   1 +
 src/Makefile.am          |   1 +
 src/libvirt_private.syms |  18 +++
 src/util/virhostdev.c    | 163 +++++++++++++++++++++++++++
 src/util/virhostdev.h    |  16 +++
 src/util/virscsivhost.c  | 288 +++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virscsivhost.h  |  65 +++++++++++
 tests/qemuxml2argvmock.c |   9 ++
 8 files changed, 561 insertions(+)
 create mode 100644 src/util/virscsivhost.c
 create mode 100644 src/util/virscsivhost.h

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 25867ae..bdff679 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -237,6 +237,7 @@ src/util/virqemu.c
 src/util/virrandom.c
 src/util/virrotatingfile.c
 src/util/virscsi.c
+src/util/virscsivhost.c
 src/util/virsecret.c
 src/util/virsexpr.c
 src/util/virsocketaddr.c
diff --git a/src/Makefile.am b/src/Makefile.am
index aaba9e6..a0e5e92 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -163,6 +163,7 @@ UTIL_SOURCES =							\
 		util/virrandom.h util/virrandom.c		\
 		util/virrotatingfile.h util/virrotatingfile.c   \
 		util/virscsi.c util/virscsi.h			\
+		util/virscsivhost.c util/virscsivhost.h		\
 		util/virseclabel.c util/virseclabel.h		\
 		util/virsecret.c util/virsecret.h		\
 		util/virsexpr.c util/virsexpr.h			\
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index baff82b..46b4e87 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1684,10 +1684,12 @@ virHostdevPCINodeDeviceReset;
 virHostdevPrepareDomainDevices;
 virHostdevPreparePCIDevices;
 virHostdevPrepareSCSIDevices;
+virHostdevPrepareSCSIVHostDevices;
 virHostdevPrepareUSBDevices;
 virHostdevReAttachDomainDevices;
 virHostdevReAttachPCIDevices;
 virHostdevReAttachSCSIDevices;
+virHostdevReAttachSCSIVHostDevices;
 virHostdevReAttachUSBDevices;
 virHostdevUpdateActiveDomainDevices;
 virHostdevUpdateActivePCIDevices;
@@ -2305,6 +2307,22 @@ virSCSIDeviceNew;
 virSCSIDeviceSetUsedBy;
 
 
+# util/virscsivhost.h
+virSCSIVHostDeviceFileIterate;
+virSCSIVHostDeviceFree;
+virSCSIVHostDeviceGetName;
+virSCSIVHostDeviceListAdd;
+virSCSIVHostDeviceListCount;
+virSCSIVHostDeviceListDel;
+virSCSIVHostDeviceListFind;
+virSCSIVHostDeviceListGet;
+virSCSIVHostDeviceListNew;
+virSCSIVHostDeviceListSteal;
+virSCSIVHostDeviceNew;
+virSCSIVHostDeviceSetUsedBy;
+virSCSIVHostOpenVhostSCSI;
+
+
 # util/virseclabel.h
 virSecurityDeviceLabelDefFree;
 virSecurityDeviceLabelDefNew;
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
index 9c2262e..ca4c339 100644
--- a/src/util/virhostdev.c
+++ b/src/util/virhostdev.c
@@ -146,6 +146,7 @@ virHostdevManagerDispose(void *obj)
     virObjectUnref(hostdevMgr->inactivePCIHostdevs);
     virObjectUnref(hostdevMgr->activeUSBHostdevs);
     virObjectUnref(hostdevMgr->activeSCSIHostdevs);
+    virObjectUnref(hostdevMgr->activeSCSIVHostHostdevs);
     VIR_FREE(hostdevMgr->stateDir);
 }
 
@@ -170,6 +171,9 @@ virHostdevManagerNew(void)
     if (!(hostdevMgr->activeSCSIHostdevs = virSCSIDeviceListNew()))
         goto error;
 
+    if (!(hostdevMgr->activeSCSIVHostHostdevs = virSCSIVHostDeviceListNew()))
+        goto error;
+
     if (privileged) {
         if (VIR_STRDUP(hostdevMgr->stateDir, HOSTDEV_STATE_DIR) < 0)
             goto error;
@@ -1472,6 +1476,102 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr mgr,
     return -1;
 }
 
+int
+virHostdevPrepareSCSIVHostDevices(virHostdevManagerPtr mgr,
+                                  const char *drv_name,
+                                  const char *dom_name,
+                                  virDomainHostdevDefPtr *hostdevs,
+                                  int nhostdevs)
+{
+    size_t i, j;
+    int count;
+    virSCSIVHostDeviceListPtr list;
+    virSCSIVHostDevicePtr host, tmp;
+
+    if (!nhostdevs)
+        return 0;
+
+    /* To prevent situation where scsi_host device is assigned to two domains
+     * we need to keep a list of currently assigned scsi_host devices.
+     * This is done in several loops which cannot be joined into one big
+     * loop. See virHostdevPreparePCIDevices()
+     */
+    if (!(list = virSCSIVHostDeviceListNew()))
+        goto cleanup;
+
+    /* Loop 1: build temporary list */
+    for (i = 0; i < nhostdevs; i++) {
+        virDomainHostdevDefPtr hostdev = hostdevs[i];
+        virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host;
+
+        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+            hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST)
+            continue;
+
+        if (hostsrc->protocol != VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST)
+            continue;  /* Not supported */
+
+        if (!(host = virSCSIVHostDeviceNew(hostsrc->wwpn)))
+            goto cleanup;
+
+        if (virSCSIVHostDeviceListAdd(list, host) < 0) {
+            virSCSIVHostDeviceFree(host);
+            goto cleanup;
+        }
+    }
+
+    /* Loop 2: Mark devices in temporary list as used by @name
+     * and add them to driver list. However, if something goes
+     * wrong, perform rollback.
+     */
+    virObjectLock(mgr->activeSCSIVHostHostdevs);
+    count = virSCSIVHostDeviceListCount(list);
+
+    for (i = 0; i < count; i++) {
+        host = virSCSIVHostDeviceListGet(list, i);
+        if ((tmp = virSCSIVHostDeviceListFind(mgr->activeSCSIVHostHostdevs,
+                                              host))) {
+            virReportError(VIR_ERR_OPERATION_INVALID,
+                           _("SCSI_host device %s is already in use by "
+                             "another domain"),
+                           virSCSIVHostDeviceGetName(tmp));
+            goto error;
+        } else {
+            if (virSCSIVHostDeviceSetUsedBy(host, drv_name, dom_name) < 0)
+                goto error;
+
+            VIR_DEBUG("Adding %s to activeSCSIVHostHostdevs",
+                      virSCSIVHostDeviceGetName(host));
+
+            if (virSCSIVHostDeviceListAdd(mgr->activeSCSIVHostHostdevs, host) < 0)
+                goto error;
+        }
+    }
+
+    virObjectUnlock(mgr->activeSCSIVHostHostdevs);
+
+    /* Loop 3: Temporary list was successfully merged with
+     * driver list, so steal all items to avoid freeing them
+     * when freeing temporary list.
+     */
+    while (virSCSIVHostDeviceListCount(list) > 0) {
+        tmp = virSCSIVHostDeviceListGet(list, 0);
+        virSCSIVHostDeviceListSteal(list, tmp);
+    }
+
+    virObjectUnref(list);
+    return 0;
+ error:
+    for (j = 0; j < i; j++) {
+        tmp = virSCSIVHostDeviceListGet(list, i);
+        virSCSIVHostDeviceListSteal(mgr->activeSCSIVHostHostdevs, tmp);
+    }
+    virObjectUnlock(mgr->activeSCSIVHostHostdevs);
+ cleanup:
+    virObjectUnref(list);
+    return -1;
+}
+
 void
 virHostdevReAttachUSBDevices(virHostdevManagerPtr mgr,
                              const char *drv_name,
@@ -1604,6 +1704,69 @@ virHostdevReAttachSCSIDevices(virHostdevManagerPtr mgr,
     virObjectUnlock(mgr->activeSCSIHostdevs);
 }
 
+void
+virHostdevReAttachSCSIVHostDevices(virHostdevManagerPtr mgr,
+                                   const char *drv_name,
+                                   const char *dom_name,
+                                   virDomainHostdevDefPtr *hostdevs,
+                                   int nhostdevs)
+{
+    size_t i;
+    virSCSIVHostDevicePtr host, tmp;
+
+
+    if (!nhostdevs)
+        return;
+
+    virObjectLock(mgr->activeSCSIVHostHostdevs);
+    for (i = 0; i < nhostdevs; i++) {
+        virDomainHostdevDefPtr hostdev = hostdevs[i];
+        virDomainHostdevSubsysSCSIVHostPtr hostsrc = &hostdev->source.subsys.u.scsi_host;
+        const char *usedby_drvname;
+        const char *usedby_domname;
+
+        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
+            hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST)
+            continue;
+
+        if (hostsrc->protocol != VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST)
+            continue; /* Not supported */
+
+        if (!(host = virSCSIVHostDeviceNew(hostsrc->wwpn))) {
+            VIR_WARN("Unable to reattach SCSI_host device %s on domain %s",
+                     hostsrc->wwpn, dom_name);
+            virObjectUnlock(mgr->activeSCSIVHostHostdevs);
+            return;
+        }
+
+        /* Only delete the devices which are marked as being used by @name,
+         * because qemuProcessStart could fail half way through. */
+
+        if (!(tmp = virSCSIVHostDeviceListFind(mgr->activeSCSIVHostHostdevs,
+                                               host))) {
+            VIR_WARN("Unable to find device %s "
+                     "in list of active SCSI_host devices",
+                     hostsrc->wwpn);
+            virSCSIVHostDeviceFree(host);
+            virObjectUnlock(mgr->activeSCSIVHostHostdevs);
+            return;
+        }
+
+        virSCSIVHostDeviceGetUsedBy(tmp, &usedby_drvname, &usedby_domname);
+
+        if (STREQ_NULLABLE(drv_name, usedby_drvname) &&
+            STREQ_NULLABLE(dom_name, usedby_domname)) {
+            VIR_DEBUG("Removing %s dom=%s from activeSCSIVHostHostdevs",
+                       hostsrc->wwpn, dom_name);
+
+            virSCSIVHostDeviceListDel(mgr->activeSCSIVHostHostdevs, tmp);
+        }
+
+        virSCSIVHostDeviceFree(host);
+    }
+    virObjectUnlock(mgr->activeSCSIVHostHostdevs);
+}
+
 int
 virHostdevPCINodeDeviceDetach(virHostdevManagerPtr mgr,
                               virPCIDevicePtr pci)
diff --git a/src/util/virhostdev.h b/src/util/virhostdev.h
index f2f51bd..1330cbc 100644
--- a/src/util/virhostdev.h
+++ b/src/util/virhostdev.h
@@ -30,6 +30,7 @@
 # include "virpci.h"
 # include "virusb.h"
 # include "virscsi.h"
+# include "virscsivhost.h"
 # include "domain_conf.h"
 
 typedef enum {
@@ -53,6 +54,7 @@ struct _virHostdevManager {
     virPCIDeviceListPtr inactivePCIHostdevs;
     virUSBDeviceListPtr activeUSBHostdevs;
     virSCSIDeviceListPtr activeSCSIHostdevs;
+    virSCSIVHostDeviceListPtr activeSCSIVHostHostdevs;
 };
 
 virHostdevManagerPtr virHostdevManagerGetDefault(void);
@@ -87,6 +89,13 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr,
                              virDomainHostdevDefPtr *hostdevs,
                              int nhostdevs)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+int
+virHostdevPrepareSCSIVHostDevices(virHostdevManagerPtr hostdev_mgr,
+                                  const char *drv_name,
+                                  const char *dom_name,
+                                  virDomainHostdevDefPtr *hostdevs,
+                                  int nhostdevs)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
 void
 virHostdevReAttachPCIDevices(virHostdevManagerPtr hostdev_mgr,
                              const char *drv_name,
@@ -109,6 +118,13 @@ virHostdevReAttachSCSIDevices(virHostdevManagerPtr hostdev_mgr,
                               virDomainHostdevDefPtr *hostdevs,
                               int nhostdevs)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+void
+virHostdevReAttachSCSIVHostDevices(virHostdevManagerPtr hostdev_mgr,
+                                   const char *drv_name,
+                                   const char *dom_name,
+                                   virDomainHostdevDefPtr *hostdevs,
+                                   int nhostdevs)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
 int
 virHostdevUpdateActivePCIDevices(virHostdevManagerPtr mgr,
                                  virDomainHostdevDefPtr *hostdevs,
diff --git a/src/util/virscsivhost.c b/src/util/virscsivhost.c
new file mode 100644
index 0000000..9d18b6e
--- /dev/null
+++ b/src/util/virscsivhost.c
@@ -0,0 +1,288 @@
+/*
+ * virscsivhost.c: helper APIs for managing scsi_host devices
+ *
+ * Copyright (C) 2016 IBM Corporation
+ *
+ * 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/>.
+ *
+ * Authors:
+ *     Eric Farman <farman at linux.vnet.ibm.com>
+ */
+
+#include <config.h>
+#include <fcntl.h>
+
+#include "virscsivhost.h"
+#include "virlog.h"
+#include "viralloc.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virstring.h"
+
+VIR_LOG_INIT("util.scsihost");
+
+#define SYSFS_VHOST_SCSI_DEVICES "/sys/kernel/config/target/vhost/"
+#define VHOST_SCSI_DEVICE "/dev/vhost-scsi"
+
+struct _virSCSIVHostDevice {
+    char *name; /* naa.<wwn> */
+    char *path;
+    char *used_by_drvname;
+    char *used_by_domname;
+};
+
+struct _virSCSIVHostDeviceList {
+    virObjectLockable parent;
+    size_t count;
+    virSCSIVHostDevicePtr *devs;
+};
+
+static virClassPtr virSCSIVHostDeviceListClass;
+
+static void
+virSCSIVHostDeviceListDispose(void *obj)
+{
+    virSCSIVHostDeviceListPtr list = obj;
+    size_t i;
+
+    for (i = 0; i < list->count; i++)
+        virSCSIVHostDeviceFree(list->devs[i]);
+
+    VIR_FREE(list->devs);
+}
+
+
+static int
+virSCSIVHostOnceInit(void)
+{
+    if (!(virSCSIVHostDeviceListClass = virClassNew(virClassForObjectLockable(),
+                                                    "virSCSIVHostDeviceList",
+                                                    sizeof(virSCSIVHostDeviceList),
+                                                    virSCSIVHostDeviceListDispose)))
+        return -1;
+
+    return 0;
+}
+
+
+VIR_ONCE_GLOBAL_INIT(virSCSIVHost)
+
+/* For virReportOOMError()  and virReportSystemError() */
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+
+int
+virSCSIVHostOpenVhostSCSI(int *vhostfd)
+{
+    if (!virFileExists(VHOST_SCSI_DEVICE))
+        goto error;
+
+    *vhostfd = open(VHOST_SCSI_DEVICE, O_RDWR);
+
+    if (*vhostfd < 0) {
+        virReportSystemError(errno, _("Failed to open %s"), VHOST_SCSI_DEVICE);
+        goto error;
+    }
+
+    return 0;
+
+ error:
+    VIR_FORCE_CLOSE(*vhostfd);
+
+    return -1;
+}
+
+
+void
+virSCSIVHostDeviceListDel(virSCSIVHostDeviceListPtr list,
+                          virSCSIVHostDevicePtr dev)
+{
+    virSCSIVHostDevicePtr tmp = virSCSIVHostDeviceListSteal(list, dev);
+    virSCSIVHostDeviceFree(tmp);
+}
+
+
+static int
+virSCSIVHostDeviceListFindIndex(virSCSIVHostDeviceListPtr list,
+                                virSCSIVHostDevicePtr dev)
+{
+    size_t i;
+
+    for (i = 0; i < list->count; i++) {
+        virSCSIVHostDevicePtr other = list->devs[i];
+        if (STREQ_NULLABLE(other->name, dev->name))
+            return i;
+    }
+    return -1;
+}
+
+
+virSCSIVHostDevicePtr
+virSCSIVHostDeviceListGet(virSCSIVHostDeviceListPtr list, int idx)
+{
+    if (idx >= list->count || idx < 0)
+        return NULL;
+
+    return list->devs[idx];
+}
+
+
+size_t
+virSCSIVHostDeviceListCount(virSCSIVHostDeviceListPtr list)
+{
+    return list->count;
+}
+
+
+virSCSIVHostDevicePtr
+virSCSIVHostDeviceListSteal(virSCSIVHostDeviceListPtr list,
+                            virSCSIVHostDevicePtr dev)
+{
+    virSCSIVHostDevicePtr ret = NULL;
+    size_t i;
+
+    for (i = 0; i < list->count; i++) {
+        if (STREQ_NULLABLE(list->devs[i]->name, dev->name)) {
+            ret = list->devs[i];
+            VIR_DELETE_ELEMENT(list->devs, i, list->count);
+            break;
+        }
+    }
+
+    return ret;
+}
+
+
+virSCSIVHostDevicePtr
+virSCSIVHostDeviceListFind(virSCSIVHostDeviceListPtr list,
+                           virSCSIVHostDevicePtr dev)
+{
+    int idx;
+
+    if ((idx = virSCSIVHostDeviceListFindIndex(list, dev)) >= 0)
+        return list->devs[idx];
+    else
+        return NULL;
+}
+
+
+int
+virSCSIVHostDeviceListAdd(virSCSIVHostDeviceListPtr list,
+                          virSCSIVHostDevicePtr dev)
+{
+    if (virSCSIVHostDeviceListFind(list, dev)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Device %s is already in use"), dev->name);
+        return -1;
+    }
+    return VIR_APPEND_ELEMENT(list->devs, list->count, dev);
+}
+
+
+virSCSIVHostDeviceListPtr
+virSCSIVHostDeviceListNew(void)
+{
+    if (virSCSIVHostInitialize() < 0)
+        return NULL;
+
+    return virObjectLockableNew(virSCSIVHostDeviceListClass);
+}
+
+
+int
+virSCSIVHostDeviceSetUsedBy(virSCSIVHostDevicePtr dev,
+                            const char *drvname,
+                            const char *domname)
+{
+    VIR_FREE(dev->used_by_drvname);
+    VIR_FREE(dev->used_by_domname);
+    if (VIR_STRDUP(dev->used_by_drvname, drvname) < 0)
+        return -1;
+    if (VIR_STRDUP(dev->used_by_domname, domname) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+void
+virSCSIVHostDeviceGetUsedBy(virSCSIVHostDevicePtr dev,
+                            const char **drv_name,
+                            const char **dom_name)
+{
+    *drv_name = dev->used_by_drvname;
+    *dom_name = dev->used_by_domname;
+ }
+
+
+int
+virSCSIVHostDeviceFileIterate(virSCSIVHostDevicePtr dev,
+                              virSCSIVHostDeviceFileActor actor,
+                              void *opaque)
+{
+    return (actor)(dev, dev->path, opaque);
+}
+
+
+const char *
+virSCSIVHostDeviceGetName(virSCSIVHostDevicePtr dev)
+{
+    return dev->name;
+}
+
+
+virSCSIVHostDevicePtr
+virSCSIVHostDeviceNew(const char *name)
+{
+    virSCSIVHostDevicePtr dev;
+
+    if (VIR_ALLOC(dev) < 0)
+        return NULL;
+
+    if (VIR_STRDUP(dev->name, name) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("dev->name buffer overflow: %s"),
+                       name);
+        goto error;
+    }
+
+    if (virAsprintf(&dev->path, "%s/%s",
+                    SYSFS_VHOST_SCSI_DEVICES, name) < 0)
+        goto cleanup;
+
+    VIR_DEBUG("%s: initialized", dev->name);
+
+ cleanup:
+    return dev;
+
+ error:
+    virSCSIVHostDeviceFree(dev);
+    dev = NULL;
+    goto cleanup;
+}
+
+
+void
+virSCSIVHostDeviceFree(virSCSIVHostDevicePtr dev)
+{
+    if (!dev)
+        return;
+    VIR_DEBUG("%s: freeing", dev->name);
+    VIR_FREE(dev->name);
+    VIR_FREE(dev->path);
+    VIR_FREE(dev->used_by_drvname);
+    VIR_FREE(dev->used_by_domname);
+    VIR_FREE(dev);
+}
diff --git a/src/util/virscsivhost.h b/src/util/virscsivhost.h
new file mode 100644
index 0000000..1a52acf
--- /dev/null
+++ b/src/util/virscsivhost.h
@@ -0,0 +1,65 @@
+/*
+ * virscsivhost.h: helper APIs for managing host scsi_host devices
+ *
+ * Copyright (C) 2016 IBM Corporation
+ *
+ * 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/>.
+ *
+ * Authors:
+ *     Eric Farman <farman at linux.vnet.ibm.com>
+ */
+
+#ifndef __VIR_SCSIHOST_H__
+# define __VIR_SCSIHOST_H__
+
+# include "internal.h"
+# include "virobject.h"
+# include "virutil.h"
+
+typedef struct _virSCSIVHostDevice virSCSIVHostDevice;
+typedef virSCSIVHostDevice *virSCSIVHostDevicePtr;
+typedef struct _virSCSIVHostDeviceList virSCSIVHostDeviceList;
+typedef virSCSIVHostDeviceList *virSCSIVHostDeviceListPtr;
+
+typedef int (*virSCSIVHostDeviceFileActor)(virSCSIVHostDevicePtr dev,
+                                           const char *name, void *opaque);
+
+int virSCSIVHostDeviceFileIterate(virSCSIVHostDevicePtr dev,
+                                  virSCSIVHostDeviceFileActor actor,
+                                  void *opaque);
+const char *virSCSIVHostDeviceGetName(virSCSIVHostDevicePtr dev);
+virSCSIVHostDevicePtr virSCSIVHostDeviceListGet(virSCSIVHostDeviceListPtr list,
+                                                int idx);
+size_t virSCSIVHostDeviceListCount(virSCSIVHostDeviceListPtr list);
+virSCSIVHostDevicePtr virSCSIVHostDeviceListSteal(virSCSIVHostDeviceListPtr list,
+                                                  virSCSIVHostDevicePtr dev);
+virSCSIVHostDevicePtr virSCSIVHostDeviceListFind(virSCSIVHostDeviceListPtr list,
+                                                 virSCSIVHostDevicePtr dev);
+int  virSCSIVHostDeviceListAdd(virSCSIVHostDeviceListPtr list,
+                               virSCSIVHostDevicePtr dev);
+void virSCSIVHostDeviceListDel(virSCSIVHostDeviceListPtr list,
+                               virSCSIVHostDevicePtr dev);
+virSCSIVHostDeviceListPtr virSCSIVHostDeviceListNew(void);
+virSCSIVHostDevicePtr virSCSIVHostDeviceNew(const char *name);
+int virSCSIVHostDeviceSetUsedBy(virSCSIVHostDevicePtr dev,
+                                const char *drvname,
+                                const char *domname);
+void virSCSIVHostDeviceGetUsedBy(virSCSIVHostDevicePtr dev,
+                                 const char **drv_name,
+                                 const char **dom_name);
+void virSCSIVHostDeviceFree(virSCSIVHostDevicePtr dev);
+int virSCSIVHostOpenVhostSCSI(int *vhostfd);
+
+#endif /* __VIR_SCSIHOST_H__ */
diff --git a/tests/qemuxml2argvmock.c b/tests/qemuxml2argvmock.c
index 78a224b..c501b59 100644
--- a/tests/qemuxml2argvmock.c
+++ b/tests/qemuxml2argvmock.c
@@ -31,6 +31,7 @@
 #include "virnuma.h"
 #include "virrandom.h"
 #include "virscsi.h"
+#include "virscsivhost.h"
 #include "virstring.h"
 #include "virtpm.h"
 #include "virutil.h"
@@ -107,6 +108,14 @@ virSCSIDeviceGetSgName(const char *sysfs_prefix ATTRIBUTE_UNUSED,
 }
 
 int
+virSCSIVHostOpenVhostSCSI(int *vhostfd)
+{
+    *vhostfd = STDERR_FILENO + 1;
+
+    return 0;
+}
+
+int
 virNetDevTapCreate(char **ifname,
                    const char *tunpath ATTRIBUTE_UNUSED,
                    int *tapfd,
-- 
1.9.1




More information about the libvir-list mailing list