Create a virscsihost.c and place the functions there. That removes the last #ifdef __linux__ from virutil.c. Take the opporunity to also change the function names and in one case the parameters slightly Signed-off-by: John Ferlan <jferlan@xxxxxxxxxx> --- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/conf/storage_conf.c | 34 ++-- src/libvirt_private.syms | 10 +- src/node_device/node_device_linux_sysfs.c | 5 +- src/storage/storage_backend_scsi.c | 15 +- src/util/virscsihost.c | 297 ++++++++++++++++++++++++++++++ src/util/virscsihost.h | 40 ++++ src/util/virutil.c | 269 --------------------------- src/util/virutil.h | 20 -- tests/scsihosttest.c | 16 +- 11 files changed, 386 insertions(+), 322 deletions(-) create mode 100644 src/util/virscsihost.c create mode 100644 src/util/virscsihost.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 1331093..e9a3569 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -240,6 +240,7 @@ src/util/virqemu.c src/util/virrandom.c src/util/virrotatingfile.c src/util/virscsi.c +src/util/virscsihost.c src/util/virscsivhost.c src/util/virsecret.c src/util/virsexpr.c diff --git a/src/Makefile.am b/src/Makefile.am index 0fec45b..5db0ea9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -164,6 +164,7 @@ UTIL_SOURCES = \ util/virrandom.h util/virrandom.c \ util/virrotatingfile.h util/virrotatingfile.c \ util/virscsi.c util/virscsi.h \ + util/virscsihost.c util/virscsihost.h \ util/virscsivhost.c util/virscsivhost.h \ util/virseclabel.c util/virseclabel.h \ util/virsecret.c util/virsecret.h \ diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 5e13bbf..8289ccc 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -43,6 +43,7 @@ #include "virbuffer.h" #include "viralloc.h" #include "virfile.h" +#include "virscsihost.h" #include "virstring.h" #include "virlog.h" #include "virvhba.h" @@ -2277,16 +2278,16 @@ getSCSIHostNumber(virStoragePoolSourceAdapter adapter, virPCIDeviceAddress addr = adapter.data.scsi_host.parentaddr; unsigned int unique_id = adapter.data.scsi_host.unique_id; - if (!(name = virGetSCSIHostNameByParentaddr(addr.domain, + if (!(name = virSCSIHostGetNameByParentaddr(addr.domain, addr.bus, addr.slot, addr.function, unique_id))) goto cleanup; - if (virGetSCSIHostNumber(name, &num) < 0) + if (virSCSIHostGetNumber(name, &num) < 0) goto cleanup; } else { - if (virGetSCSIHostNumber(adapter.data.scsi_host.name, &num) < 0) + if (virSCSIHostGetNumber(adapter.data.scsi_host.name, &num) < 0) goto cleanup; } @@ -2298,6 +2299,20 @@ getSCSIHostNumber(virStoragePoolSourceAdapter adapter, return ret; } + +static bool +isSameHostnum(const char *name, unsigned int scsi_hostnum) +{ + unsigned int fc_hostnum; + + if (virSCSIHostGetNumber(name, &fc_hostnum) == 0 && + scsi_hostnum == fc_hostnum) + return true; + + return false; +} + + /* * matchFCHostToSCSIHost: * @@ -2315,14 +2330,12 @@ matchFCHostToSCSIHost(virConnectPtr conn, { char *name = NULL; char *parent_name = NULL; - unsigned int fc_hostnum; /* If we have a parent defined, get its hostnum, and compare to the * scsi_hostnum. If they are the same, then we have a match */ if (fc_adapter.data.fchost.parent && - virGetSCSIHostNumber(fc_adapter.data.fchost.parent, &fc_hostnum) == 0 && - scsi_hostnum == fc_hostnum) + isSameHostnum(fc_adapter.data.fchost.parent, scsi_hostnum)) return true; /* If we find an fc_adapter name, then either libvirt created a vHBA @@ -2334,11 +2347,11 @@ matchFCHostToSCSIHost(virConnectPtr conn, /* Get the scsi_hostN for the vHBA in order to see if it * matches our scsi_hostnum */ - if (virGetSCSIHostNumber(name, &fc_hostnum) == 0 && - scsi_hostnum == fc_hostnum) { + if (isSameHostnum(name, scsi_hostnum)) { VIR_FREE(name); return true; } + VIR_FREE(name); /* We weren't provided a parent, so we have to query the node * device driver in order to ascertain the parent of the vHBA. @@ -2347,10 +2360,8 @@ matchFCHostToSCSIHost(virConnectPtr conn, */ if (conn && !fc_adapter.data.fchost.parent) { if ((parent_name = virVHBAGetParent(conn, name))) { - if (virGetSCSIHostNumber(parent_name, &fc_hostnum) == 0 && - scsi_hostnum == fc_hostnum) { + if (isSameHostnum(parent_name, scsi_hostnum)) { VIR_FREE(parent_name); - VIR_FREE(name); return true; } VIR_FREE(parent_name); @@ -2360,7 +2371,6 @@ matchFCHostToSCSIHost(virConnectPtr conn, VIR_DEBUG("Could not determine parent vHBA"); } } - VIR_FREE(name); } /* NB: Lack of a name means that this vHBA hasn't yet been created, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b58742d..ec3cab7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2349,6 +2349,12 @@ virSCSIDeviceNew; virSCSIDeviceSetUsedBy; +# util/virscsihost.h +virSCSIHostFindByPCI; +virSCSIHostGetNameByParentaddr; +virSCSIHostGetNumber; +virSCSIHostGetUniqueId; + # util/virscsivhost.h virSCSIVHostDeviceFileIterate; virSCSIVHostDeviceFree; @@ -2674,7 +2680,6 @@ virUSBDeviceSetUsedBy; virDoubleToStr; virEnumFromString; virEnumToString; -virFindSCSIHostByPCI; virFormatIntDecimal; virGetDeviceID; virGetDeviceUnprivSGIO; @@ -2686,8 +2691,6 @@ virGetGroupName; virGetHostname; virGetHostnameQuiet; virGetListenFDs; -virGetSCSIHostNameByParentaddr; -virGetSCSIHostNumber; virGetSelfLastChanged; virGetSystemPageSize; virGetSystemPageSizeKB; @@ -2711,7 +2714,6 @@ virParseNumber; virParseOwnershipIds; virParseVersionString; virPipeReadUntilEOF; -virReadSCSIUniqueId; virScaleInteger; virSetBlocking; virSetCloseExec; diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index 1c72b07..8ac8bf6 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -33,6 +33,7 @@ #include "viralloc.h" #include "virlog.h" #include "virfile.h" +#include "virscsihost.h" #include "virstring.h" #include "virvhba.h" @@ -48,8 +49,8 @@ nodeDeviceSysfsGetSCSIHostCaps(virNodeDevCapDataPtr d) char *tmp = NULL; int ret = -1; - if (virReadSCSIUniqueId(NULL, d->scsi_host.host, - &d->scsi_host.unique_id) < 0) { + if ((d->scsi_host.unique_id = + virSCSIHostGetUniqueId(NULL, d->scsi_host.host)) < 0) { VIR_DEBUG("Failed to read unique_id for host%d", d->scsi_host.host); d->scsi_host.unique_id = -1; } diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c index 2da15dd..da3b847 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -33,6 +33,7 @@ #include "virlog.h" #include "virfile.h" #include "vircommand.h" +#include "virscsihost.h" #include "virstring.h" #include "virvhba.h" #include "storage_util.h" @@ -159,7 +160,7 @@ virStoragePoolFCRefreshThread(void *opaque) pool->def->allocation = pool->def->capacity = pool->def->available = 0; if (virStoragePoolObjIsActive(pool) && - virGetSCSIHostNumber(fchost_name, &host) == 0 && + virSCSIHostGetNumber(fchost_name, &host) == 0 && virStorageBackendSCSITriggerRescan(host) == 0) { virStoragePoolObjClearVols(pool); found = virStorageBackendSCSIFindLUs(pool, host); @@ -184,7 +185,7 @@ getAdapterName(virStoragePoolSourceAdapter adapter) virPCIDeviceAddress addr = adapter.data.scsi_host.parentaddr; unsigned int unique_id = adapter.data.scsi_host.unique_id; - if (!(name = virGetSCSIHostNameByParentaddr(addr.domain, + if (!(name = virSCSIHostGetNameByParentaddr(addr.domain, addr.bus, addr.slot, addr.function, @@ -312,7 +313,7 @@ createVport(virConnectPtr conn, skip_capable_check = true; } - if (virGetSCSIHostNumber(parent_hoststr, &parent_host) < 0) + if (virSCSIHostGetNumber(parent_hoststr, &parent_host) < 0) goto cleanup; /* NOTE: @@ -413,13 +414,13 @@ deleteVport(virConnectPtr conn, * the parent scsi_host which we did not save at startup time */ if (adapter.data.fchost.parent) { - if (virGetSCSIHostNumber(adapter.data.fchost.parent, &parent_host) < 0) + if (virSCSIHostGetNumber(adapter.data.fchost.parent, &parent_host) < 0) goto cleanup; } else { if (!(vhba_parent = virVHBAGetParent(conn, name))) goto cleanup; - if (virGetSCSIHostNumber(vhba_parent, &parent_host) < 0) + if (virSCSIHostGetNumber(vhba_parent, &parent_host) < 0) goto cleanup; } @@ -460,7 +461,7 @@ virStorageBackendSCSICheckPool(virStoragePoolObjPtr pool, } } - if (virGetSCSIHostNumber(name, &host) < 0) + if (virSCSIHostGetNumber(name, &host) < 0) goto cleanup; if (virAsprintf(&path, "%s/host%d", @@ -489,7 +490,7 @@ virStorageBackendSCSIRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED, if (!(name = getAdapterName(pool->def->source.adapter))) return -1; - if (virGetSCSIHostNumber(name, &host) < 0) + if (virSCSIHostGetNumber(name, &host) < 0) goto out; VIR_DEBUG("Scanning host%u", host); diff --git a/src/util/virscsihost.c b/src/util/virscsihost.c new file mode 100644 index 0000000..eea0474 --- /dev/null +++ b/src/util/virscsihost.c @@ -0,0 +1,297 @@ +/* + * virscsihost.c: Generic scsi_host management utility functions + * + * 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/>. + */ + +#include <config.h> +#include <dirent.h> + +#include "viralloc.h" +#include "virerror.h" +#include "virfile.h" +#include "virlog.h" +#include "virscsihost.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +VIR_LOG_INIT("util.scsi_host"); + +#ifdef __linux__ + +# define SYSFS_SCSI_HOST_PATH "/sys/class/scsi_host" + +/* virSCSIHostGetUniqueId: + * @sysfs_prefix: "scsi_host" sysfs path, defaults to SYSFS_SCSI_HOST_PATH + * @host: Host number, E.g. 5 of "scsi_host/host5" + * + * Read the value of the "scsi_host" unique_id file. + * + * Returns the value on success or -1 on failure. + */ +int +virSCSIHostGetUniqueId(const char *sysfs_prefix, + int host) +{ + char *sysfs_path = NULL; + char *p = NULL; + int ret = -1; + char *buf = NULL; + int unique_id; + + if (virAsprintf(&sysfs_path, "%s/host%d/unique_id", + sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_HOST_PATH, + host) < 0) + return -1; + + if (virFileReadAll(sysfs_path, 1024, &buf) < 0) + goto cleanup; + + if ((p = strchr(buf, '\n'))) + *p = '\0'; + + if (virStrToLong_i(buf, NULL, 10, &unique_id) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unable to parse unique_id: %s"), buf); + + goto cleanup; + } + + ret = unique_id; + + cleanup: + VIR_FREE(sysfs_path); + VIR_FREE(buf); + return ret; +} + + +/* virSCSIHostFindByPCI: + * @sysfs_prefix: "scsi_host" sysfs path, defaults to SYSFS_SCSI_HOST_PATH + * @parentaddr: string of the PCI address "scsi_host" device to be found + * @unique_id: unique_id value of the to be found "scsi_host" device + * @result: Return the host# of the matching "scsi_host" device + * + * Iterate over the SYSFS_SCSI_HOST_PATH entries looking for a matching + * PCI Address in the expected format (dddd:bb:ss.f, where 'dddd' is the + * 'domain' value, 'bb' is the 'bus' value, 'ss' is the 'slot' value, and + * 'f' is the 'function' value from the PCI address) with a unique_id file + * entry having the value expected. Unlike virReadSCSIUniqueId() we don't + * have a host number yet and that's what we're looking for. + * + * Returns the host name of the "scsi_host" which must be freed by the caller, + * or NULL on failure + */ +char * +virSCSIHostFindByPCI(const char *sysfs_prefix, + const char *parentaddr, + unsigned int unique_id) +{ + const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_HOST_PATH; + struct dirent *entry = NULL; + DIR *dir = NULL; + char *host_link = NULL; + char *host_path = NULL; + char *p = NULL; + char *ret = NULL; + char *buf = NULL; + char *unique_path = NULL; + unsigned int read_unique_id; + + if (virDirOpen(&dir, prefix) < 0) + return NULL; + + while (virDirRead(dir, &entry, prefix) > 0) { + if (!virFileIsLink(entry->d_name)) + continue; + + if (virAsprintf(&host_link, "%s/%s", prefix, entry->d_name) < 0) + goto cleanup; + + if (virFileResolveLink(host_link, &host_path) < 0) + goto cleanup; + + if (!strstr(host_path, parentaddr)) { + VIR_FREE(host_link); + VIR_FREE(host_path); + continue; + } + VIR_FREE(host_link); + VIR_FREE(host_path); + + if (virAsprintf(&unique_path, "%s/%s/unique_id", prefix, + entry->d_name) < 0) + goto cleanup; + + if (!virFileExists(unique_path)) { + VIR_FREE(unique_path); + continue; + } + + if (virFileReadAll(unique_path, 1024, &buf) < 0) + goto cleanup; + + if ((p = strchr(buf, '\n'))) + *p = '\0'; + + if (virStrToLong_ui(buf, NULL, 10, &read_unique_id) < 0) + goto cleanup; + + VIR_FREE(buf); + + if (read_unique_id != unique_id) { + VIR_FREE(unique_path); + continue; + } + + ignore_value(VIR_STRDUP(ret, entry->d_name)); + break; + } + + cleanup: + VIR_DIR_CLOSE(dir); + VIR_FREE(unique_path); + VIR_FREE(host_link); + VIR_FREE(host_path); + VIR_FREE(buf); + return ret; +} + + +/* virSCSIHostGetNumber: + * @adapter_name: Name of the host adapter + * @result: Return the entry value as unsigned int + * + * Convert the various forms of scsi_host names into the numeric + * host# value that can be used in order to scan sysfs looking for + * the specific host. + * + * Names can be either "scsi_host#" or just "host#", where + * "host#" is the back-compat format, but both equate to + * the same source adapter. First check if both pool and def + * are using same format (easier) - if so, then compare + * + * Returns 0 on success, and @result has the host number. + * Otherwise returns -1. + */ +int +virSCSIHostGetNumber(const char *adapter_name, + unsigned int *result) +{ + /* Specifying adapter like 'host5' is still supported for + * back-compat reason. + */ + if (STRPREFIX(adapter_name, "scsi_host")) { + adapter_name += strlen("scsi_host"); + } else if (STRPREFIX(adapter_name, "fc_host")) { + adapter_name += strlen("fc_host"); + } else if (STRPREFIX(adapter_name, "host")) { + adapter_name += strlen("host"); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid adapter name '%s' for SCSI pool"), + adapter_name); + return -1; + } + + if (virStrToLong_ui(adapter_name, NULL, 10, result) == -1) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid adapter name '%s' for SCSI pool"), + adapter_name); + return -1; + } + + return 0; +} + +/* virSCSIHostGetNameByParentaddr: + * @domain: The domain from the scsi_host parentaddr + * @bus: The bus from the scsi_host parentaddr + * @slot: The slot from the scsi_host parentaddr + * @function: The function from the scsi_host parentaddr + * @unique_id: The unique id value for parentaddr + * + * Generate a parentaddr and find the scsi_host host# for + * the provided parentaddr PCI address fields. + * + * Returns the "host#" string which must be free'd by + * the caller or NULL on error + */ +char * +virSCSIHostGetNameByParentaddr(unsigned int domain, + unsigned int bus, + unsigned int slot, + unsigned int function, + unsigned int unique_id) +{ + char *name = NULL; + char *parentaddr = NULL; + + if (virAsprintf(&parentaddr, "%04x:%02x:%02x.%01x", + domain, bus, slot, function) < 0) + goto cleanup; + if (!(name = virSCSIHostFindByPCI(NULL, parentaddr, unique_id))) { + virReportError(VIR_ERR_XML_ERROR, + _("Failed to find scsi_host using PCI '%s' " + "and unique_id='%u'"), + parentaddr, unique_id); + goto cleanup; + } + + cleanup: + VIR_FREE(parentaddr); + return name; +} + +#else + +int +virSCSIHostGetUniqueId(const char *sysfs_prefix ATTRIBUTE_UNUSED, + int host ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); + return -1; +} + +char * +virSCSIHostFindByPCI(const char *sysfs_prefix ATTRIBUTE_UNUSED, + const char *parentaddr ATTRIBUTE_UNUSED, + unsigned int unique_id ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); + return NULL; +} + +int +virSCSIHostGetNumber(const char *adapter_name ATTRIBUTE_UNUSED, + unsigned int *result ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); + return -1; +} + +char * +virSCSIHostGetNameByParentaddr(unsigned int domain ATTRIBUTE_UNUSED, + unsigned int bus ATTRIBUTE_UNUSED, + unsigned int slot ATTRIBUTE_UNUSED, + unsigned int function ATTRIBUTE_UNUSED, + unsigned int unique_id ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); + return NULL; +} + +#endif /* __linux__ */ diff --git a/src/util/virscsihost.h b/src/util/virscsihost.h new file mode 100644 index 0000000..c35ccb9 --- /dev/null +++ b/src/util/virscsihost.h @@ -0,0 +1,40 @@ +/* + * virscsihost.h: Generic scsi_host management utility functions + * + * 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/>. + */ + +#ifndef __VIR_SCSI_HOST_H__ +# define __VIR_SCSI_HOST_H__ + +# include "internal.h" + +int virSCSIHostGetUniqueId(const char *sysfs_prefix, int host); + +char *virSCSIHostFindByPCI(const char *sysfs_prefix, + const char *parentaddr, + unsigned int unique_id); + +int virSCSIHostGetNumber(const char *adapter_name, + unsigned int *result) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +char *virSCSIHostGetNameByParentaddr(unsigned int domain, + unsigned int bus, + unsigned int slot, + unsigned int function, + unsigned int unique_id); + +#endif /* __VIR_SCSI_HOST_H__ */ diff --git a/src/util/virutil.c b/src/util/virutil.c index 51a1394..6fb70db 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -27,7 +27,6 @@ #include <config.h> #include <stdlib.h> -#include <dirent.h> #include <stdio.h> #include <stdarg.h> #include <unistd.h> @@ -1776,274 +1775,6 @@ virGetDeviceUnprivSGIO(const char *path, return ret; } -#ifdef __linux__ - -# define SYSFS_SCSI_HOST_PATH "/sys/class/scsi_host" - -/* virReadSCSIUniqueId: - * @sysfs_prefix: "scsi_host" sysfs path, defaults to SYSFS_SCSI_HOST_PATH - * @host: Host number, E.g. 5 of "scsi_host/host5" - * @result: Return the entry value as an unsigned int - * - * Read the value of the "scsi_host" unique_id file. - * - * Returns 0 on success, and @result is filled with the unique_id value - * Otherwise returns -1 - */ -int -virReadSCSIUniqueId(const char *sysfs_prefix, - int host, - int *result) -{ - char *sysfs_path = NULL; - char *p = NULL; - int ret = -1; - char *buf = NULL; - int unique_id; - - if (virAsprintf(&sysfs_path, "%s/host%d/unique_id", - sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_HOST_PATH, - host) < 0) - goto cleanup; - - if (virFileReadAll(sysfs_path, 1024, &buf) < 0) - goto cleanup; - - if ((p = strchr(buf, '\n'))) - *p = '\0'; - - if (virStrToLong_i(buf, NULL, 10, &unique_id) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unable to parse unique_id: %s"), buf); - - goto cleanup; - } - - *result = unique_id; - ret = 0; - - cleanup: - VIR_FREE(sysfs_path); - VIR_FREE(buf); - return ret; -} - -/* virFindSCSIHostByPCI: - * @sysfs_prefix: "scsi_host" sysfs path, defaults to SYSFS_SCSI_HOST_PATH - * @parentaddr: string of the PCI address "scsi_host" device to be found - * @unique_id: unique_id value of the to be found "scsi_host" device - * @result: Return the host# of the matching "scsi_host" device - * - * Iterate over the SYSFS_SCSI_HOST_PATH entries looking for a matching - * PCI Address in the expected format (dddd:bb:ss.f, where 'dddd' is the - * 'domain' value, 'bb' is the 'bus' value, 'ss' is the 'slot' value, and - * 'f' is the 'function' value from the PCI address) with a unique_id file - * entry having the value expected. Unlike virReadSCSIUniqueId() we don't - * have a host number yet and that's what we're looking for. - * - * Returns the host name of the "scsi_host" which must be freed by the caller, - * or NULL on failure - */ -char * -virFindSCSIHostByPCI(const char *sysfs_prefix, - const char *parentaddr, - unsigned int unique_id) -{ - const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_HOST_PATH; - struct dirent *entry = NULL; - DIR *dir = NULL; - char *host_link = NULL; - char *host_path = NULL; - char *p = NULL; - char *ret = NULL; - char *buf = NULL; - char *unique_path = NULL; - unsigned int read_unique_id; - - if (virDirOpen(&dir, prefix) < 0) - return NULL; - - while (virDirRead(dir, &entry, prefix) > 0) { - if (!virFileIsLink(entry->d_name)) - continue; - - if (virAsprintf(&host_link, "%s/%s", prefix, entry->d_name) < 0) - goto cleanup; - - if (virFileResolveLink(host_link, &host_path) < 0) - goto cleanup; - - if (!strstr(host_path, parentaddr)) { - VIR_FREE(host_link); - VIR_FREE(host_path); - continue; - } - VIR_FREE(host_link); - VIR_FREE(host_path); - - if (virAsprintf(&unique_path, "%s/%s/unique_id", prefix, - entry->d_name) < 0) - goto cleanup; - - if (!virFileExists(unique_path)) { - VIR_FREE(unique_path); - continue; - } - - if (virFileReadAll(unique_path, 1024, &buf) < 0) - goto cleanup; - - if ((p = strchr(buf, '\n'))) - *p = '\0'; - - if (virStrToLong_ui(buf, NULL, 10, &read_unique_id) < 0) - goto cleanup; - - VIR_FREE(buf); - - if (read_unique_id != unique_id) { - VIR_FREE(unique_path); - continue; - } - - ignore_value(VIR_STRDUP(ret, entry->d_name)); - break; - } - - cleanup: - VIR_DIR_CLOSE(dir); - VIR_FREE(unique_path); - VIR_FREE(host_link); - VIR_FREE(host_path); - VIR_FREE(buf); - return ret; -} - -/* virGetSCSIHostNumber: - * @adapter_name: Name of the host adapter - * @result: Return the entry value as unsigned int - * - * Convert the various forms of scsi_host names into the numeric - * host# value that can be used in order to scan sysfs looking for - * the specific host. - * - * Names can be either "scsi_host#" or just "host#", where - * "host#" is the back-compat format, but both equate to - * the same source adapter. First check if both pool and def - * are using same format (easier) - if so, then compare - * - * Returns 0 on success, and @result has the host number. - * Otherwise returns -1. - */ -int -virGetSCSIHostNumber(const char *adapter_name, - unsigned int *result) -{ - /* Specifying adapter like 'host5' is still supported for - * back-compat reason. - */ - if (STRPREFIX(adapter_name, "scsi_host")) { - adapter_name += strlen("scsi_host"); - } else if (STRPREFIX(adapter_name, "fc_host")) { - adapter_name += strlen("fc_host"); - } else if (STRPREFIX(adapter_name, "host")) { - adapter_name += strlen("host"); - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid adapter name '%s' for SCSI pool"), - adapter_name); - return -1; - } - - if (virStrToLong_ui(adapter_name, NULL, 10, result) == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid adapter name '%s' for SCSI pool"), - adapter_name); - return -1; - } - - return 0; -} - -/* virGetSCSIHostNameByParentaddr: - * @domain: The domain from the scsi_host parentaddr - * @bus: The bus from the scsi_host parentaddr - * @slot: The slot from the scsi_host parentaddr - * @function: The function from the scsi_host parentaddr - * @unique_id: The unique id value for parentaddr - * - * Generate a parentaddr and find the scsi_host host# for - * the provided parentaddr PCI address fields. - * - * Returns the "host#" string which must be free'd by - * the caller or NULL on error - */ -char * -virGetSCSIHostNameByParentaddr(unsigned int domain, - unsigned int bus, - unsigned int slot, - unsigned int function, - unsigned int unique_id) -{ - char *name = NULL; - char *parentaddr = NULL; - - if (virAsprintf(&parentaddr, "%04x:%02x:%02x.%01x", - domain, bus, slot, function) < 0) - goto cleanup; - if (!(name = virFindSCSIHostByPCI(NULL, parentaddr, unique_id))) { - virReportError(VIR_ERR_XML_ERROR, - _("Failed to find scsi_host using PCI '%s' " - "and unique_id='%u'"), - parentaddr, unique_id); - goto cleanup; - } - - cleanup: - VIR_FREE(parentaddr); - return name; -} - -#else - -int -virReadSCSIUniqueId(const char *sysfs_prefix ATTRIBUTE_UNUSED, - int host ATTRIBUTE_UNUSED, - int *result ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); - return -1; -} - -char * -virFindSCSIHostByPCI(const char *sysfs_prefix ATTRIBUTE_UNUSED, - const char *parentaddr ATTRIBUTE_UNUSED, - unsigned int unique_id ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); - return NULL; -} - -int -virGetSCSIHostNumber(const char *adapter_name ATTRIBUTE_UNUSED, - unsigned int *result ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); - return -1; -} - -char * -virGetSCSIHostNameByParentaddr(unsigned int domain ATTRIBUTE_UNUSED, - unsigned int bus ATTRIBUTE_UNUSED, - unsigned int slot ATTRIBUTE_UNUSED, - unsigned int function ATTRIBUTE_UNUSED, - unsigned int unique_id ATTRIBUTE_UNUSED) -{ - virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); - return NULL; -} - -#endif /* __linux__ */ /** * virParseOwnershipIds: diff --git a/src/util/virutil.h b/src/util/virutil.h index b320c06..877207c 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -164,26 +164,6 @@ int virGetDeviceUnprivSGIO(const char *path, int *unpriv_sgio); char *virGetUnprivSGIOSysfsPath(const char *path, const char *sysfs_dir); -int virReadSCSIUniqueId(const char *sysfs_prefix, - int host, - int *result) - ATTRIBUTE_NONNULL(3); -char * -virFindSCSIHostByPCI(const char *sysfs_prefix, - const char *parentaddr, - unsigned int unique_id); -int -virGetSCSIHostNumber(const char *adapter_name, - unsigned int *result) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -char * -virGetSCSIHostNameByParentaddr(unsigned int domain, - unsigned int bus, - unsigned int slot, - unsigned int function, - unsigned int unique_id); - - int virParseOwnershipIds(const char *label, uid_t *uidPtr, gid_t *gidPtr); diff --git a/tests/scsihosttest.c b/tests/scsihosttest.c index 7f16e04..9efc2d2 100644 --- a/tests/scsihosttest.c +++ b/tests/scsihosttest.c @@ -26,9 +26,9 @@ # include <fcntl.h> # include <sys/stat.h> # include "virstring.h" -# include "virutil.h" # include "virerror.h" # include "virlog.h" +# include "virscsihost.h" # define VIR_FROM_THIS VIR_FROM_NONE @@ -173,8 +173,8 @@ testVirReadSCSIUniqueId(const void *data ATTRIBUTE_UNUSED) int hostnum, unique_id; for (hostnum = 0; hostnum < 4; hostnum++) { - if (virReadSCSIUniqueId(TEST_SCSIHOST_CLASS_PATH, - hostnum, &unique_id) < 0) { + if ((unique_id = virSCSIHostGetUniqueId(TEST_SCSIHOST_CLASS_PATH, + hostnum)) < 0) { fprintf(stderr, "Failed to read hostnum=%d unique_id\n", hostnum); return -1; } @@ -196,7 +196,7 @@ testVirReadSCSIUniqueId(const void *data ATTRIBUTE_UNUSED) return 0; } -/* Test virFindSCSIHostByPCI */ +/* Test virSCSIHostFindByPCI */ static int testVirFindSCSIHostByPCI(const void *data ATTRIBUTE_UNUSED) { @@ -212,25 +212,25 @@ testVirFindSCSIHostByPCI(const void *data ATTRIBUTE_UNUSED) "sysfs/class/scsi_host") < 0) goto cleanup; - if (!(ret_host = virFindSCSIHostByPCI(TEST_SCSIHOST_CLASS_PATH, + if (!(ret_host = virSCSIHostFindByPCI(TEST_SCSIHOST_CLASS_PATH, pci_addr1, unique_id1)) || STRNEQ(ret_host, "host0")) goto cleanup; VIR_FREE(ret_host); - if (!(ret_host = virFindSCSIHostByPCI(TEST_SCSIHOST_CLASS_PATH, + if (!(ret_host = virSCSIHostFindByPCI(TEST_SCSIHOST_CLASS_PATH, pci_addr1, unique_id2)) || STRNEQ(ret_host, "host1")) goto cleanup; VIR_FREE(ret_host); - if (!(ret_host = virFindSCSIHostByPCI(TEST_SCSIHOST_CLASS_PATH, + if (!(ret_host = virSCSIHostFindByPCI(TEST_SCSIHOST_CLASS_PATH, pci_addr2, unique_id1)) || STRNEQ(ret_host, "host2")) goto cleanup; VIR_FREE(ret_host); - if (!(ret_host = virFindSCSIHostByPCI(TEST_SCSIHOST_CLASS_PATH, + if (!(ret_host = virSCSIHostFindByPCI(TEST_SCSIHOST_CLASS_PATH, pci_addr2, unique_id2)) || STRNEQ(ret_host, "host3")) goto cleanup; -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list