diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ff7f078e29f6b0a9c066c637e7b8d6d1e284ccfe..53d99cba529efbcaf17c1c0e7a0468087b7f385f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1864,6 +1864,8 @@ virGetUserName; virGetUserRuntimeDirectory; virHexToBin; virIndexToDiskName; +virIsCapableFCHost; +virIsCapableVport; virIsDevMapperDevice; virParseNumber; virParseVersionString; diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c index 87e7e3ea3a7c39d6db4c44a1a49ce53389c88732..b4749fbef0115b5197eee32c50421eb9cd0816a3 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -48,7 +48,7 @@ static int update_caps(virNodeDeviceObjPtr dev) while (cap) { /* The only caps that currently need updating are FC related. */ if (cap->type == VIR_NODE_DEV_CAP_SCSI_HOST) { - check_fc_host(&dev->def->caps->data); + detect_scsi_host_caps(&dev->def->caps->data); } cap = cap->next; } @@ -241,18 +241,15 @@ nodeDeviceLookupSCSIHostByWWN(virConnectPtr conn, nodeDeviceLock(driver); for (i = 0; i < devs->count; i++) { - obj = devs->objs[i]; virNodeDeviceObjLock(obj); cap = obj->def->caps; while (cap) { - if (cap->type == VIR_NODE_DEV_CAP_SCSI_HOST) { - check_fc_host(&cap->data); + detect_scsi_host_caps(&cap->data); if (cap->data.scsi_host.flags & VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) { - if (STREQ(cap->data.scsi_host.wwnn, wwnn) && STREQ(cap->data.scsi_host.wwpn, wwpn)) { dev = virGetNodeDevice(conn, obj->def->name); diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_device_driver.h index 26c1594c34675f2f6aae913fe641d346e3d602bb..ea819177e1eb2451ae89cf642ef1f3c05921cd98 100644 --- a/src/node_device/node_device_driver.h +++ b/src/node_device/node_device_driver.h @@ -53,16 +53,12 @@ int nodedevRegister(void); # ifdef __linux__ -# define check_fc_host(d) check_fc_host_linux(d) -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 detect_scsi_host_caps(d) detect_scsi_host_caps_linux(d) +int detect_scsi_host_caps_linux(union _virNodeDevCapData *d); # else /* __linux__ */ -# define check_fc_host(d) (-1) -# define check_vport_capable(d) (-1) +# define detect_scsi_host_caps(d) (-1) # endif /* __linux__ */ diff --git a/src/node_device/node_device_hal.c b/src/node_device/node_device_hal.c index 0ce1d0e05e4ef90289b72c3436853b5b723e6044..12835105055daede350f708d1a882ccf96f4293d 100644 --- a/src/node_device/node_device_hal.c +++ b/src/node_device/node_device_hal.c @@ -236,14 +236,12 @@ static int gather_scsi_host_cap(LibHalContext *ctx, const char *udi, (void)get_int_prop(ctx, udi, "scsi_host.host", (int *)&d->scsi_host.host); - retval = check_fc_host(d); + retval = detect_scsi_host_caps(d); if (retval == -1) { goto out; } - retval = check_vport_capable(d); - out: return retval; } diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index 742a0bc7db946f6c7f6053fa11783d686bfc644c..85bbab610feb5081596f5724f0f9df8cc486ced0 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -1,8 +1,8 @@ /* - * node_device_hal_linuc.c: Linux specific code to gather device data + * node_device_linux_sysfs.c: Linux specific code to gather device data * not available through HAL. * - * Copyright (C) 2009-2011 Red Hat, Inc. + * Copyright (C) 2009-2013 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,112 +37,53 @@ #ifdef __linux__ -int check_fc_host_linux(union _virNodeDevCapData *d) +int +detect_scsi_host_caps_linux(union _virNodeDevCapData *d) { - char *sysfs_path = NULL; - int retval = 0; - struct stat st; + int ret = -1; VIR_DEBUG("Checking if host%d is an FC HBA", d->scsi_host.host); - if (virAsprintf(&sysfs_path, "%shost%d", - LINUX_SYSFS_FC_HOST_PREFIX, - d->scsi_host.host) < 0) { - virReportOOMError(); - retval = -1; - goto out; + if (virIsCapableFCHost(NULL, d->scsi_host.host)) { + d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST; + + 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); + goto cleanup; + } + + 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); + goto cleanup; + } + + 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); + goto cleanup; + } } - if (stat(sysfs_path, &st) != 0) { - /* Not an FC HBA; not an error, either. */ - goto out; - } - - d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST; - - 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 (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 (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; - goto out; - } + if (virIsCapableVport(NULL, d->scsi_host.host) == 0) + d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS; -out: - if (retval == -1) { + ret = 0; +cleanup: + if (ret < 0) { VIR_FREE(d->scsi_host.wwnn); VIR_FREE(d->scsi_host.wwpn); VIR_FREE(d->scsi_host.fabric_wwn); } - VIR_FREE(sysfs_path); - return retval; -} - - -int check_vport_capable_linux(union _virNodeDevCapData *d) -{ - char *sysfs_path = NULL; - struct stat st; - int retval = 0; - - if (virAsprintf(&sysfs_path, - "%shost%d%s", - LINUX_SYSFS_FC_HOST_PREFIX, - d->scsi_host.host, - LINUX_SYSFS_VPORT_CREATE_POSTFIX) < 0) { - virReportOOMError(); - retval = -1; - goto out; - } - - if (stat(sysfs_path, &st) == 0) { - d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS; - goto out; - } - - VIR_FREE(sysfs_path); - if (virAsprintf(&sysfs_path, - "%shost%d%s", - LINUX_SYSFS_SCSI_HOST_PREFIX, - d->scsi_host.host, - LINUX_SYSFS_VPORT_CREATE_POSTFIX) < 0) { - virReportOOMError(); - retval = -1; - goto out; - } - - if (stat(sysfs_path, &st) == 0) { - d->scsi_host.flags |= VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS; - } else { - /* Not a vport capable HBA; not an error, either. */ - VIR_DEBUG("No vport operation path found for host%d", - d->scsi_host.host); - } - -out: - VIR_FREE(sysfs_path); - return retval; + return ret; } #endif /* __linux__ */ diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index 7f312522316a9afa3c30555a06ed3b5a6ab01566..0d8b984b84a0a85c76d752a34bb67e039eeed098 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -663,8 +663,7 @@ static int udevProcessSCSIHost(struct udev_device *device ATTRIBUTE_UNUSED, goto out; } - check_fc_host(&def->caps->data); - check_vport_capable(&def->caps->data); + detect_scsi_host_caps(&def->caps->data); if (udevGenerateDeviceName(device, def, NULL) != 0) { goto out; diff --git a/src/util/virutil.c b/src/util/virutil.c index 1d416e757ef8126859aca795e5390ca8cebd6433..456e3958dcca79a10d7c6ce44bbabe90a2b755a7 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -3386,6 +3386,7 @@ cleanup: #ifdef __linux__ # define SYSFS_FC_HOST_PATH "/sys/class/fc_host/" +# define SYSFS_SCSI_HOST_PATH "/sys/class/scsi_host/" /* virReadFCHost: * @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH @@ -3439,6 +3440,63 @@ cleanup: VIR_FREE(buf); return ret; } + +int +virIsCapableFCHost(const char *sysfs_prefix, + int host) +{ + char *sysfs_path = NULL; + int ret = -1; + + if (virAsprintf(&sysfs_path, "%shost%d", + sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH, + host) < 0) { + virReportOOMError(); + return -1; + } + + if (access(sysfs_path, F_OK) == 0) + ret = 0; + + VIR_FREE(sysfs_path); + return ret; +} + +int +virIsCapableVport(const char *sysfs_prefix, + int host) +{ + char *scsi_host_path = NULL; + char *fc_host_path = NULL; + int ret = -1; + + if (virAsprintf(&fc_host_path, + "%shost%d%s", + sysfs_prefix ? sysfs_prefix : SYSFS_FC_HOST_PATH, + host, + "vport_create") < 0) { + virReportOOMError(); + return -1; + } + + if (virAsprintf(&scsi_host_path, + "%shost%d%s", + sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_HOST_PATH, + host, + "vport_create") < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((access(fc_host_path, F_OK) == 0) || + (access(scsi_host_path, F_OK) == 0)) + ret = 0; + +cleanup: + VIR_FREE(fc_host_path); + VIR_FREE(scsi_host_path); + return ret; +} #else int virReadFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED, @@ -3449,4 +3507,19 @@ virReadFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED, virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); return -1; } + +int +virIsCapableFCHost(int host ATTRIBUTE_UNUSED) +{ + virReportSystemError(ENOSYS, "%s", _("Not supported on this platform")); + return -1; +} + +int +virIsCapbleVport(const char *sysfs_prefix ATTRIBUTE_UNUSED, + int host 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 80e763c72a33338c3cb165041e631178c9fae41a..6fc10a483e89fa743e9b97fed5042c8a3f8f6369 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -303,4 +303,7 @@ int virReadFCHost(const char *sysfs_prefix, char **result) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); +int virIsCapableFCHost(const char *sysfs_prefix, int host); +int virIsCapableVport(const char *sysfs_prefix, int host); + #endif /* __VIR_UTIL_H__ */