From nobody Thu May 2 17:31:04 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1542024150924951.4843124380388; Mon, 12 Nov 2018 04:02:30 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 604A3A403F; Mon, 12 Nov 2018 12:02:27 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E604160BE0; Mon, 12 Nov 2018 12:02:26 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 85114181A132; Mon, 12 Nov 2018 12:02:26 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id wACBupGQ003327 for ; Mon, 12 Nov 2018 06:56:51 -0500 Received: by smtp.corp.redhat.com (Postfix) id 0C63E608F8; Mon, 12 Nov 2018 11:56:51 +0000 (UTC) Received: from beluga.usersys.redhat.com (unknown [10.43.2.166]) by smtp.corp.redhat.com (Postfix) with ESMTP id 04FA06090A; Mon, 12 Nov 2018 11:56:46 +0000 (UTC) From: Erik Skultety To: libvir-list@redhat.com Date: Mon, 12 Nov 2018 12:56:41 +0100 Message-Id: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Cc: mprivozn@redhat.com, Erik Skultety Subject: [libvirt] [PATCH v2] conf: Add new module node_device_util X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 12 Nov 2018 12:02:29 +0000 (UTC) Content-Type: text/plain; charset="utf-8" There's a lot of stuff going on in src/conf/nodedev_conf which is sometimes not directly related to config and we're not really consistent with putting only parser/formatter related stuff here, e.g. like we do for domains. So, let's start simply by adding a new module node_device_util containing some of the helpers. Unfortunately, even though these helpers tend to open a secondary driver connection and would be much therefore better suited as a nodedev driver module, we can't do that without pulling headers from the driver into conf/ and that's wrong because we want conf/ to stay driver-agnostic. Signed-off-by: Erik Skultety --- src/conf/Makefile.inc.am | 2 + src/conf/node_device_conf.c | 199 ----------------------- src/conf/node_device_conf.h | 11 -- src/conf/node_device_util.c | 229 +++++++++++++++++++++++++++ src/conf/node_device_util.h | 35 ++++ src/conf/virstorageobj.c | 1 + src/libvirt_private.syms | 7 +- src/node_device/node_device_driver.c | 1 + src/storage/storage_backend_scsi.c | 1 + 9 files changed, 273 insertions(+), 213 deletions(-) create mode 100644 src/conf/node_device_util.c create mode 100644 src/conf/node_device_util.h diff --git a/src/conf/Makefile.inc.am b/src/conf/Makefile.inc.am index af23810640..219ff350d7 100644 --- a/src/conf/Makefile.inc.am +++ b/src/conf/Makefile.inc.am @@ -119,6 +119,8 @@ SECRET_CONF_SOURCES =3D \ NODE_DEVICE_CONF_SOURCES =3D \ conf/node_device_conf.c \ conf/node_device_conf.h \ + conf/node_device_util.c \ + conf/node_device_util.h \ conf/virnodedeviceobj.c \ conf/virnodedeviceobj.h \ $(NULL) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 03bd794dc0..74a7bc3933 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -2220,205 +2220,6 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) } -/* virNodeDeviceGetParentName - * @conn: Connection pointer - * @nodedev_name: Node device to lookup - * - * Lookup the node device by name and return the parent name - * - * Returns parent name on success, caller is responsible for freeing; - * otherwise, returns NULL on failure - */ -char * -virNodeDeviceGetParentName(virConnectPtr conn, - const char *nodedev_name) -{ - virNodeDevicePtr device =3D NULL; - char *parent; - - if (!(device =3D virNodeDeviceLookupByName(conn, nodedev_name))) { - virReportError(VIR_ERR_XML_ERROR, - _("Cannot find '%s' in node device database"), - nodedev_name); - return NULL; - } - - ignore_value(VIR_STRDUP(parent, virNodeDeviceGetParent(device))); - virObjectUnref(device); - - return parent; -} - - -/** - * @fchost: Pointer to vHBA adapter - * - * Create a vHBA for Storage. This code accomplishes this via searching - * through the sysfs for scsi_host/fc_host in order to first ensure some - * vHBA doesn't already exist for the requested wwnn/wwpn (e.g. an unmanag= ed - * vHBA) and to search for the parent vport capable scsi_host by name, - * wwnn/wwpn, or fabric_wwn (if provided). If no parent is provided, then - * a vport capable scsi_host will be selected. - * - * Returns vHBA name on success, NULL on failure with an error message set - */ -char * -virNodeDeviceCreateVport(virStorageAdapterFCHostPtr fchost) -{ - unsigned int parent_host; - char *name =3D NULL; - char *parent_hoststr =3D NULL; - bool skip_capable_check =3D false; - - VIR_DEBUG("parent=3D'%s', wwnn=3D'%s' wwpn=3D'%s'", - NULLSTR(fchost->parent), fchost->wwnn, fchost->wwpn); - - if (fchost->parent) { - if (VIR_STRDUP(parent_hoststr, fchost->parent) < 0) - goto cleanup; - } else if (fchost->parent_wwnn && fchost->parent_wwpn) { - if (!(parent_hoststr =3D virVHBAGetHostByWWN(NULL, fchost->parent_= wwnn, - fchost->parent_wwpn))) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("cannot find parent using provided wwnn/wwpn"= )); - goto cleanup; - } - } else if (fchost->parent_fabric_wwn) { - if (!(parent_hoststr =3D - virVHBAGetHostByFabricWWN(NULL, fchost->parent_fabric_wwn)))= { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("cannot find parent using provided fabric_wwn= ")); - goto cleanup; - } - } else { - if (!(parent_hoststr =3D virVHBAFindVportHost(NULL))) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("'parent' for vHBA not specified, and " - "cannot find one on this host")); - goto cleanup; - } - skip_capable_check =3D true; - } - - if (virSCSIHostGetNumber(parent_hoststr, &parent_host) < 0) - goto cleanup; - - /* NOTE: - * We do not save the parent_hoststr in fchost->parent since - * we could be writing out the 'def' to the saved XML config. - * If we wrote out the name in the XML, then future starts would - * always use the same parent rather than finding the "best available" - * parent. Besides we have a way to determine the parent based on - * the 'name' field. - */ - if (!skip_capable_check && !virVHBAPathExists(NULL, parent_host)) { - virReportError(VIR_ERR_XML_ERROR, - _("parent '%s' specified for vHBA does not exist"), - parent_hoststr); - goto cleanup; - } - - if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, - VPORT_CREATE) < 0) - goto cleanup; - - /* Let's ensure the device was created */ - virWaitForDevices(); - if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn)))= { - ignore_value(virVHBAManageVport(parent_host, fchost->wwpn, fchost-= >wwnn, - VPORT_DELETE)); - goto cleanup; - } - - cleanup: - VIR_FREE(parent_hoststr); - return name; -} - - -/** - * @conn: Connection pointer - * @fchost: Pointer to vHBA adapter - * - * As long as the vHBA is being managed, search for the scsi_host via the - * provided wwnn/wwpn and then find the corresponding parent scsi_host in - * order to send the delete request. - * - * Returns 0 on success, -1 on failure - */ -int -virNodeDeviceDeleteVport(virConnectPtr conn, - virStorageAdapterFCHostPtr fchost) -{ - char *name =3D NULL; - char *scsi_host_name =3D NULL; - unsigned int parent_host; - char *vhba_parent =3D NULL; - int ret =3D -1; - - VIR_DEBUG("conn=3D%p parent=3D'%s', managed=3D'%d' wwnn=3D'%s' wwpn=3D= '%s'", - conn, NULLSTR(fchost->parent), fchost->managed, - fchost->wwnn, fchost->wwpn); - - /* If we're not managing the deletion of the vHBA, then just return */ - if (fchost->managed !=3D VIR_TRISTATE_BOOL_YES) - return 0; - - /* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn= */ - if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn)))= { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to find fc_host for wwnn=3D'%s' and wwpn= =3D'%s'"), - fchost->wwnn, fchost->wwpn); - goto cleanup; - } - - if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0) - goto cleanup; - - /* If at startup time we provided a parent, then use that to - * get the parent_host value; otherwise, we have to determine - * the parent scsi_host which we did not save at startup time - */ - if (fchost->parent) { - /* Someone provided a parent string at startup time that - * was the same as the scsi_host - meaning we have a pool - * backed to an HBA, so there won't be a vHBA to delete */ - if (STREQ(scsi_host_name, fchost->parent)) { - ret =3D 0; - goto cleanup; - } - - if (virSCSIHostGetNumber(fchost->parent, &parent_host) < 0) - goto cleanup; - } else { - if (!(vhba_parent =3D virNodeDeviceGetParentName(conn, scsi_host_n= ame))) - goto cleanup; - - /* If the parent is not a scsi_host, then this is a pool backed - * directly to an HBA and there's no vHBA to remove - so we're don= e */ - if (!STRPREFIX(vhba_parent, "scsi_host")) { - ret =3D 0; - goto cleanup; - } - - if (virSCSIHostGetNumber(vhba_parent, &parent_host) < 0) - goto cleanup; - } - - if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, - VPORT_DELETE) < 0) - goto cleanup; - - ret =3D 0; - - cleanup: - VIR_FREE(name); - VIR_FREE(vhba_parent); - VIR_FREE(scsi_host_name); - return ret; -} - - int virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def) { diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index 685ae30347..fde239183d 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -367,17 +367,6 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps); VIR_CONNECT_LIST_NODE_DEVICES_CAP_MDEV | \ VIR_CONNECT_LIST_NODE_DEVICES_CAP_CCW_DEV) -char * -virNodeDeviceGetParentName(virConnectPtr conn, - const char *nodedev_name); - -char * -virNodeDeviceCreateVport(virStorageAdapterFCHostPtr fchost); - -int -virNodeDeviceDeleteVport(virConnectPtr conn, - virStorageAdapterFCHostPtr fchost); - int virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host); diff --git a/src/conf/node_device_util.c b/src/conf/node_device_util.c new file mode 100644 index 0000000000..d1d9c3ee49 --- /dev/null +++ b/src/conf/node_device_util.c @@ -0,0 +1,229 @@ +/* + * node_device_util.c: helper functions for the node device driver + * + * 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 + * . + */ + +#include + +#include "internal.h" + +#include "node_device_util.h" +#include "virlog.h" +#include "virscsihost.h" +#include "virstring.h" +#include "virvhba.h" + +#define VIR_FROM_THIS VIR_FROM_NODEDEV + +VIR_LOG_INIT("node_device.node_device_util"); + +/* virNodeDeviceGetParentName + * @conn: Connection pointer + * @nodedev_name: Node device to lookup + * + * Lookup the node device by name and return the parent name + * + * Returns parent name on success, caller is responsible for freeing; + * otherwise, returns NULL on failure + */ +char * +virNodeDeviceGetParentName(virConnectPtr conn, + const char *nodedev_name) +{ + virNodeDevicePtr device =3D NULL; + char *parent; + + if (!(device =3D virNodeDeviceLookupByName(conn, nodedev_name))) { + virReportError(VIR_ERR_XML_ERROR, + _("Cannot find '%s' in node device database"), + nodedev_name); + return NULL; + } + + ignore_value(VIR_STRDUP(parent, virNodeDeviceGetParent(device))); + virObjectUnref(device); + + return parent; +} + + +/** + * @fchost: Pointer to vHBA adapter + * + * Create a vHBA for Storage. This code accomplishes this via searching + * through the sysfs for scsi_host/fc_host in order to first ensure some + * vHBA doesn't already exist for the requested wwnn/wwpn (e.g. an unmanag= ed + * vHBA) and to search for the parent vport capable scsi_host by name, + * wwnn/wwpn, or fabric_wwn (if provided). If no parent is provided, then + * a vport capable scsi_host will be selected. + * + * Returns vHBA name on success, NULL on failure with an error message set + */ +char * +virNodeDeviceCreateVport(virStorageAdapterFCHostPtr fchost) +{ + unsigned int parent_host; + char *name =3D NULL; + char *parent_hoststr =3D NULL; + bool skip_capable_check =3D false; + + VIR_DEBUG("parent=3D'%s', wwnn=3D'%s' wwpn=3D'%s'", + NULLSTR(fchost->parent), fchost->wwnn, fchost->wwpn); + + if (fchost->parent) { + if (VIR_STRDUP(parent_hoststr, fchost->parent) < 0) + goto cleanup; + } else if (fchost->parent_wwnn && fchost->parent_wwpn) { + if (!(parent_hoststr =3D virVHBAGetHostByWWN(NULL, fchost->parent_= wwnn, + fchost->parent_wwpn))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("cannot find parent using provided wwnn/wwpn"= )); + goto cleanup; + } + } else if (fchost->parent_fabric_wwn) { + if (!(parent_hoststr =3D + virVHBAGetHostByFabricWWN(NULL, fchost->parent_fabric_wwn)))= { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("cannot find parent using provided fabric_wwn= ")); + goto cleanup; + } + } else { + if (!(parent_hoststr =3D virVHBAFindVportHost(NULL))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("'parent' for vHBA not specified, and " + "cannot find one on this host")); + goto cleanup; + } + skip_capable_check =3D true; + } + + if (virSCSIHostGetNumber(parent_hoststr, &parent_host) < 0) + goto cleanup; + + /* NOTE: + * We do not save the parent_hoststr in fchost->parent since + * we could be writing out the 'def' to the saved XML config. + * If we wrote out the name in the XML, then future starts would + * always use the same parent rather than finding the "best available" + * parent. Besides we have a way to determine the parent based on + * the 'name' field. + */ + if (!skip_capable_check && !virVHBAPathExists(NULL, parent_host)) { + virReportError(VIR_ERR_XML_ERROR, + _("parent '%s' specified for vHBA does not exist"), + parent_hoststr); + goto cleanup; + } + + if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, + VPORT_CREATE) < 0) + goto cleanup; + + /* Let's ensure the device was created */ + virWaitForDevices(); + if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn)))= { + ignore_value(virVHBAManageVport(parent_host, fchost->wwpn, fchost-= >wwnn, + VPORT_DELETE)); + goto cleanup; + } + + cleanup: + VIR_FREE(parent_hoststr); + return name; +} + + +/** + * @conn: Connection pointer + * @fchost: Pointer to vHBA adapter + * + * As long as the vHBA is being managed, search for the scsi_host via the + * provided wwnn/wwpn and then find the corresponding parent scsi_host in + * order to send the delete request. + * + * Returns 0 on success, -1 on failure + */ +int +virNodeDeviceDeleteVport(virConnectPtr conn, + virStorageAdapterFCHostPtr fchost) +{ + char *name =3D NULL; + char *scsi_host_name =3D NULL; + unsigned int parent_host; + char *vhba_parent =3D NULL; + int ret =3D -1; + + VIR_DEBUG("conn=3D%p parent=3D'%s', managed=3D'%d' wwnn=3D'%s' wwpn=3D= '%s'", + conn, NULLSTR(fchost->parent), fchost->managed, + fchost->wwnn, fchost->wwpn); + + /* If we're not managing the deletion of the vHBA, then just return */ + if (fchost->managed !=3D VIR_TRISTATE_BOOL_YES) + return 0; + + /* Find our vHBA by searching the fc_host sysfs tree for our wwnn/wwpn= */ + if (!(name =3D virVHBAGetHostByWWN(NULL, fchost->wwnn, fchost->wwpn)))= { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to find fc_host for wwnn=3D'%s' and wwpn= =3D'%s'"), + fchost->wwnn, fchost->wwpn); + goto cleanup; + } + + if (virAsprintf(&scsi_host_name, "scsi_%s", name) < 0) + goto cleanup; + + /* If at startup time we provided a parent, then use that to + * get the parent_host value; otherwise, we have to determine + * the parent scsi_host which we did not save at startup time + */ + if (fchost->parent) { + /* Someone provided a parent string at startup time that + * was the same as the scsi_host - meaning we have a pool + * backed to an HBA, so there won't be a vHBA to delete */ + if (STREQ(scsi_host_name, fchost->parent)) { + ret =3D 0; + goto cleanup; + } + + if (virSCSIHostGetNumber(fchost->parent, &parent_host) < 0) + goto cleanup; + } else { + if (!(vhba_parent =3D virNodeDeviceGetParentName(conn, scsi_host_n= ame))) + goto cleanup; + + /* If the parent is not a scsi_host, then this is a pool backed + * directly to an HBA and there's no vHBA to remove - so we're don= e */ + if (!STRPREFIX(vhba_parent, "scsi_host")) { + ret =3D 0; + goto cleanup; + } + + if (virSCSIHostGetNumber(vhba_parent, &parent_host) < 0) + goto cleanup; + } + + if (virVHBAManageVport(parent_host, fchost->wwpn, fchost->wwnn, + VPORT_DELETE) < 0) + goto cleanup; + + ret =3D 0; + + cleanup: + VIR_FREE(name); + VIR_FREE(vhba_parent); + VIR_FREE(scsi_host_name); + return ret; +} diff --git a/src/conf/node_device_util.h b/src/conf/node_device_util.h new file mode 100644 index 0000000000..5cb225d03e --- /dev/null +++ b/src/conf/node_device_util.h @@ -0,0 +1,35 @@ +/* + * node_device_util.h: utility functions for node device driver + * + * 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 + * . + */ + +#ifndef __VIR_NODE_DEVICE_UTIL_H__ +# define __VIR_NODE_DEVICE_UTIL_H__ + +# include "conf/storage_adapter_conf.h" + +char * +virNodeDeviceGetParentName(virConnectPtr conn, + const char *nodedev_name); + +char * +virNodeDeviceCreateVport(virStorageAdapterFCHostPtr fchost); + +int +virNodeDeviceDeleteVport(virConnectPtr conn, + virStorageAdapterFCHostPtr fchost); + +#endif /* __VIR_NODE_DEVICE_UTIL_H__ */ diff --git a/src/conf/virstorageobj.c b/src/conf/virstorageobj.c index 0b3ba84af2..30aabb2b37 100644 --- a/src/conf/virstorageobj.c +++ b/src/conf/virstorageobj.c @@ -22,6 +22,7 @@ #include "datatypes.h" #include "node_device_conf.h" +#include "node_device_util.h" #include "virstorageobj.h" #include "viralloc.h" diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 335210c31d..2343a757c1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -722,14 +722,11 @@ virNodeDevCapsDefFree; virNodeDevCapTypeFromString; virNodeDevCapTypeToString; virNodeDeviceCapsListExport; -virNodeDeviceCreateVport; virNodeDeviceDefFormat; virNodeDeviceDefFree; virNodeDeviceDefParseFile; virNodeDeviceDefParseNode; virNodeDeviceDefParseString; -virNodeDeviceDeleteVport; -virNodeDeviceGetParentName; virNodeDeviceGetPCIDynamicCaps; virNodeDeviceGetSCSIHostCaps; virNodeDeviceGetSCSITargetCaps; @@ -742,6 +739,10 @@ virNodeDeviceEventLifecycleNew; virNodeDeviceEventStateRegisterID; virNodeDeviceEventUpdateNew; +# conf/node_device_util.h +virNodeDeviceCreateVport; +virNodeDeviceDeleteVport; +virNodeDeviceGetParentName; # conf/numa_conf.h virDomainMemoryAccessTypeFromString; diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_de= vice_driver.c index c46d0fbe12..0bcb3de053 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -37,6 +37,7 @@ #include "node_device_event.h" #include "node_device_driver.h" #include "node_device_hal.h" +#include "node_device_util.h" #include "virvhba.h" #include "viraccessapicheck.h" #include "virnetdev.h" diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backe= nd_scsi.c index 7c927c4d95..fe3a1e36ac 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -35,6 +35,7 @@ #include "virstring.h" #include "storage_util.h" #include "node_device_conf.h" +#include "node_device_util.h" #include "driver.h" #define VIR_FROM_THIS VIR_FROM_STORAGE -- 2.19.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list