From 521a2285cfee3d2fdd59cb7a3270e9ef91bcc14f Mon Sep 17 00:00:00 2001 Message-Id: <521a2285cfee3d2fdd59cb7a3270e9ef91bcc14f@dist-git> From: Michal Privoznik Date: Fri, 6 Mar 2020 15:51:44 +0100 Subject: [PATCH] RHEL: virscsi: Check device type before getting it's /dev node name Not all SCSI devices are block devices, therefore /sys/bus/scsi/devices/X:X:X:X/block/ directory does not always exist. Check if the SCSI device is a block device beforehand. https://bugzilla.redhat.com/show_bug.cgi?id=1808388 Signed-off-by: Michal Privoznik Signed-off-by: Andrea Bolognani Message-Id: <20200306145149.1610286-2-abologna@redhat.com> Reviewed-by: Jiri Denemark --- src/util/virscsi.c | 149 ++++++++++++++++++++++++++++++--- tests/virscsidata/0-0-0-0/type | 1 + tests/virscsidata/1-0-0-0/type | 1 + 3 files changed, 138 insertions(+), 13 deletions(-) create mode 100644 tests/virscsidata/0-0-0-0/type create mode 100644 tests/virscsidata/1-0-0-0/type diff --git a/src/util/virscsi.c b/src/util/virscsi.c index b51103a86d..af908107d9 100644 --- a/src/util/virscsi.c +++ b/src/util/virscsi.c @@ -56,6 +56,32 @@ struct _virUsedByInfo { }; typedef struct _virUsedByInfo *virUsedByInfoPtr; + +/* Keep in sync with scsi/scsi_proto.h */ +typedef enum { + VIR_SCSI_DEVICE_TYPE_NONE = -1, + VIR_SCSI_DEVICE_TYPE_DISK = 0x00, + VIR_SCSI_DEVICE_TYPE_TAPE = 0x01, + VIR_SCSI_DEVICE_TYPE_PRINTER = 0x02, + VIR_SCSI_DEVICE_TYPE_PROCESSOR = 0x03, + VIR_SCSI_DEVICE_TYPE_WORM = 0x04, + VIR_SCSI_DEVICE_TYPE_ROM = 0x05, + VIR_SCSI_DEVICE_TYPE_SCANNER = 0x06, + VIR_SCSI_DEVICE_TYPE_MOD = 0x07, + VIR_SCSI_DEVICE_TYPE_MEDIUM_CHANGER = 0x08, + VIR_SCSI_DEVICE_TYPE_COMM = 0x09, + VIR_SCSI_DEVICE_TYPE_RAID = 0x0c, + VIR_SCSI_DEVICE_TYPE_ENCLOSURE = 0x0d, + VIR_SCSI_DEVICE_TYPE_RBC = 0x0e, + VIR_SCSI_DEVICE_TYPE_OSD = 0x11, + VIR_SCSI_DEVICE_TYPE_ZBC = 0x14, + VIR_SCSI_DEVICE_TYPE_WLUN = 0x1e, + VIR_SCSI_DEVICE_TYPE_NO_LUN = 0x7f, + + VIR_SCSI_DEVICE_TYPE_LAST, +} virSCSIDeviceType; + + struct _virSCSIDevice { unsigned int adapter; unsigned int bus; @@ -143,6 +169,86 @@ virSCSIDeviceGetSgName(const char *sysfs_prefix, return sg; } + +static int +virSCSIDeviceGetType(const char *prefix, + unsigned int adapter, + unsigned int bus, + unsigned int target, + unsigned long long unit, + virSCSIDeviceType *type) +{ + int intType; + + if (virFileReadValueInt(&intType, + "%s/%d:%u:%u:%llu/type", + prefix, adapter, bus, target, unit) < 0) + return -1; + + switch (intType) { + case VIR_SCSI_DEVICE_TYPE_DISK: + case VIR_SCSI_DEVICE_TYPE_TAPE: + case VIR_SCSI_DEVICE_TYPE_PRINTER: + case VIR_SCSI_DEVICE_TYPE_PROCESSOR: + case VIR_SCSI_DEVICE_TYPE_WORM: + case VIR_SCSI_DEVICE_TYPE_ROM: + case VIR_SCSI_DEVICE_TYPE_SCANNER: + case VIR_SCSI_DEVICE_TYPE_MOD: + case VIR_SCSI_DEVICE_TYPE_MEDIUM_CHANGER: + case VIR_SCSI_DEVICE_TYPE_COMM: + case VIR_SCSI_DEVICE_TYPE_RAID: + case VIR_SCSI_DEVICE_TYPE_ENCLOSURE: + case VIR_SCSI_DEVICE_TYPE_RBC: + case VIR_SCSI_DEVICE_TYPE_OSD: + case VIR_SCSI_DEVICE_TYPE_ZBC: + case VIR_SCSI_DEVICE_TYPE_WLUN: + case VIR_SCSI_DEVICE_TYPE_NO_LUN: + *type = intType; + break; + + default: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown SCSI device type: %x"), + intType); + return -1; + } + + return 0; +} + + +static char * +virSCSIDeviceGetDevNameBlock(const char *prefix, + unsigned int adapter, + unsigned int bus, + unsigned int target, + unsigned long long unit) +{ + DIR *dir = NULL; + struct dirent *entry; + char *path = NULL; + char *name = NULL; + + if (virAsprintf(&path, + "%s/%d:%u:%u:%llu/block", + prefix, adapter, bus, target, unit) < 0) + return NULL; + + if (virDirOpen(&dir, path) < 0) + goto cleanup; + + while (virDirRead(dir, &entry, path) > 0) { + ignore_value(VIR_STRDUP(name, entry->d_name)); + break; + } + + cleanup: + VIR_DIR_CLOSE(dir); + VIR_FREE(path); + return name; +} + + /* Returns device name (e.g. "sdc") on success, or NULL * on failure. */ @@ -153,35 +259,52 @@ virSCSIDeviceGetDevName(const char *sysfs_prefix, unsigned int target, unsigned long long unit) { - DIR *dir = NULL; - struct dirent *entry; - char *path = NULL; char *name = NULL; unsigned int adapter_id; + virSCSIDeviceType type; const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_DEVICES; if (virSCSIDeviceGetAdapterId(adapter, &adapter_id) < 0) return NULL; - if (virAsprintf(&path, - "%s/%d:%u:%u:%llu/block", - prefix, adapter_id, bus, target, unit) < 0) + if (virSCSIDeviceGetType(prefix, adapter_id, + bus, target, unit, &type) < 0) return NULL; - if (virDirOpen(&dir, path) < 0) - goto cleanup; + switch (type) { + case VIR_SCSI_DEVICE_TYPE_DISK: + name = virSCSIDeviceGetDevNameBlock(prefix, adapter_id, bus, target, unit); + break; - while (virDirRead(dir, &entry, path) > 0) { - ignore_value(VIR_STRDUP(name, entry->d_name)); + case VIR_SCSI_DEVICE_TYPE_TAPE: + case VIR_SCSI_DEVICE_TYPE_PRINTER: + case VIR_SCSI_DEVICE_TYPE_PROCESSOR: + case VIR_SCSI_DEVICE_TYPE_WORM: + case VIR_SCSI_DEVICE_TYPE_ROM: + case VIR_SCSI_DEVICE_TYPE_SCANNER: + case VIR_SCSI_DEVICE_TYPE_MOD: + case VIR_SCSI_DEVICE_TYPE_MEDIUM_CHANGER: + case VIR_SCSI_DEVICE_TYPE_COMM: + case VIR_SCSI_DEVICE_TYPE_RAID: + case VIR_SCSI_DEVICE_TYPE_ENCLOSURE: + case VIR_SCSI_DEVICE_TYPE_RBC: + case VIR_SCSI_DEVICE_TYPE_OSD: + case VIR_SCSI_DEVICE_TYPE_ZBC: + case VIR_SCSI_DEVICE_TYPE_WLUN: + case VIR_SCSI_DEVICE_TYPE_NO_LUN: + case VIR_SCSI_DEVICE_TYPE_NONE: + case VIR_SCSI_DEVICE_TYPE_LAST: + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported SCSI device type: %x"), + type); break; } - cleanup: - VIR_DIR_CLOSE(dir); - VIR_FREE(path); return name; } + virSCSIDevicePtr virSCSIDeviceNew(const char *sysfs_prefix, const char *adapter, diff --git a/tests/virscsidata/0-0-0-0/type b/tests/virscsidata/0-0-0-0/type new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/virscsidata/0-0-0-0/type @@ -0,0 +1 @@ +0 diff --git a/tests/virscsidata/1-0-0-0/type b/tests/virscsidata/1-0-0-0/type new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/virscsidata/1-0-0-0/type @@ -0,0 +1 @@ +0 -- 2.25.1