From 629544be0feb87a5503466f55d4b9d5803a53b26 Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Mon, 21 Nov 2016 22:58:17 -0500 Subject: [PATCH] util: Management routines for scsi_host devices 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 --- 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 25867aef83..bdff67906a 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 b358e0ee1f..d440548bef 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 b7d26fda94..a04ba23d3d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1685,10 +1685,12 @@ virHostdevPCINodeDeviceReset; virHostdevPrepareDomainDevices; virHostdevPreparePCIDevices; virHostdevPrepareSCSIDevices; +virHostdevPrepareSCSIVHostDevices; virHostdevPrepareUSBDevices; virHostdevReAttachDomainDevices; virHostdevReAttachPCIDevices; virHostdevReAttachSCSIDevices; +virHostdevReAttachSCSIVHostDevices; virHostdevReAttachUSBDevices; virHostdevUpdateActiveDomainDevices; virHostdevUpdateActivePCIDevices; @@ -2306,6 +2308,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 ee81ca9042..0673afb7b6 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; @@ -1484,6 +1488,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, @@ -1615,6 +1715,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 aa056ebcea..4c1fea3ef1 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 0000000000..f32d647ebf --- /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 + * . + * + * Authors: + * Eric Farman + */ + +#include +#include + +#include "virscsivhost.h" +#include "virlog.h" +#include "viralloc.h" +#include "virerror.h" +#include "virfile.h" +#include "virstring.h" + +/* For virReportOOMError() and virReportSystemError() */ +#define VIR_FROM_THIS VIR_FROM_NONE + +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. */ + 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) + + +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 error; + + 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 0000000000..1a52acf02e --- /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 + * . + * + * Authors: + * Eric Farman + */ + +#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 78a224bd50..c501b59acb 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" @@ -106,6 +107,14 @@ virSCSIDeviceGetSgName(const char *sysfs_prefix ATTRIBUTE_UNUSED, return ret; } +int +virSCSIVHostOpenVhostSCSI(int *vhostfd) +{ + *vhostfd = STDERR_FILENO + 1; + + return 0; +} + int virNetDevTapCreate(char **ifname, const char *tunpath ATTRIBUTE_UNUSED,