The helper iterates over sysfs, to find out the matched scsi host
name by comparing the wwnn,wwpn pair. It's used for checkPool and
refreshPool of storage scsi backend. New helper getAdapterName
is introduced in storage_backend_scsi.c, it uses the new util
helper virGetFCHostNameByWWN to get the fc_host adapter name.
---
src/libvirt_private.syms | 1 +
src/storage/storage_backend_scsi.c | 50 ++++++++++++++---
src/util/virutil.c | 109 ++++++++++++++++++++++++++++++++++++
src/util/virutil.h | 5 ++
4 files changed, 157 insertions(+), 8 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 96f56cd..0bec5a0 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1833,6 +1833,7 @@ virFindFileInPath;
virFormatIntDecimal;
virGetDeviceID;
virGetDeviceUnprivSGIO;
+virGetFCHostNameByWWN;
virGetGroupID;
virGetGroupName;
virGetHostname;
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
index 257001c..8166311 100644
--- a/src/storage/storage_backend_scsi.c
+++ b/src/storage/storage_backend_scsi.c
@@ -601,7 +601,8 @@ getHostNumber(const char *adapter_name)
* back-compact reason.
*/
if ((sscanf(adapter_name, "scsi_host%d", &host) != 1) &&
- (sscanf(adapter_name, "host%d", &host) != 1)) {
+ (sscanf(adapter_name, "host%d", &host) != 1) &&
+ (sscanf(adapter_name, "fc_host%d", &host) != 1)) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to get host number from '%s'"),
adapter_name);
@@ -611,42 +612,74 @@ getHostNumber(const char *adapter_name)
return host;
}
+static char *
+getAdapterName(virStoragePoolSourceAdapter adapter)
+{
+ char *name = NULL;
+
+ if (adapter.type != VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST)
+ return strdup(adapter.data.name);
+
+ if (!(name = virGetFCHostNameByWWN(NULL,
+ adapter.data.fchost.wwnn,
+ adapter.data.fchost.wwpn))) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Failed to find SCSI host with wwnn='%s', "
+ "wwpn='%s'"), adapter.data.fchost.wwnn,
+ adapter.data.fchost.wwpn);
+ return NULL;
+ }
+
+ return name;
+}
+
static int
virStorageBackendSCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool,
bool *isActive)
{
- char *path;
+ char *path = NULL;
+ char *name = NULL;
int host;
+ int ret = -1;
*isActive = false;
- if ((host = getHostNumber(pool->def->source.adapter.data.name)) < 0)
+ if (!(name = getAdapterName(pool->def->source.adapter)))
return -1;
+ if ((host = getHostNumber(name)) < 0)
+ goto cleanup;
+
if (virAsprintf(&path, "/sys/class/scsi_host/host%d", host) < 0) {
virReportOOMError();
- return -1;
+ goto cleanup;
}
if (access(path, F_OK) == 0)
*isActive = true;
+ ret = 0;
+cleanup:
VIR_FREE(path);
-
- return 0;
+ VIR_FREE(name);
+ return ret;
}
static int
virStorageBackendSCSIRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool)
{
- int ret = -1;
+ char *name = NULL;
int host;
+ int ret = -1;
pool->def->allocation = pool->def->capacity = pool->def->available
= 0;
- if ((host = getHostNumber(pool->def->source.adapter.data.name)) < 0)
+ if (!(name = getAdapterName(pool->def->source.adapter)))
+ return -1;
+
+ if ((host = getHostNumber(name)) < 0)
goto out;
VIR_DEBUG("Scanning host%u", host);
@@ -658,6 +691,7 @@ virStorageBackendSCSIRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
ret = 0;
out:
+ VIR_FREE(name);
return ret;
}
diff --git a/src/util/virutil.c b/src/util/virutil.c
index b1d915c..4171004 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -26,6 +26,7 @@
#include <config.h>
+#include <dirent.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -3447,6 +3448,105 @@ cleanup:
VIR_FREE(operation_path);
return ret;
}
+
+/* virGetHostNameByWWN:
+ *
+ * Iterate over the sysfs tree to get SCSI host name (e.g. scsi_host5)
+ * by wwnn,wwpn pair.
+ */
+char *
+virGetFCHostNameByWWN(const char *sysfs_prefix,
+ const char *wwnn,
+ const char *wwpn)
+{
+ const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH;
+ struct dirent *entry = NULL;
+ DIR *dir = NULL;
+ char *wwnn_path = NULL;
+ char *wwpn_path = NULL;
+ char *wwnn_buf = NULL;
+ char *wwpn_buf = NULL;
+ char *p;
+ char *ret = NULL;
+
+ if (!(dir = opendir(prefix))) {
+ virReportSystemError(errno,
+ _("Failed to opendir path '%s'"),
+ prefix);
+ return NULL;
+ }
+
+# define READ_WWN(wwn_path, buf) \
+ do { \
+ if (virFileReadAll(wwn_path, 1024, &buf) < 0) \
+ goto cleanup; \
+ if ((p = strchr(buf, '\n'))) \
+ *p = '\0'; \
+ if (STRPREFIX(buf, "0x")) \
+ p = buf + strlen("0x"); \
+ else \
+ p = buf; \
+ } while (0)
+
+ while ((entry = readdir(dir))) {
+ if (STREQ(entry->d_name, ".") || STREQ(entry->d_name,
".."))
+ continue;
+
+ if (virAsprintf(&wwnn_path, "%s%s/node_name", prefix,
+ entry->d_name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (!virFileExists(wwnn_path)) {
+ VIR_FREE(wwnn_path);
+ continue;
+ }
+
+ READ_WWN(wwnn_path, wwnn_buf);
+
+ if (STRNEQ(wwnn, p)) {
+ VIR_FREE(wwpn_buf);
+ VIR_FREE(wwnn_path);
+ continue;
+ }
+
+ if (virAsprintf(&wwpn_path, "%s%s/port_name", prefix,
+ entry->d_name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (!virFileExists(wwpn_path)) {
+ VIR_FREE(wwnn_buf);
+ VIR_FREE(wwnn_path);
+ VIR_FREE(wwpn_path);
+ continue;
+ }
+
+ READ_WWN(wwpn_path, wwpn_buf);
+
+ if (STRNEQ(wwpn, p)) {
+ VIR_FREE(wwnn_path);
+ VIR_FREE(wwpn_path);
+ VIR_FREE(wwnn_buf);
+ VIR_FREE(wwpn_buf);
+ continue;
+ }
+
+ ret = strdup(entry->d_name);
+ goto cleanup;
+ }
+
+cleanup:
+# undef READ_WWN
+ closedir(dir);
+ VIR_FREE(wwnn_path);
+ VIR_FREE(wwpn_path);
+ VIR_FREE(wwnn_buf);
+ VIR_FREE(wwpn_buf);
+ return ret;
+}
#else
int
virReadFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED,
@@ -3483,4 +3583,13 @@ virManageVport(const int parent_host ATTRIBUTE_UNUSED,
return -1;
}
+char *
+virGetFCHostNameByWWN(const char *sysfs_prefix ATTRIBUTE_UNUSED,
+ const char *wwnn ATTRIBUTE_UNUSED,
+ const char *wwpn ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s", _("Not supported on this
platform"));
+ return NULL;
+}
+
#endif /* __linux__ */
diff --git a/src/util/virutil.h b/src/util/virutil.h
index c07417c..69774ad 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -313,4 +313,9 @@ int virManageVport(const int parent_host,
int operation)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+char * virGetFCHostNameByWWN(const char *sysfs_prefix,
+ const char *wwnn,
+ const char *wwpn)
+ ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
+
#endif /* __VIR_UTIL_H__ */
--
1.7.7.6