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

Reply via email to