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(a)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(a)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(a)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