* src/node_device_hal_linux.c, src/node_device.c: Older kernels had vport_create and delete in /sys/class/scsi_host not /sys/class/fc_host. This patch causes libvirt to look in both places. --- src/node_device.c | 23 +++++- src/node_device.h | 2 +- src/node_device_hal_linux.c | 186 +++++++++++++++++++++++++----------------- 3 files changed, 134 insertions(+), 77 deletions(-) diff --git a/src/node_device.c b/src/node_device.c index d01695d..4a936de 100644 --- a/src/node_device.c +++ b/src/node_device.c @@ -369,6 +369,7 @@ nodeDeviceVportCreateDelete(virConnectPtr conn, int operation) { int retval = 0; + struct stat st; char *operation_path = NULL, *vport_name = NULL; const char *operation_file = NULL; @@ -388,7 +389,7 @@ nodeDeviceVportCreateDelete(virConnectPtr conn, } if (virAsprintf(&operation_path, - "%shost%d%s", + "%s/host%d%s", LINUX_SYSFS_FC_HOST_PREFIX, parent_host, operation_file) < 0) { @@ -398,6 +399,26 @@ nodeDeviceVportCreateDelete(virConnectPtr conn, goto cleanup; } + if (stat(operation_path, &st) != 0) { + VIR_FREE(operation_path); + if (virAsprintf(&operation_path, + "%s/host%d%s", + LINUX_SYSFS_SCSI_HOST_PREFIX, + parent_host, + operation_file) < 0) { + + virReportOOMError(conn); + retval = -1; + goto cleanup; + } + } + + if (stat(operation_path, &st) != 0) { + VIR_ERROR(_("No vport operation path found for host%d"), parent_host); + retval = -1; + goto cleanup; + } + VIR_DEBUG(_("Vport operation path is '%s'"), operation_path); if (virAsprintf(&vport_name, diff --git a/src/node_device.h b/src/node_device.h index db01624..e745eb4 100644 --- a/src/node_device.h +++ b/src/node_device.h @@ -30,7 +30,7 @@ #define LINUX_SYSFS_SCSI_HOST_PREFIX "/sys/class/scsi_host" #define LINUX_SYSFS_SCSI_HOST_POSTFIX "device" -#define LINUX_SYSFS_FC_HOST_PREFIX "/sys/class/fc_host/" +#define LINUX_SYSFS_FC_HOST_PREFIX "/sys/class/fc_host" #define VPORT_CREATE 0 #define VPORT_DELETE 1 diff --git a/src/node_device_hal_linux.c b/src/node_device_hal_linux.c index b76235d..b669a3a 100644 --- a/src/node_device_hal_linux.c +++ b/src/node_device_hal_linux.c @@ -34,58 +34,82 @@ #ifdef __linux__ -int check_fc_host_linux(union _virNodeDevCapData *d) + +static int fc_file_exists(const char *prefix, + int host, + const char *file) { + int retval = 0; char *sysfs_path = NULL; - char *wwnn_path = NULL; - char *wwpn_path = NULL; - char *p = NULL; - int fd = -1, retval = 0; - char buf[64]; struct stat st; - VIR_DEBUG(_("Checking if host%d is an FC HBA"), d->scsi_host.host); - - if (virAsprintf(&sysfs_path, "%s/host%d", - LINUX_SYSFS_FC_HOST_PREFIX, - d->scsi_host.host) < 0) { + if (virAsprintf(&sysfs_path, "%s/host%d%s", prefix, host, file) < 0) { virReportOOMError(NULL); retval = -1; goto out; } - if (stat(sysfs_path, &st) != 0) { - /* Not an FC HBA; not an error, either. */ - goto out; + if (stat(sysfs_path, &st) == 0) { + + retval = 1; + VIR_ERROR(_("'%s' exists"), sysfs_path); + + } else { + VIR_ERROR(_("'%s' does not exist"), sysfs_path); } - d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST; +out: + VIR_FREE(sysfs_path); + return retval; +} - if (virAsprintf(&wwnn_path, "%s/node_name", - sysfs_path) < 0) { + +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(NULL); retval = -1; goto out; } - if ((fd = open(wwnn_path, O_RDONLY)) < 0) { - retval = -1; - VIR_ERROR(_("Failed to open WWNN path '%s' for reading"), - wwnn_path); - goto out; + if ((*fd = open(wwn_path, O_RDONLY)) != -1) { + VIR_ERROR(_("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; +} + + +static int get_wwn(int host, const char *file, char **wwn) +{ + char *p = NULL; + int fd = -1, retval = 0; + char buf[64]; + + if (open_wwn_file(LINUX_SYSFS_FC_HOST_PREFIX, host, file, &fd) < 0) { + goto out; } memset(buf, 0, sizeof(buf)); if (saferead(fd, buf, sizeof(buf)) < 0) { retval = -1; - VIR_ERROR(_("Failed to read WWNN from '%s'"), - wwnn_path); + VIR_DEBUG(_("Failed to read WWN for host%d '%s'"), + host, file); goto out; } - close(fd); - fd = -1; - p = strstr(buf, "0x"); if (p != NULL) { p += strlen("0x"); @@ -93,97 +117,109 @@ int check_fc_host_linux(union _virNodeDevCapData *d) p = buf; } - d->scsi_host.wwnn = strndup(p, sizeof(buf)); - if (d->scsi_host.wwnn == NULL) { + *wwn = strndup(p, sizeof(buf)); + if (*wwn == NULL) { virReportOOMError(NULL); retval = -1; goto out; } - p = strchr(d->scsi_host.wwnn, '\n'); + p = strchr(*wwn, '\n'); if (p != NULL) { *p = '\0'; } - if (virAsprintf(&wwpn_path, "%s/port_name", - sysfs_path) < 0) { - virReportOOMError(NULL); - retval = -1; - goto out; +out: + if (fd != -1) { + close(fd); } + return retval; +} - if ((fd = open(wwpn_path, O_RDONLY)) < 0) { + +int check_fc_host_linux(union _virNodeDevCapData *d) +{ + int fc_host = 0; + int retval = 0; + + VIR_DEBUG(_("Checking if host%d is an FC HBA"), d->scsi_host.host); + + fc_host = fc_file_exists(LINUX_SYSFS_FC_HOST_PREFIX, + d->scsi_host.host, ""); + + if (fc_host == -1) { retval = -1; - VIR_ERROR(_("Failed to open WWPN path '%s' for reading"), - wwpn_path); goto out; } - memset(buf, 0, sizeof(buf)); - if (saferead(fd, buf, sizeof(buf)) < 0) { - retval = -1; - VIR_ERROR(_("Failed to read WWPN from '%s'"), - wwpn_path); + if (fc_host == 0) { + /* Not an FC HBA; not an error, either. */ goto out; } - close(fd); - fd = -1; + d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST; - p = strstr(buf, "0x"); - if (p != NULL) { - p += strlen("0x"); - } else { - p = buf; - } + retval = get_wwn(d->scsi_host.host, + "node_name", + &d->scsi_host.wwnn); - d->scsi_host.wwpn = strndup(p, sizeof(buf)); - if (d->scsi_host.wwpn == NULL) { - virReportOOMError(NULL); - retval = -1; + if (retval == -1) { goto out; } - p = strchr(d->scsi_host.wwpn, '\n'); - if (p != NULL) { - *p = '\0'; + VIR_DEBUG(_("WWNN: '%s'"), d->scsi_host.wwnn); + + retval = get_wwn(d->scsi_host.host, + "port_name", + &d->scsi_host.wwpn); + + if (retval == -1) { + goto out; } + VIR_DEBUG(_("WWPN: '%s'"), d->scsi_host.wwpn); + out: - if (fd != -1) { - close(fd); - } - VIR_FREE(sysfs_path); - VIR_FREE(wwnn_path); - VIR_FREE(wwpn_path); return 0; } int check_vport_capable_linux(union _virNodeDevCapData *d) { - char *sysfs_path = NULL; - struct stat st; - int retval = 0; + int retval = 0, file_exists = 0; - if (virAsprintf(&sysfs_path, "%s/host%d/vport_create", - LINUX_SYSFS_FC_HOST_PREFIX, - d->scsi_host.host) < 0) { - virReportOOMError(NULL); + VIR_DEBUG(_("Checking if host%d is vport capable"), d->scsi_host.host); + + file_exists = fc_file_exists(LINUX_SYSFS_FC_HOST_PREFIX, + d->scsi_host.host, + LINUX_SYSFS_VPORT_CREATE_POSTFIX); + + if (file_exists == -1) { retval = -1; goto out; } - if (stat(sysfs_path, &st) != 0) { - /* Not a vport capable HBA; not an error, either. */ + if (file_exists == 1) { + d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS; goto out; } - d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS; + file_exists = fc_file_exists(LINUX_SYSFS_SCSI_HOST_PREFIX, + d->scsi_host.host, + LINUX_SYSFS_VPORT_CREATE_POSTFIX); + + if (file_exists == -1) { + retval = -1; + goto out; + } + + if (file_exists == 1) { + d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS; + } out: - VIR_FREE(sysfs_path); return retval; } #endif /* __linux__ */ + -- 1.6.0.6 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list