diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f241ec4e2f8f4d1d4ea9b9863f8ee70978f23815..ff7f078e29f6b0a9c066c637e7b8d6d1e284ccfe 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1868,6 +1868,7 @@ virIsDevMapperDevice; virParseNumber; virParseVersionString; virPipeReadUntilEOF; +virReadFCHost; virScaleInteger; virSetBlocking; virSetCloseExec; diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_device_driver.h index 510ae73df8f8cd20f660bbec6e64a6e4b03b6074..26c1594c34675f2f6aae913fe641d346e3d602bb 100644 --- a/src/node_device/node_device_driver.h +++ b/src/node_device/node_device_driver.h @@ -59,14 +59,10 @@ int check_fc_host_linux(union _virNodeDevCapData *d); # define check_vport_capable(d) check_vport_capable_linux(d) int check_vport_capable_linux(union _virNodeDevCapData *d); -# define read_wwn(host, file, wwn) read_wwn_linux(host, file, wwn) -int read_wwn_linux(int host, const char *file, char **wwn); - # else /* __linux__ */ # define check_fc_host(d) (-1) # define check_vport_capable(d) (-1) -# define read_wwn(host, file, wwn) # endif /* __linux__ */ diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index 9c305d3b355efb8820bef7b88d895bd301540c6a..742a0bc7db946f6c7f6053fa11783d686bfc644c 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -37,77 +37,6 @@ #ifdef __linux__ -static int open_wwn_file(const char *prefix, - int host, - const char *file, - int *fd) -{ - int retval = 0; - char *wwn_path = NULL; - - if (virAsprintf(&wwn_path, "%s/host%d/%s", prefix, host, file) < 0) { - virReportOOMError(); - retval = -1; - goto out; - } - - /* fd will be closed by caller */ - if ((*fd = open(wwn_path, O_RDONLY)) != -1) { - VIR_DEBUG("Opened WWN path '%s' for reading", - wwn_path); - } else { - VIR_ERROR(_("Failed to open WWN path '%s' for reading"), - wwn_path); - } - -out: - VIR_FREE(wwn_path); - return retval; -} - - -int read_wwn_linux(int host, const char *file, char **wwn) -{ - char *p = NULL; - int fd = -1, retval = 0; - char buf[65] = ""; - - if (open_wwn_file(LINUX_SYSFS_FC_HOST_PREFIX, host, file, &fd) < 0) { - goto out; - } - - if (saferead(fd, buf, sizeof(buf) - 1) < 0) { - retval = -1; - VIR_DEBUG("Failed to read WWN for host%d '%s'", - host, file); - goto out; - } - - p = strstr(buf, "0x"); - if (p != NULL) { - p += strlen("0x"); - } else { - p = buf; - } - - *wwn = strndup(p, sizeof(buf)); - if (*wwn == NULL) { - virReportOOMError(); - retval = -1; - goto out; - } - - p = strchr(*wwn, '\n'); - if (p != NULL) { - *p = '\0'; - } - -out: - VIR_FORCE_CLOSE(fd); - return retval; -} - - int check_fc_host_linux(union _virNodeDevCapData *d) { char *sysfs_path = NULL; @@ -131,26 +60,29 @@ int check_fc_host_linux(union _virNodeDevCapData *d) d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST; - if (read_wwn(d->scsi_host.host, - "port_name", - &d->scsi_host.wwpn) == -1) { + if (virReadFCHost(NULL, + d->scsi_host.host, + "port_name", + &d->scsi_host.wwpn) == -1) { VIR_ERROR(_("Failed to read WWPN for host%d"), d->scsi_host.host); retval = -1; goto out; } - if (read_wwn(d->scsi_host.host, - "node_name", - &d->scsi_host.wwnn) == -1) { + if (virReadFCHost(NULL, + d->scsi_host.host, + "node_name", + &d->scsi_host.wwnn) == -1) { VIR_ERROR(_("Failed to read WWNN for host%d"), d->scsi_host.host); retval = -1; } - if (read_wwn(d->scsi_host.host, - "fabric_name", - &d->scsi_host.fabric_wwn) == -1) { + if (virReadFCHost(NULL, + d->scsi_host.host, + "fabric_name", + &d->scsi_host.fabric_wwn) == -1) { VIR_ERROR(_("Failed to read fabric WWN for host%d"), d->scsi_host.host); retval = -1; diff --git a/src/util/virutil.c b/src/util/virutil.c index 42b42954e39b71b9b8b37465f9dd160011ba3151..1d416e757ef8126859aca795e5390ca8cebd6433 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -3383,3 +3383,70 @@ cleanup: VIR_FREE(buf); return ret; } + +#ifdef __linux__ +# define SYSFS_FC_HOST_PATH "/sys/class/fc_host/" + +/* virReadFCHost: + * @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH + * @host: Host number, E.g. 5 of "fc_host/host5" + * @entry: Name of the sysfs entry to read + * @result: Return the entry value as string + * + * Read the value of sysfs "fc_host" entry. + * + * Returns 0 on success, and @result is filled with the entry value. + * as string, Otherwise returns -1. Caller must free @result after + * use. + */ +int +virReadFCHost(const char *sysfs_prefix, + int host, + const char *entry, + char **result) +{ + char *sysfs_path = NULL; + char *p = NULL; + int ret = -1; + char *buf = NULL; + + if (virAsprintf(&sysfs_path, "%s/host%d/%s", + sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH, + host, entry) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileReadAll(sysfs_path, 1024, &buf) < 0) + goto cleanup; + + if ((p = strchr(buf, '\n'))) + *p = '\0'; + + if ((p = strstr(buf, "0x"))) + p += strlen("0x"); + else + p = buf; + + if (!(*result = strndup(p, sizeof(buf)))) { + virReportOOMError(); + goto cleanup; + } + + ret = 0; +cleanup: + VIR_FREE(sysfs_path); + VIR_FREE(buf); + return ret; +} +#else +int +virReadFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED, + int host ATTRIBUTE_UNUSED, + const char *entry ATTRIBUTE_UNUSED, + char **result ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); + return -1; +} +#endif /* __linux__ */ diff --git a/src/util/virutil.h b/src/util/virutil.h index 665ad78edd3fa2ee8c7ec3b36b7dc35bfa5b9a0d..80e763c72a33338c3cb165041e631178c9fae41a 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -297,5 +297,10 @@ int virGetDeviceUnprivSGIO(const char *path, int *unpriv_sgio); char * virGetUnprivSGIOSysfsPath(const char *path, const char *sysfs_dir); +int virReadFCHost(const char *sysfs_prefix, + int host, + const char *entry, + char **result) + ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); #endif /* __VIR_UTIL_H__ */