On Thu, Mar 26, 2009 at 05:55:48PM -0400, David Allan wrote: > It does not attempt to add a volume if it cannot find a stable > path for a particular LU, for example, if the user specifies a > target path by-id and the LU is one path of a multipath device. This will cause a regression in current behaviour - if a device does not have a stable path, the semantics are that we just expose the raw path /dev/sdXX. > diff --git a/src/storage_backend_scsi.c b/src/storage_backend_scsi.c > new file mode 100644 > index 0000000..62c05ae > +static int > +processLU(virConnectPtr conn, > + virStoragePoolObjPtr pool, > + uint32_t host, > + uint32_t bus, > + uint32_t target, > + uint32_t lun) > +{ > + char *type_path = NULL; > + int retval = 0; > + int device_type; > + char *block_device = NULL; > + > + VIR_DEBUG(_("Processing LU %u:%u:%u:%u"), > + host, bus, target, lun); > + > + if (getDeviceType(conn, host, bus, target, lun, &device_type) < 0) { > + virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, > + _("Failed to determine if %u:%u:%u:%u is a Direct-Access LUN"), > + host, bus, target, lun); > + retval = -1; > + goto out; > + } > + > + /* We don't use anything except Direct-Access devices, but finding > + * one isn't an error, either. */ > + if (device_type != 0) { > + retval = 0; > + goto out; > + } This is not quite right - it is valid for LUNs to have a non-zero device type. For example, defining a SCSI pool for the IDE controller associated with the CDROM device causes it not to expose the CDROM device LUN. This is because it has a device type of 0x5 instead of 0x0 These values in sysfs come from these constants #define TYPE_DISK 0x00 #define TYPE_TAPE 0x01 #define TYPE_PRINTER 0x02 #define TYPE_PROCESSOR 0x03 /* HP scanners use this */ #define TYPE_WORM 0x04 /* Treated as ROM by our system */ #define TYPE_ROM 0x05 #define TYPE_SCANNER 0x06 #define TYPE_MOD 0x07 /* Magneto-optical disk - * - treated as TYPE_DISK */ #define TYPE_MEDIUM_CHANGER 0x08 #define TYPE_COMM 0x09 /* Communications device */ #define TYPE_RAID 0x0c #define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ #define TYPE_RBC 0x0e #define TYPE_NO_LUN 0x7f So we probably want to allow TYPE_DISK, TYPE_TAPE, TYPE_WORM, TYPE_ROM, TYPE_MOD. The Linux iSCSI target exposes one special 'controller' device as LUN-0 For some reason they have given this TYPE_RAID, so we need to skip this one. > + > + VIR_DEBUG(_("%u:%u:%u:%u is a Direct-Access LUN"), > + host, bus, target, lun); > + > + if (getBlockDevice(conn, host, bus, target, lun, &block_device) < 0) { > + goto out; > + } > + > + if (virStorageBackendSCSINewLun(conn, pool, > + host, bus, target, lun, > + block_device) < 0) { > + VIR_DEBUG(_("Failed to create new storage volume for %u:%u:%u:%u"), > + host, bus, target, lun); > + retval = -1; > + goto out; > + } > + > + VIR_DEBUG(_("Created new storage volume for %u:%u:%u:%u successfully"), > + host, bus, target, lun); > + > + VIR_FREE(type_path); > + > +out: > + return retval; > +} > + > + > +static int > +virStorageBackendSCSIFindLUs(virConnectPtr conn, > + virStoragePoolObjPtr pool, > + uint32_t scanhost, > + uint32_t scanbus, > + uint32_t scantarget) > +{ > + int retval = 0; > + uint32_t host, bus, target, lun; > + char *target_path = NULL; > + DIR *targetdir = NULL; > + struct dirent *lun_dirent = NULL; > + > + VIR_DEBUG(_("Discovering LUs on host %u bus %u target %u"), > + scanhost, scanbus, scantarget); > + > + if (virAsprintf(&target_path, "/sys/bus/scsi/devices/target%u:%u:%u", > + scanhost, scanbus, scantarget) < 0) { > + virReportOOMError(conn); > + goto out; > + } This unfortauntely does not work on RHEL5, because there are no targetX.X.X links here. Only the LUNs appear in this directory. The location which appears to be present on both old and new kernels is under: /sys/class/scsi_host/host0/device/targetX.X.X This appears to be present for both SCSI and iSCSI hosts. > + > + targetdir = opendir(target_path); > + > + if (targetdir == NULL) { > + virReportSystemError(conn, errno, > + _("Failed to opendir path '%s'"), target_path); > + retval = -1; > + goto out; > + } > + > + while ((lun_dirent = readdir(targetdir))) { > + if (sscanf(lun_dirent->d_name, "%u:%u:%u:%u\n", > + &host, &bus, &target, &lun) != 4) { > + continue; > + } > + > + VIR_DEBUG(_("Found LU '%s'"), lun_dirent->d_name); > + > + processLU(conn, pool, host, bus, target, lun); > + } > + > + closedir(targetdir); > + > +out: > + VIR_FREE(target_path); > + return retval; > +} > + > + > +int > +virStorageBackendSCSIFindTargets(virConnectPtr conn, > + virStoragePoolObjPtr pool, > + const char *sysfs_path, > + const char *pattern) > +{ > + int retval = 0; > + uint32_t host, bus, target; > + DIR *sysdir = NULL; > + struct dirent *dirent = NULL; > + > + VIR_DEBUG(_("Discovering targets in '%s'"), sysfs_path); > + > + sysdir = opendir(sysfs_path); > + > + if (sysdir == NULL) { > + virReportSystemError(conn, errno, > + _("Failed to opendir path '%s'"), sysfs_path); > + retval = -1; > + goto out; > + } > + > + while ((dirent = readdir(sysdir))) { > + if (STREQLEN(dirent->d_name, pattern, strlen(pattern))) { > + if (sscanf(dirent->d_name, > + "target%u:%u:%u", &host, &bus, &target) != 3) { > + VIR_DEBUG(_("Failed to parse target '%s'"), dirent->d_name); > + retval = -1; > + break; > + } > + virStorageBackendSCSIFindLUs(conn, pool, host, bus, target); > + } > + } > + > + closedir(sysdir); > +out: > + return retval; > +} > + > + > +static int > +virStorageBackendSCSIRefreshPool(virConnectPtr conn, > + virStoragePoolObjPtr pool) > +{ > + char targetN[64]; > + int retval = 0; > + uint32_t host; > + > + pool->def->allocation = pool->def->capacity = pool->def->available = 0; > + > + virStorageBackendWaitForDevices(conn); > + > + if (sscanf(pool->def->source.adapter, "host%u", &host) != 1) { > + VIR_DEBUG(_("Failed to get host number from '%s'"), pool->def->source.adapter); > + retval = -1; > + goto out; > + } > + > + VIR_DEBUG(_("Scanning host%u"), host); > + > + snprintf(targetN, sizeof(targetN), "target%u", host); > + > + virStorageBackendSCSIFindTargets(conn, pool, "/sys/bus/scsi/devices", targetN); This path doesn't work for same reason as earlier comment - targetX.X.X does not exist under this location in RHEL-5 vintage kernels. Since you already have the 'hostX' name, you can just go straight to /sys/class/scsi_host/host0/device to find the target.X.X.X name. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list