mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 14:45:24 +00:00
util: Add helper to get the scsi host name by iterating over sysfs
The helper iterates over sysfs, to find out the matched scsi host name by comparing the wwnn,wwpn pair. It will be used by checkPool and refreshPool of storage scsi backend. New helper getAdapterName is introduced in storage_backend_scsi.c, which uses the new util helper virGetFCHostNameByWWN to get the fc_host adapter name.
This commit is contained in:
parent
b78db1c365
commit
b52fbad150
@ -1856,6 +1856,7 @@ virFindFileInPath;
|
||||
virFormatIntDecimal;
|
||||
virGetDeviceID;
|
||||
virGetDeviceUnprivSGIO;
|
||||
virGetFCHostNameByWWN;
|
||||
virGetGroupID;
|
||||
virGetGroupName;
|
||||
virGetHostname;
|
||||
|
@ -603,6 +603,8 @@ getHostNumber(const char *adapter_name,
|
||||
*/
|
||||
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 {
|
||||
@ -622,42 +624,73 @@ getHostNumber(const char *adapter_name,
|
||||
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);
|
||||
@ -669,6 +702,7 @@ virStorageBackendSCSIRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
VIR_FREE(name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
@ -3570,6 +3571,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 (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,
|
||||
@ -3607,4 +3707,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__ */
|
||||
|
@ -295,7 +295,7 @@ int virSetDeviceUnprivSGIO(const char *path,
|
||||
int virGetDeviceUnprivSGIO(const char *path,
|
||||
const char *sysfs_dir,
|
||||
int *unpriv_sgio);
|
||||
char * virGetUnprivSGIOSysfsPath(const char *path,
|
||||
char *virGetUnprivSGIOSysfsPath(const char *path,
|
||||
const char *sysfs_dir);
|
||||
int virReadFCHost(const char *sysfs_prefix,
|
||||
int host,
|
||||
@ -317,4 +317,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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user