The iSCSI backend driver was using stuff from the SCSI driver without making sure that it's compiled in. Move the common code into the storage_util.c since it does not contain any specific code. --- src/storage/storage_backend_iscsi.c | 1 - src/storage/storage_backend_scsi.c | 447 ----------------------------------- src/storage/storage_backend_scsi.h | 4 - src/storage/storage_util.c | 449 ++++++++++++++++++++++++++++++++++++ src/storage/storage_util.h | 3 + 5 files changed, 452 insertions(+), 452 deletions(-) diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c index 8799349b6..281334124 100644 --- a/src/storage/storage_backend_iscsi.c +++ b/src/storage/storage_backend_iscsi.c @@ -32,7 +32,6 @@ #include "datatypes.h" #include "driver.h" -#include "storage_backend_scsi.h" #include "storage_backend_iscsi.h" #include "viralloc.h" #include "vircommand.h" diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c index d294d2ac0..ecad1782c 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -25,7 +25,6 @@ #include <unistd.h> #include <stdio.h> -#include <dirent.h> #include <fcntl.h> #include "virerror.h" @@ -48,452 +47,6 @@ struct _virStoragePoolFCRefreshInfo { unsigned char pool_uuid[VIR_UUID_BUFLEN]; }; -/* Function to check if the type file in the given sysfs_path is a - * Direct-Access device (i.e. type 0). Return -1 on failure, type of - * the device otherwise. - */ -static int -getDeviceType(uint32_t host, - uint32_t bus, - uint32_t target, - uint32_t lun, - int *type) -{ - char *type_path = NULL; - char typestr[3]; - char *gottype, *p; - FILE *typefile; - int retval = 0; - - if (virAsprintf(&type_path, "/sys/bus/scsi/devices/%u:%u:%u:%u/type", - host, bus, target, lun) < 0) - goto out; - - typefile = fopen(type_path, "r"); - if (typefile == NULL) { - virReportSystemError(errno, - _("Could not find typefile '%s'"), - type_path); - /* there was no type file; that doesn't seem right */ - retval = -1; - goto out; - } - - gottype = fgets(typestr, 3, typefile); - VIR_FORCE_FCLOSE(typefile); - - if (gottype == NULL) { - virReportSystemError(errno, - _("Could not read typefile '%s'"), - type_path); - /* we couldn't read the type file; have to give up */ - retval = -1; - goto out; - } - - /* we don't actually care about p, but if you pass NULL and the last - * character is not \0, virStrToLong_i complains - */ - if (virStrToLong_i(typestr, &p, 10, type) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Device type '%s' is not an integer"), - typestr); - /* Hm, type wasn't an integer; seems strange */ - retval = -1; - goto out; - } - - VIR_DEBUG("Device type is %d", *type); - - out: - VIR_FREE(type_path); - return retval; -} - -static char * -virStorageBackendSCSISerial(const char *dev) -{ - char *serial = NULL; -#ifdef WITH_UDEV - virCommandPtr cmd = virCommandNewArgList( - "/lib/udev/scsi_id", - "--replace-whitespace", - "--whitelisted", - "--device", dev, - NULL - ); - - /* Run the program and capture its output */ - virCommandSetOutputBuffer(cmd, &serial); - if (virCommandRun(cmd, NULL) < 0) - goto cleanup; -#endif - - if (serial && STRNEQ(serial, "")) { - char *nl = strchr(serial, '\n'); - if (nl) - *nl = '\0'; - } else { - VIR_FREE(serial); - ignore_value(VIR_STRDUP(serial, dev)); - } - -#ifdef WITH_UDEV - cleanup: - virCommandFree(cmd); -#endif - - return serial; -} - - -/* - * Attempt to create a new LUN - * - * Returns: - * - * 0 => Success - * -1 => Failure due to some sort of OOM or other fatal issue found when - * attempting to get/update information about a found volume - * -2 => Failure to find a stable path, not fatal, caller can try another - */ -static int -virStorageBackendSCSINewLun(virStoragePoolObjPtr pool, - uint32_t host ATTRIBUTE_UNUSED, - uint32_t bus, - uint32_t target, - uint32_t lun, - const char *dev) -{ - virStorageVolDefPtr vol = NULL; - char *devpath = NULL; - int retval = -1; - - /* Check if the pool is using a stable target path. The call to - * virStorageBackendStablePath will fail if the pool target path - * isn't stable and just return the strdup'd 'devpath' anyway. - * This would be indistinguishable to failing to find the stable - * path to the device if the virDirRead loop to search the - * target pool path for our devpath had failed. - */ - if (!virStorageBackendPoolPathIsStable(pool->def->target.path) && - !(STREQ(pool->def->target.path, "/dev") || - STREQ(pool->def->target.path, "/dev/"))) { - virReportError(VIR_ERR_INVALID_ARG, - _("unable to use target path '%s' for dev '%s'"), - NULLSTR(pool->def->target.path), dev); - goto cleanup; - } - - if (VIR_ALLOC(vol) < 0) - goto cleanup; - - vol->type = VIR_STORAGE_VOL_BLOCK; - - /* 'host' is dynamically allocated by the kernel, first come, - * first served, per HBA. As such it isn't suitable for use - * in the volume name. We only need uniqueness per-pool, so - * just leave 'host' out - */ - if (virAsprintf(&(vol->name), "unit:%u:%u:%u", bus, target, lun) < 0) - goto cleanup; - - if (virAsprintf(&devpath, "/dev/%s", dev) < 0) - goto cleanup; - - VIR_DEBUG("Trying to create volume for '%s'", devpath); - - /* Now figure out the stable path - * - * XXX this method is O(N) because it scans the pool target - * dir every time its run. Should figure out a more efficient - * way of doing this... - */ - if ((vol->target.path = virStorageBackendStablePath(pool, - devpath, - true)) == NULL) - goto cleanup; - - if (STREQ(devpath, vol->target.path) && - !(STREQ(pool->def->target.path, "/dev") || - STREQ(pool->def->target.path, "/dev/"))) { - - VIR_DEBUG("No stable path found for '%s' in '%s'", - devpath, pool->def->target.path); - - retval = -2; - goto cleanup; - } - - /* Allow a volume read failure to ignore or skip this block file */ - if ((retval = virStorageBackendUpdateVolInfo(vol, true, - VIR_STORAGE_VOL_OPEN_DEFAULT, - VIR_STORAGE_VOL_READ_NOERROR)) < 0) - goto cleanup; - - if (!(vol->key = virStorageBackendSCSISerial(vol->target.path))) - goto cleanup; - - pool->def->capacity += vol->target.capacity; - pool->def->allocation += vol->target.allocation; - - if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0) - goto cleanup; - - vol = NULL; - retval = 0; - - cleanup: - virStorageVolDefFree(vol); - VIR_FREE(devpath); - return retval; -} - - -static int -getNewStyleBlockDevice(const char *lun_path, - const char *block_name ATTRIBUTE_UNUSED, - char **block_device) -{ - char *block_path = NULL; - DIR *block_dir = NULL; - struct dirent *block_dirent = NULL; - int retval = -1; - int direrr; - - if (virAsprintf(&block_path, "%s/block", lun_path) < 0) - goto cleanup; - - VIR_DEBUG("Looking for block device in '%s'", block_path); - - if (virDirOpen(&block_dir, block_path) < 0) - goto cleanup; - - while ((direrr = virDirRead(block_dir, &block_dirent, block_path)) > 0) { - if (VIR_STRDUP(*block_device, block_dirent->d_name) < 0) - goto cleanup; - - VIR_DEBUG("Block device is '%s'", *block_device); - - break; - } - - if (direrr < 0) - goto cleanup; - - retval = 0; - - cleanup: - VIR_DIR_CLOSE(block_dir); - VIR_FREE(block_path); - return retval; -} - - -static int -getOldStyleBlockDevice(const char *lun_path ATTRIBUTE_UNUSED, - const char *block_name, - char **block_device) -{ - char *blockp = NULL; - int retval = -1; - - /* old-style; just parse out the sd */ - if (!(blockp = strrchr(block_name, ':'))) { - /* Hm, wasn't what we were expecting; have to give up */ - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to parse block name %s"), - block_name); - goto cleanup; - } else { - blockp++; - if (VIR_STRDUP(*block_device, blockp) < 0) - goto cleanup; - - VIR_DEBUG("Block device is '%s'", *block_device); - } - - retval = 0; - cleanup: - return retval; -} - - -/* - * Search a device entry for the "block" file - * - * Returns - * - * 0 => Found it - * -1 => Fatal error - * -2 => Didn't find in lun_path directory - */ -static int -getBlockDevice(uint32_t host, - uint32_t bus, - uint32_t target, - uint32_t lun, - char **block_device) -{ - char *lun_path = NULL; - DIR *lun_dir = NULL; - struct dirent *lun_dirent = NULL; - int retval = -1; - int direrr; - - *block_device = NULL; - - if (virAsprintf(&lun_path, "/sys/bus/scsi/devices/%u:%u:%u:%u", - host, bus, target, lun) < 0) - goto cleanup; - - if (virDirOpen(&lun_dir, lun_path) < 0) - goto cleanup; - - while ((direrr = virDirRead(lun_dir, &lun_dirent, lun_path)) > 0) { - if (STRPREFIX(lun_dirent->d_name, "block")) { - if (strlen(lun_dirent->d_name) == 5) { - if (getNewStyleBlockDevice(lun_path, - lun_dirent->d_name, - block_device) < 0) - goto cleanup; - } else { - if (getOldStyleBlockDevice(lun_path, - lun_dirent->d_name, - block_device) < 0) - goto cleanup; - } - break; - } - } - if (direrr < 0) - goto cleanup; - if (!*block_device) { - retval = -2; - goto cleanup; - } - - retval = 0; - - cleanup: - VIR_DIR_CLOSE(lun_dir); - VIR_FREE(lun_path); - return retval; -} - - -/* - * Process a Logical Unit entry from the scsi host device directory - * - * Returns: - * - * 0 => Found a valid entry - * -1 => Some sort of fatal error - * -2 => non-fatal error or a non-disk entry - */ -static int -processLU(virStoragePoolObjPtr pool, - uint32_t host, - uint32_t bus, - uint32_t target, - uint32_t lun) -{ - int retval = -1; - int device_type; - char *block_device = NULL; - - VIR_DEBUG("Processing LU %u:%u:%u:%u", - host, bus, target, lun); - - if (getDeviceType(host, bus, target, lun, &device_type) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to determine if %u:%u:%u:%u is a Direct-Access LUN"), - host, bus, target, lun); - return -1; - } - - /* We don't create volumes for devices other than disk and cdrom - * devices, but finding a device that isn't one of those types - * isn't an error, either. */ - if (!(device_type == VIR_STORAGE_DEVICE_TYPE_DISK || - device_type == VIR_STORAGE_DEVICE_TYPE_ROM)) - return -2; - - VIR_DEBUG("%u:%u:%u:%u is a Direct-Access LUN", - host, bus, target, lun); - - if ((retval = getBlockDevice(host, bus, target, lun, &block_device)) < 0) { - VIR_DEBUG("Failed to find block device for this LUN"); - return retval; - } - - retval = virStorageBackendSCSINewLun(pool, host, bus, target, lun, - block_device); - if (retval < 0) { - VIR_DEBUG("Failed to create new storage volume for %u:%u:%u:%u", - host, bus, target, lun); - goto cleanup; - } - - VIR_DEBUG("Created new storage volume for %u:%u:%u:%u successfully", - host, bus, target, lun); - - cleanup: - VIR_FREE(block_device); - return retval; -} - - -int -virStorageBackendSCSIFindLUs(virStoragePoolObjPtr pool, - uint32_t scanhost) -{ - int retval = 0; - uint32_t bus, target, lun; - const char *device_path = "/sys/bus/scsi/devices"; - DIR *devicedir = NULL; - struct dirent *lun_dirent = NULL; - char devicepattern[64]; - int found = 0; - - VIR_DEBUG("Discovering LUs on host %u", scanhost); - - virFileWaitForDevices(); - - if (virDirOpen(&devicedir, device_path) < 0) - return -1; - - snprintf(devicepattern, sizeof(devicepattern), "%u:%%u:%%u:%%u\n", scanhost); - - while ((retval = virDirRead(devicedir, &lun_dirent, device_path)) > 0) { - int rc; - - if (sscanf(lun_dirent->d_name, devicepattern, - &bus, &target, &lun) != 3) { - continue; - } - - VIR_DEBUG("Found possible LU '%s'", lun_dirent->d_name); - - rc = processLU(pool, scanhost, bus, target, lun); - if (rc == -1) { - retval = -1; - break; - } - if (rc == 0) - found++; - } - - VIR_DIR_CLOSE(devicedir); - - if (retval < 0) - return -1; - - VIR_DEBUG("Found %d LUs for pool %s", found, pool->def->name); - - return found; -} - static int virStorageBackendSCSITriggerRescan(uint32_t host) diff --git a/src/storage/storage_backend_scsi.h b/src/storage/storage_backend_scsi.h index 0984fd503..691b8cbf1 100644 --- a/src/storage/storage_backend_scsi.h +++ b/src/storage/storage_backend_scsi.h @@ -32,8 +32,4 @@ extern virStorageBackend virStorageBackendSCSI; -int -virStorageBackendSCSIFindLUs(virStoragePoolObjPtr pool, - uint32_t scanhost); - #endif /* __VIR_STORAGE_BACKEND_SCSI_H__ */ diff --git a/src/storage/storage_util.c b/src/storage/storage_util.c index 353dec4a8..7e69276a6 100644 --- a/src/storage/storage_util.c +++ b/src/storage/storage_util.c @@ -2913,3 +2913,452 @@ virStorageBackendDeviceIsEmpty(const char *devpath, return ret == 0; } + + +static char * +virStorageBackendSCSISerial(const char *dev) +{ + char *serial = NULL; +#ifdef WITH_UDEV + virCommandPtr cmd = virCommandNewArgList( + "/lib/udev/scsi_id", + "--replace-whitespace", + "--whitelisted", + "--device", dev, + NULL + ); + + /* Run the program and capture its output */ + virCommandSetOutputBuffer(cmd, &serial); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; +#endif + + if (serial && STRNEQ(serial, "")) { + char *nl = strchr(serial, '\n'); + if (nl) + *nl = '\0'; + } else { + VIR_FREE(serial); + ignore_value(VIR_STRDUP(serial, dev)); + } + +#ifdef WITH_UDEV + cleanup: + virCommandFree(cmd); +#endif + + return serial; +} + + +/* + * Attempt to create a new LUN + * + * Returns: + * + * 0 => Success + * -1 => Failure due to some sort of OOM or other fatal issue found when + * attempting to get/update information about a found volume + * -2 => Failure to find a stable path, not fatal, caller can try another + */ +static int +virStorageBackendSCSINewLun(virStoragePoolObjPtr pool, + uint32_t host ATTRIBUTE_UNUSED, + uint32_t bus, + uint32_t target, + uint32_t lun, + const char *dev) +{ + virStorageVolDefPtr vol = NULL; + char *devpath = NULL; + int retval = -1; + + /* Check if the pool is using a stable target path. The call to + * virStorageBackendStablePath will fail if the pool target path + * isn't stable and just return the strdup'd 'devpath' anyway. + * This would be indistinguishable to failing to find the stable + * path to the device if the virDirRead loop to search the + * target pool path for our devpath had failed. + */ + if (!virStorageBackendPoolPathIsStable(pool->def->target.path) && + !(STREQ(pool->def->target.path, "/dev") || + STREQ(pool->def->target.path, "/dev/"))) { + virReportError(VIR_ERR_INVALID_ARG, + _("unable to use target path '%s' for dev '%s'"), + NULLSTR(pool->def->target.path), dev); + goto cleanup; + } + + if (VIR_ALLOC(vol) < 0) + goto cleanup; + + vol->type = VIR_STORAGE_VOL_BLOCK; + + /* 'host' is dynamically allocated by the kernel, first come, + * first served, per HBA. As such it isn't suitable for use + * in the volume name. We only need uniqueness per-pool, so + * just leave 'host' out + */ + if (virAsprintf(&(vol->name), "unit:%u:%u:%u", bus, target, lun) < 0) + goto cleanup; + + if (virAsprintf(&devpath, "/dev/%s", dev) < 0) + goto cleanup; + + VIR_DEBUG("Trying to create volume for '%s'", devpath); + + /* Now figure out the stable path + * + * XXX this method is O(N) because it scans the pool target + * dir every time its run. Should figure out a more efficient + * way of doing this... + */ + if ((vol->target.path = virStorageBackendStablePath(pool, + devpath, + true)) == NULL) + goto cleanup; + + if (STREQ(devpath, vol->target.path) && + !(STREQ(pool->def->target.path, "/dev") || + STREQ(pool->def->target.path, "/dev/"))) { + + VIR_DEBUG("No stable path found for '%s' in '%s'", + devpath, pool->def->target.path); + + retval = -2; + goto cleanup; + } + + /* Allow a volume read failure to ignore or skip this block file */ + if ((retval = virStorageBackendUpdateVolInfo(vol, true, + VIR_STORAGE_VOL_OPEN_DEFAULT, + VIR_STORAGE_VOL_READ_NOERROR)) < 0) + goto cleanup; + + if (!(vol->key = virStorageBackendSCSISerial(vol->target.path))) + goto cleanup; + + pool->def->capacity += vol->target.capacity; + pool->def->allocation += vol->target.allocation; + + if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0) + goto cleanup; + + vol = NULL; + retval = 0; + + cleanup: + virStorageVolDefFree(vol); + VIR_FREE(devpath); + return retval; +} + + + +static int +getNewStyleBlockDevice(const char *lun_path, + const char *block_name ATTRIBUTE_UNUSED, + char **block_device) +{ + char *block_path = NULL; + DIR *block_dir = NULL; + struct dirent *block_dirent = NULL; + int retval = -1; + int direrr; + + if (virAsprintf(&block_path, "%s/block", lun_path) < 0) + goto cleanup; + + VIR_DEBUG("Looking for block device in '%s'", block_path); + + if (virDirOpen(&block_dir, block_path) < 0) + goto cleanup; + + while ((direrr = virDirRead(block_dir, &block_dirent, block_path)) > 0) { + if (VIR_STRDUP(*block_device, block_dirent->d_name) < 0) + goto cleanup; + + VIR_DEBUG("Block device is '%s'", *block_device); + + break; + } + + if (direrr < 0) + goto cleanup; + + retval = 0; + + cleanup: + VIR_DIR_CLOSE(block_dir); + VIR_FREE(block_path); + return retval; +} + + +static int +getOldStyleBlockDevice(const char *lun_path ATTRIBUTE_UNUSED, + const char *block_name, + char **block_device) +{ + char *blockp = NULL; + int retval = -1; + + /* old-style; just parse out the sd */ + if (!(blockp = strrchr(block_name, ':'))) { + /* Hm, wasn't what we were expecting; have to give up */ + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to parse block name %s"), + block_name); + goto cleanup; + } else { + blockp++; + if (VIR_STRDUP(*block_device, blockp) < 0) + goto cleanup; + + VIR_DEBUG("Block device is '%s'", *block_device); + } + + retval = 0; + cleanup: + return retval; +} + + +/* + * Search a device entry for the "block" file + * + * Returns + * + * 0 => Found it + * -1 => Fatal error + * -2 => Didn't find in lun_path directory + */ +static int +getBlockDevice(uint32_t host, + uint32_t bus, + uint32_t target, + uint32_t lun, + char **block_device) +{ + char *lun_path = NULL; + DIR *lun_dir = NULL; + struct dirent *lun_dirent = NULL; + int retval = -1; + int direrr; + + *block_device = NULL; + + if (virAsprintf(&lun_path, "/sys/bus/scsi/devices/%u:%u:%u:%u", + host, bus, target, lun) < 0) + goto cleanup; + + if (virDirOpen(&lun_dir, lun_path) < 0) + goto cleanup; + + while ((direrr = virDirRead(lun_dir, &lun_dirent, lun_path)) > 0) { + if (STRPREFIX(lun_dirent->d_name, "block")) { + if (strlen(lun_dirent->d_name) == 5) { + if (getNewStyleBlockDevice(lun_path, + lun_dirent->d_name, + block_device) < 0) + goto cleanup; + } else { + if (getOldStyleBlockDevice(lun_path, + lun_dirent->d_name, + block_device) < 0) + goto cleanup; + } + break; + } + } + if (direrr < 0) + goto cleanup; + if (!*block_device) { + retval = -2; + goto cleanup; + } + + retval = 0; + + cleanup: + VIR_DIR_CLOSE(lun_dir); + VIR_FREE(lun_path); + return retval; +} + + +/* Function to check if the type file in the given sysfs_path is a + * Direct-Access device (i.e. type 0). Return -1 on failure, type of + * the device otherwise. + */ +static int +getDeviceType(uint32_t host, + uint32_t bus, + uint32_t target, + uint32_t lun, + int *type) +{ + char *type_path = NULL; + char typestr[3]; + char *gottype, *p; + FILE *typefile; + int retval = 0; + + if (virAsprintf(&type_path, "/sys/bus/scsi/devices/%u:%u:%u:%u/type", + host, bus, target, lun) < 0) + goto out; + + typefile = fopen(type_path, "r"); + if (typefile == NULL) { + virReportSystemError(errno, + _("Could not find typefile '%s'"), + type_path); + /* there was no type file; that doesn't seem right */ + retval = -1; + goto out; + } + + gottype = fgets(typestr, 3, typefile); + VIR_FORCE_FCLOSE(typefile); + + if (gottype == NULL) { + virReportSystemError(errno, + _("Could not read typefile '%s'"), + type_path); + /* we couldn't read the type file; have to give up */ + retval = -1; + goto out; + } + + /* we don't actually care about p, but if you pass NULL and the last + * character is not \0, virStrToLong_i complains + */ + if (virStrToLong_i(typestr, &p, 10, type) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Device type '%s' is not an integer"), + typestr); + /* Hm, type wasn't an integer; seems strange */ + retval = -1; + goto out; + } + + VIR_DEBUG("Device type is %d", *type); + + out: + VIR_FREE(type_path); + return retval; +} + + +/* + * Process a Logical Unit entry from the scsi host device directory + * + * Returns: + * + * 0 => Found a valid entry + * -1 => Some sort of fatal error + * -2 => non-fatal error or a non-disk entry + */ +static int +processLU(virStoragePoolObjPtr pool, + uint32_t host, + uint32_t bus, + uint32_t target, + uint32_t lun) +{ + int retval = -1; + int device_type; + char *block_device = NULL; + + VIR_DEBUG("Processing LU %u:%u:%u:%u", + host, bus, target, lun); + + if (getDeviceType(host, bus, target, lun, &device_type) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to determine if %u:%u:%u:%u is a Direct-Access LUN"), + host, bus, target, lun); + return -1; + } + + /* We don't create volumes for devices other than disk and cdrom + * devices, but finding a device that isn't one of those types + * isn't an error, either. */ + if (!(device_type == VIR_STORAGE_DEVICE_TYPE_DISK || + device_type == VIR_STORAGE_DEVICE_TYPE_ROM)) + return -2; + + VIR_DEBUG("%u:%u:%u:%u is a Direct-Access LUN", + host, bus, target, lun); + + if ((retval = getBlockDevice(host, bus, target, lun, &block_device)) < 0) { + VIR_DEBUG("Failed to find block device for this LUN"); + return retval; + } + + retval = virStorageBackendSCSINewLun(pool, host, bus, target, lun, + block_device); + if (retval < 0) { + VIR_DEBUG("Failed to create new storage volume for %u:%u:%u:%u", + host, bus, target, lun); + goto cleanup; + } + + VIR_DEBUG("Created new storage volume for %u:%u:%u:%u successfully", + host, bus, target, lun); + + cleanup: + VIR_FREE(block_device); + return retval; +} + + +int +virStorageBackendSCSIFindLUs(virStoragePoolObjPtr pool, + uint32_t scanhost) +{ + int retval = 0; + uint32_t bus, target, lun; + const char *device_path = "/sys/bus/scsi/devices"; + DIR *devicedir = NULL; + struct dirent *lun_dirent = NULL; + char devicepattern[64]; + int found = 0; + + VIR_DEBUG("Discovering LUs on host %u", scanhost); + + virFileWaitForDevices(); + + if (virDirOpen(&devicedir, device_path) < 0) + return -1; + + snprintf(devicepattern, sizeof(devicepattern), "%u:%%u:%%u:%%u\n", scanhost); + + while ((retval = virDirRead(devicedir, &lun_dirent, device_path)) > 0) { + int rc; + + if (sscanf(lun_dirent->d_name, devicepattern, + &bus, &target, &lun) != 3) { + continue; + } + + VIR_DEBUG("Found possible LU '%s'", lun_dirent->d_name); + + rc = processLU(pool, scanhost, bus, target, lun); + if (rc == -1) { + retval = -1; + break; + } + if (rc == 0) + found++; + } + + VIR_DIR_CLOSE(devicedir); + + if (retval < 0) + return -1; + + VIR_DEBUG("Found %d LUs for pool %s", found, pool->def->name); + + return found; +} diff --git a/src/storage/storage_util.h b/src/storage/storage_util.h index 0555ae1e8..8bf0f42df 100644 --- a/src/storage/storage_util.h +++ b/src/storage/storage_util.h @@ -145,4 +145,7 @@ virStorageBackendCreateQemuImgCmdFromVol(virConnectPtr conn, int imgformat, const char *secretPath); +int virStorageBackendSCSIFindLUs(virStoragePoolObjPtr pool, + uint32_t scanhost); + #endif /* __VIR_STORAGE_UTIL_H__ */ -- 2.11.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list