This patch fixes two issues. It changes how the known zeroed state is tracked so that it works reliably on SIS64 adapters. We previously had been relying on the bus/target/lun value to be consistent when a JBOD disk was reformatted to a RAID capable disk. This is true for SIS32 adapters, since this tuple is tied to a physical location. For SIS64, however, this tuple is generated by the ipr driver, so is often not the same value when a JBOD is converted to RAID. Instead, we change to always use the device_id attribute, which is generated by the adapter based on the LUN WWN of the disk. This patch also eliminates a hang that can occur when formatting disks if a second iprconfig instance is started concurently.
Signed-off-by: Brian King <brk...@linux.vnet.ibm.com> --- iprconfig.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++---- iprlib.c | 86 +++++++++++++++++++++++++++++++++++++----------------------- iprlib.h | 4 ++ 3 files changed, 124 insertions(+), 38 deletions(-) diff -puN iprlib.c~iprutils_known_zeroed_device_id iprlib.c --- iprutils.fixes/iprlib.c~iprutils_known_zeroed_device_id 2016-08-09 21:37:06.369559147 -0500 +++ iprutils.fixes-bjking1/iprlib.c 2016-08-11 10:49:36.899204047 -0500 @@ -569,8 +569,7 @@ struct sysfs_dev * ipr_find_sysfs_dev(st return NULL; for (sdev = head; sdev; sdev = sdev->next) { - if (!strcmp(sdev->sysfs_device_name, - dev->scsi_dev_data->sysfs_device_name)) + if (sdev->device_id == dev->scsi_dev_data->device_id) break; } @@ -593,8 +592,7 @@ struct ipr_dev *ipr_sysfs_dev_to_dev(str for_each_dev(ioa, dev) { if (!dev->scsi_dev_data) continue; - if (!strcmp(sdev->sysfs_device_name, - dev->scsi_dev_data->sysfs_device_name)) + if (sdev->device_id == dev->scsi_dev_data->device_id) return dev; } } @@ -647,8 +645,7 @@ void ipr_add_sysfs_dev(struct ipr_dev *d if (!sdev) { sdev = calloc(1, sizeof(struct sysfs_dev)); - strcpy(sdev->sysfs_device_name, - dev->scsi_dev_data->sysfs_device_name); + sdev->device_id = dev->scsi_dev_data->device_id; if (!(*head)) { *tail = *head = sdev; @@ -3758,7 +3755,7 @@ int ipr_device_lock(struct ipr_dev *dev) return -ENOENT; if (dev->locked) { - scsi_err(dev, "Device already locked\n"); + scsi_dbg(dev, "Device already locked\n"); return -EINVAL; } @@ -3769,7 +3766,7 @@ int ipr_device_lock(struct ipr_dev *dev) return errno; } - rc = flock(fd, LOCK_EX); + rc = flock(fd, LOCK_EX | LOCK_NB); if (rc) { if (!strcmp(tool_name, "iprconfig") || ipr_debug) @@ -5873,6 +5870,32 @@ static int wait_for_dev(char *name) return -ETIMEDOUT; } +int get_sg_name(struct scsi_dev_data *scsi_dev) +{ + int i, rc = -ENXIO; + DIR *dirfd; + struct dirent *dent; + char devpath[PATH_MAX]; + + sprintf(devpath, "/sys/class/scsi_device/%s/device/scsi_generic", + scsi_dev->sysfs_device_name); + dirfd = opendir(devpath); + if (!dirfd) + return -ENXIO; + while((dent = readdir(dirfd)) != NULL) { + if (dent->d_name[0] == '.') + continue; + if (strncmp(dent->d_name, "sg", 2)) + continue; + sprintf(scsi_dev->gen_name, "/dev/%s", + dent->d_name); + rc = 0; + break; + } + closedir(dirfd); + return rc; +} + /** * get_sg_names - waits for sg devices to become available * @num_devs: number of devices @@ -5883,27 +5906,8 @@ static int wait_for_dev(char *name) static void get_sg_names(int num_devs) { int i; - DIR *dirfd; - struct dirent *dent; - char devpath[PATH_MAX]; - - for (i = 0; i < num_devs; i++) { - sprintf(devpath, "/sys/class/scsi_device/%s/device/scsi_generic", - scsi_dev_table[i].sysfs_device_name); - dirfd = opendir(devpath); - if (!dirfd) - continue; - while((dent = readdir(dirfd)) != NULL) { - if (dent->d_name[0] == '.') - continue; - if (strncmp(dent->d_name, "sg", 2)) - continue; - sprintf(scsi_dev_table[i].gen_name, "/dev/%s", - dent->d_name); - break; - } - closedir(dirfd); - } + for (i = 0; i < num_devs; i++) + get_sg_name(&scsi_dev_table[i]); } /** @@ -7492,14 +7496,24 @@ int ipr_known_zeroed_is_saved(struct ipr int ipr_set_format_completed_bit(struct ipr_dev *dev) { - int len; + int len, retries = 5; struct ipr_mode_pages mode_pages; struct ipr_ioa_mode_page *page; + scsi_dbg(dev, "Setting device formatted bit. Device ID=%lx\n", dev->scsi_dev_data->device_id); + memset(&mode_pages, 0, sizeof(mode_pages)); - if (ipr_mode_sense(dev, 0x20, &mode_pages)) + do { + if (!ipr_mode_sense(dev, 0x20, &mode_pages)) + break; + sleep(1); + } while (retries--); + + if (!retries) { + scsi_info(dev, "Page 20 mode sense failed. Device ID=%lx\n", dev->scsi_dev_data->device_id); return -EIO; + } page = (struct ipr_ioa_mode_page *) (((u8 *)&mode_pages) + mode_pages.hdr.block_desc_len + @@ -7513,8 +7527,16 @@ int ipr_set_format_completed_bit(struct mode_pages.hdr.device_spec_parms = 0; page->hdr.parms_saveable = 0; - if (ipr_mode_select(dev, &mode_pages, len)) + do { + if (!ipr_mode_select(dev, &mode_pages, len)) + break; + sleep(1); + } while (retries--); + + if (!retries) { + scsi_info(dev, "Page 20 mode select failed. Device ID=%lx\n", dev->scsi_dev_data->device_id); return -EIO; + } return 0; } diff -puN iprconfig.c~iprutils_known_zeroed_device_id iprconfig.c --- iprutils.fixes/iprconfig.c~iprutils_known_zeroed_device_id 2016-08-09 21:43:58.130829942 -0500 +++ iprutils.fixes-bjking1/iprconfig.c 2016-08-11 12:09:16.309888850 -0500 @@ -37,6 +37,7 @@ char *tool_name = "iprconfig"; struct devs_to_init_t { struct ipr_dev *dev; struct ipr_ioa *ioa; + u64 device_id; int new_block_size; int cmplt; int do_init; @@ -222,6 +223,63 @@ static int can_format_for_raid(struct ip return 1; } +static int wait_for_formatted_af_dasd(int timeout_in_secs) +{ + struct devs_to_init_t *dev = dev_init_head; + struct scsi_dev_data *scsi_devs; + struct scsi_dev_data *scsi_dev_data; + int num_devs, j, af_found, jbod2af_formats, num_secs; + u64 device_id; + + for (num_secs = 0; num_secs < timeout_in_secs; timeout_in_secs++) { + af_found = 0; + jbod2af_formats = 0; + scsi_devs = NULL; + + num_devs = get_scsi_dev_data(&scsi_devs); + + for_each_dev_to_init(dev) { + if (!dev->dev || !dev->ioa) + continue; + if (!dev->dev->scsi_dev_data) + continue; + if (dev->dev_type != IPR_JBOD_DASD_DEVICE) + continue; + if (!ipr_is_af_blk_size(dev->ioa, dev->new_block_size)) + continue; + if (!dev->do_init) + continue; + + jbod2af_formats++; + device_id = dev->dev->scsi_dev_data->device_id; + + for (j = 0, scsi_dev_data = scsi_devs; + j < num_devs; j++, scsi_dev_data++) { + if (scsi_dev_data->host != dev->ioa->host_num) + continue; + if (get_sg_name(scsi_dev_data)) + continue; + if (scsi_dev_data->type != IPR_TYPE_AF_DISK) + continue; + if (dev->device_id != scsi_dev_data->device_id) + continue; + + scsi_dbg(dev->dev, "Format complete. AF DASD found. New Device ID=%lx, Old Device ID=%lx\n", + scsi_dev_data->device_id, dev->device_id); + af_found++; + break; + } + } + + free(scsi_devs); + if (af_found == jbod2af_formats) + break; + sleep(1); + } + + return ((af_found == jbod2af_formats) ? 0 : -ETIMEDOUT); +} + /** * flush_stdscr - * @@ -6556,6 +6614,10 @@ static void add_format_device(struct ipr dev_init_tail->dev_type = IPR_JBOD_DASD_DEVICE; dev_init_tail->new_block_size = blk_size; dev_init_tail->dev = dev; + dev_init_tail->device_id = dev->scsi_dev_data->device_id; + + scsi_dbg(dev, "Formatting device to %d bytes/block. Device ID=%lx\n", + blk_size, dev_init_tail->device_id); } /** @@ -8840,8 +8902,9 @@ static int dev_init_complete(u8 num_devs return 51 | EXIT_FLAG; } - format_done = 1; - check_current_config(false); + format_done = 1; + wait_for_formatted_af_dasd(30); + check_current_config(false); if (!pid) exit(0); @@ -14012,7 +14075,6 @@ static int format_for_raid(char **args, } rc = send_dev_inits(NULL); - set_devs_format_completed(); free_devs_to_init(); return IPR_XLATE_DEV_FMT_RC(rc); } @@ -14197,8 +14259,8 @@ IOA write cache. Use --force to force c for (sdev = head_sdev; sdev; sdev = sdev->next) { dev = ipr_sysfs_dev_to_dev(sdev); if (!dev) { - syslog(LOG_ERR, _("Cannot find device: %s\n"), - sdev->sysfs_device_name); + syslog(LOG_ERR, _("Cannot find device: %lx\n"), + sdev->device_id); return -EIO; } diff -puN iprlib.h~iprutils_known_zeroed_device_id iprlib.h --- iprutils.fixes/iprlib.h~iprutils_known_zeroed_device_id 2016-08-12 10:49:09.090367101 -0500 +++ iprutils.fixes-bjking1/iprlib.h 2016-08-12 10:49:12.516371008 -0500 @@ -297,7 +297,7 @@ extern struct sysfs_dev *tail_zdev; extern enum system_p_mode power_cur_mode; struct sysfs_dev { - char sysfs_device_name[PATH_MAX]; + u64 device_id; struct sysfs_dev *next, *prev; }; @@ -2953,6 +2953,8 @@ int ipr_jbod_sysfs_bind(struct ipr_dev * int ipr_max_queue_depth(struct ipr_ioa *ioa, int num_devs, int num_ssd_devs); void ipr_count_devices_in_vset(struct ipr_dev *, int *num_devs, int *ssd_num_devs); int ipr_known_zeroed_is_saved(struct ipr_dev *); +int get_sg_name(struct scsi_dev_data *); +int ipr_sg_inquiry(struct scsi_dev_data *, u8, void *, u8); static inline u32 ipr_get_dev_res_handle(struct ipr_ioa *ioa, struct ipr_dev_record *dev_rcd) { _ ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. http://sdm.link/zohodev2dev _______________________________________________ Iprdd-devel mailing list Iprdd-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/iprdd-devel