virFormatIntDecimal;
virGetDeviceID;
virGetDeviceUnprivSGIO;
+virGetFCHostNameByWWN;
virGetGroupID;
virGetGroupName;
virGetHostname;
*/
if (STRPREFIX(host, "scsi_host")) {
host += strlen("scsi_host");
+ } else if (STRPREFIX(host, "fc_host")) {
+ host += strlen("fc_host");
} else if (STRPREFIX(host, "host")) {
host += strlen("host");
} else {
return 0;
}
+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 name;
+}
+
static int
virStorageBackendSCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool,
bool *isActive)
{
- char *path;
+ char *path = NULL;
+ char *name = NULL;
unsigned int host;
+ int ret = -1;
*isActive = false;
- if (getHostNumber(pool->def->source.adapter.data.name, &host) < 0)
+ if (!(name = getAdapterName(pool->def->source.adapter)))
return -1;
+ if (getHostNumber(name, &host) < 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;
unsigned int host;
+ int ret = -1;
pool->def->allocation = pool->def->capacity = pool->def->available = 0;
- if (getHostNumber(pool->def->source.adapter.data.name, &host) < 0)
+ if (!(name = getAdapterName(pool->def->source.adapter)))
+ return -1;
+
+ if (getHostNumber(name, &host) < 0)
goto out;
VIR_DEBUG("Scanning host%u", host);
ret = 0;
out:
+ VIR_FREE(name);
return ret;
}
#include <config.h>
+#include <dirent.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
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 (entry->d_name[0] == '.')
+ 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(wwnn_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);
+ break;
+ }
+
+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,
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__ */
int virGetDeviceUnprivSGIO(const char *path,
const char *sysfs_dir,
int *unpriv_sgio);
-char * virGetUnprivSGIOSysfsPath(const char *path,
- const char *sysfs_dir);
+char *virGetUnprivSGIOSysfsPath(const char *path,
+ const char *sysfs_dir);
int virReadFCHost(const char *sysfs_prefix,
int host,
const char *entry,
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__ */