I am enclosing a patch for you folks to test out.  The actual
patch contains a number of accumulated things that I have picked up from
linux-scsi - the main thing I am interested in is the > 7 lun stuff in
scsi-scan.c.

        I have a couple of questions related to this.  The first is that I
have essentially lifted the hardcoded limit of 8 in the lun scan - it now
follows the maximum lun specified for the host, which would normally be 8
except for fibre channel and any other variants that support more luns.
My question is what should happen in the instance of a changer listed in
the blacklist where we know there to be exactly 8 lun.  Thus the question
is whether we should interpret BLIST_FORCELUN as limiting the number of
luns to 8 - much like BLIST_MAX5LUN.

        The second question has to do with the correct setting for the 2nd
command byte.  This is typically set to something like:

        scsi_cmd[1] = (lun << 5) & 0xe0;

which is obviously broken in the event that the number of luns is > 8.
This patch starts to clean this up by forcing scsi_cmd[1] to 0 in such
instances.  The actual change came from someone else - my question is what
is the appropriate setting for scsi_cmd[1]?  A value of 0 seems
reasonable, I guess.

        Finally, Doug Gilbert pointed out that the SCSI_IOCTL_GET_IDLUN
ioctl is broke for > 255 in target, lun, channel, etc, and there is no
checking for overflow.  I believe I should go in and validate the ranges
of all of the things we are stuffing into various bytes, and if one of the
fields doesn't fit in a byte, that the ioctl fail.  In the long run, this
ioctl needs to be replaced with something that uses larger fields for
these numbers...

-Eric


-- 
"The world was a library, and its books were the stones, leaves,
 brooks, grass, and the birds of the earth.   We learned to do what only
 a student of nature ever learns, and that was to feel beauty."
                        Chief Luther Standing Bear - Teton Sioux
Index: linux/CREDITS
diff -u linux/CREDITS:1.1.1.23 linux/CREDITS:1.24
--- linux/CREDITS:1.1.1.23      Fri Feb  2 00:33:13 2001
+++ linux/CREDITS       Fri Feb  2 00:44:31 2001
@@ -2955,8 +2955,8 @@
 W: http://www.andante.org
 D: General kernel hacker
 D: SCSI iso9660 and ELF
-S: 17 Canterbury Square #101
-S: Alexandria, Virginia 22304
+S: 6389 Hawk View Lane
+S: Alexandria, Virginia 22312
 S: USA
 
 N: Niibe Yutaka
Index: linux/drivers/scsi/scsi_error.c
diff -u linux/drivers/scsi/scsi_error.c:1.1.1.12 linux/drivers/scsi/scsi_error.c:1.17
--- linux/drivers/scsi/scsi_error.c:1.1.1.12    Mon Jan 22 08:30:43 2001
+++ linux/drivers/scsi/scsi_error.c     Mon Jan 22 20:09:09 2001
@@ -549,6 +549,9 @@
        /*
         * Hey, we are done.  Let's look to see what happened.
         */
+       SCSI_LOG_ERROR_RECOVERY(3,
+               printk("scsi_test_unit_ready: SCpnt %p eh_state %x\n",
+               SCpnt, SCpnt->eh_state));
        return SCpnt->eh_state;
 }
 
@@ -671,11 +674,8 @@
                spin_unlock_irqrestore(&io_request_lock, flags);
 
                SCpnt->result = temp;
-               if (scsi_eh_completed_normally(SCpnt)) {
-                       SCpnt->eh_state = SUCCESS;
-               } else {
-                       SCpnt->eh_state = FAILED;
-               }
+               /* Fall through to code below to examine status. */
+               SCpnt->eh_state = SUCCESS;
        }
 
        /*
@@ -683,7 +683,10 @@
         * did complete normally.
         */
        if (SCpnt->eh_state == SUCCESS) {
-               switch (scsi_eh_completed_normally(SCpnt)) {
+               int ret = scsi_eh_completed_normally(SCpnt);
+               SCSI_LOG_ERROR_RECOVERY(3,
+                       printk("scsi_send_eh_cmnd: scsi_eh_completed_normally %x\n", 
+ret));
+               switch (ret) {
                case SUCCESS:
                        SCpnt->eh_state = SUCCESS;
                        break;
@@ -1104,7 +1107,6 @@
  */
 STATIC int scsi_eh_completed_normally(Scsi_Cmnd * SCpnt)
 {
-       int rtn;
        /*
         * First check the host byte, to see if there is anything in there
         * that would indicate what we need to do.
@@ -1144,11 +1146,7 @@
        case COMMAND_TERMINATED:
                return SUCCESS;
        case CHECK_CONDITION:
-               rtn = scsi_check_sense(SCpnt);
-               if (rtn == NEEDS_RETRY) {
-                       return FAILED;
-               }
-               return rtn;
+               return scsi_check_sense(SCpnt);
        case CONDITION_GOOD:
        case INTERMEDIATE_GOOD:
        case INTERMEDIATE_C_GOOD:
@@ -1634,8 +1632,10 @@
                                                 * FIXME(eric) - is this really the 
correct thing to do?
                                                 */
                                                if (rtn != SUCCESS) {
-                                                       SCloop->device->online = 
FALSE;
-                                                       SCloop->host->host_failed--;
+                                                       printk(KERN_INFO "scsi: device 
+set offline - not ready or command retry failed after bus reset: host %d channel %d 
+id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
+
+                                                       SDloop->online = FALSE;
+                                                       SDloop->host->host_failed--;
                                                        
scsi_eh_finish_command(&SCdone, SCloop);
                                                }
                                        }
@@ -1725,8 +1725,9 @@
                                                        }
                                                }
                                                if (rtn != SUCCESS) {
-                                                       SCloop->device->online = 
FALSE;
-                                                       SCloop->host->host_failed--;
+                                                       printk(KERN_INFO "scsi: device 
+set offline - not ready or command retry failed after host reset: host %d channel %d 
+id %d lun %d\n", SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
+                                                       SDloop->online = FALSE;
+                                                       SDloop->host->host_failed--;
                                                        
scsi_eh_finish_command(&SCdone, SCloop);
                                                }
                                        }
@@ -1753,7 +1754,11 @@
        for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
                for (SCloop = SDpnt->device_queue; SCloop; SCloop = SCloop->next) {
                        if (SCloop->state == SCSI_STATE_FAILED || SCloop->state == 
SCSI_STATE_TIMEOUT) {
-                               SCloop->device->online = FALSE;
+                               SDloop = SCloop->device;
+                               if (SDloop->online == TRUE) {
+                                       printk(KERN_INFO "scsi: device set offline - 
+command error recover failed: host %d channel %d id %d lun %d\n", 
+SDloop->host->host_no, SDloop->channel, SDloop->id, SDloop->lun);
+                                       SDloop->online = FALSE;
+                               }
 
                                /*
                                 * This should pass the failure up to the top level 
driver, and
@@ -1765,7 +1770,7 @@
                                        SCloop->result |= (DRIVER_TIMEOUT << 24);
                                }
                                SCSI_LOG_ERROR_RECOVERY(3, printk("Finishing command 
for device %d %x\n",
-                                   SCloop->device->id, SCloop->result));
+                                   SDloop->id, SCloop->result));
 
                                scsi_eh_finish_command(&SCdone, SCloop);
                        }
Index: linux/drivers/scsi/scsi_scan.c
diff -u linux/drivers/scsi/scsi_scan.c:1.1.1.10 linux/drivers/scsi/scsi_scan.c:1.25
--- linux/drivers/scsi/scsi_scan.c:1.1.1.10     Wed Sep 20 19:47:57 2000
+++ linux/drivers/scsi/scsi_scan.c      Fri Feb  2 00:26:58 2001
@@ -40,9 +40,10 @@
 #define BLIST_ISROM            0x200
 
 static void print_inquiry(unsigned char *data);
-static int scan_scsis_single(int channel, int dev, int lun, int *max_scsi_dev,
-               int *sparse_lun, Scsi_Device ** SDpnt,
-                            struct Scsi_Host *shpnt, char *scsi_result);
+static int scan_scsis_single(unsigned int channel, unsigned int dev,
+               unsigned int lun, unsigned int *max_scsi_dev,
+               unsigned int *sparse_lun, Scsi_Device ** SDpnt,
+               struct Scsi_Host *shpnt, char *scsi_result);
 
 struct dev_info {
        const char *vendor;
@@ -153,29 +154,31 @@
        {NULL, NULL, NULL}
 };
 
+#define MAX_SCSI_LUNS 0xFFFFFFFF
+
 #ifdef CONFIG_SCSI_MULTI_LUN
-static int max_scsi_luns = 8;
+static unsigned int max_scsi_luns = MAX_SCSI_LUNS;
 #else
-static int max_scsi_luns = 1;
+static unsigned int max_scsi_luns = 1;
 #endif
 
 #ifdef MODULE
 
 MODULE_PARM(max_scsi_luns, "i");
-MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 8)");
+MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 2^32-1)");
 
 #else
 
 static int __init scsi_luns_setup(char *str)
 {
-       int tmp;
+       unsigned int tmp;
 
        if (get_option(&str, &tmp) == 1) {
                max_scsi_luns = tmp;
                return 1;
        } else {
                printk("scsi_luns_setup : usage max_scsi_luns=n "
-                      "(n should be between 1 and 8)\n");
+                      "(n should be between 1 and 2^32-1)\n");
                return 0;
        }
 }
@@ -263,14 +266,14 @@
                       uint hlun)
 {
        uint channel;
-       int dev;
-       int lun;
-       int max_dev_lun;
+       unsigned int dev;
+       unsigned int lun;
+       unsigned int max_dev_lun;
        unsigned char *scsi_result;
        unsigned char scsi_result0[256];
        Scsi_Device *SDpnt;
        Scsi_Device *SDtail;
-       int sparse_lun;
+       unsigned int sparse_lun;
 
        scsi_result = NULL;
 
@@ -460,8 +463,9 @@
  * Returning 0 means Please don't ask further for lun!=0, 1 means OK go on.
  * Global variables used : scsi_devices(linked list)
  */
-static int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun,
-              int *sparse_lun, Scsi_Device ** SDpnt2, 
+static int scan_scsis_single(unsigned int channel, unsigned int dev,
+               unsigned int lun, unsigned int *max_dev_lun,
+               unsigned int *sparse_lun, Scsi_Device ** SDpnt2, 
                      struct Scsi_Host *shpnt, char *scsi_result)
 {
        char devname[64];
@@ -505,7 +509,9 @@
         * Build an INQUIRY command block.
         */
        scsi_cmd[0] = INQUIRY;
-       scsi_cmd[1] = (lun << 5) & 0xe0;
+       if (shpnt->max_lun <= 8)
+               scsi_cmd[1] = (lun << 5) & 0xe0;
+       else    scsi_cmd[1] = 0;        /* any other idea? */
        scsi_cmd[2] = 0;
        scsi_cmd[3] = 0;
        scsi_cmd[4] = 255;
@@ -661,7 +667,9 @@
                printk("Unlocked floptical drive.\n");
                SDpnt->lockable = 0;
                scsi_cmd[0] = MODE_SENSE;
-               scsi_cmd[1] = (lun << 5) & 0xe0;
+               if (shpnt->max_lun <= 8)
+                       scsi_cmd[1] = (lun << 5) & 0xe0;
+               else    scsi_cmd[1] = 0;        /* any other idea? */
                scsi_cmd[2] = 0x2e;
                scsi_cmd[3] = 0;
                scsi_cmd[4] = 0x2a;
@@ -744,7 +752,19 @@
         * other settings, and scan all of them.
         */
        if (bflags & BLIST_SPARSELUN) {
-               *max_dev_lun = 8;
+               /*
+                * Scanning MAX_SCSI_LUNS units would be a bad idea.
+                * Any better idea?
+                * I think we need REPORT LUNS in future to avoid scanning
+                * of unused LUNs. But, that is another item.
+                *
+                * FIXME(eric) - perhaps this should be a kernel configurable?
+                */
+               if (*max_dev_lun < shpnt->max_lun)
+                       *max_dev_lun = shpnt->max_lun;
+               else    if ((max_scsi_luns >> 1) >= *max_dev_lun)
+                               *max_dev_lun += shpnt->max_lun;
+                       else    *max_dev_lun = max_scsi_luns;
                *sparse_lun = 1;
                return 1;
        }
@@ -753,7 +773,17 @@
         * settings, and scan all of them.
         */
        if (bflags & BLIST_FORCELUN) {
-               *max_dev_lun = 8;
+               /* 
+                * Scanning MAX_SCSI_LUNS units would be a bad idea.
+                * Any better idea?
+                * I think we need REPORT LUNS in future to avoid scanning
+                * of unused LUNs. But, that is another item.
+                */
+               if (*max_dev_lun < shpnt->max_lun)
+                       *max_dev_lun = shpnt->max_lun;
+               else    if ((max_scsi_luns >> 1) >= *max_dev_lun)
+                               *max_dev_lun += shpnt->max_lun;
+                       else    *max_dev_lun = max_scsi_luns;
                return 1;
        }
        /*
Index: linux/drivers/scsi/sd.c
diff -u linux/drivers/scsi/sd.c:1.1.1.23 linux/drivers/scsi/sd.c:1.30
--- linux/drivers/scsi/sd.c:1.1.1.23    Sat Nov  4 13:23:23 2000
+++ linux/drivers/scsi/sd.c     Fri Feb  2 00:10:29 2001
@@ -798,9 +798,9 @@
                                SRpnt->sr_data_direction = SCSI_DATA_READ;
                                scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
                                            0/*512*/, SD_TIMEOUT, MAX_RETRIES);
+                                spintime_value = jiffies;
                        }
                        spintime = 1;
-                       spintime_value = jiffies;
                        time1 = HZ;
                        /* Wait 1 second for next try */
                        do {
Index: linux/include/linux/blkdev.h
diff -u linux/include/linux/blkdev.h:1.1.1.12 linux/include/linux/blkdev.h:1.3
--- linux/include/linux/blkdev.h:1.1.1.12       Mon Jan 22 09:31:17 2001
+++ linux/include/linux/blkdev.h        Mon Jan 22 10:01:35 2001
@@ -146,7 +146,6 @@
  */
 #define BLK_DEFAULT_QUEUE(_MAJOR)  &blk_dev[_MAJOR].request_queue
 
-extern struct sec_size * blk_sec[MAX_BLKDEV];
 extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
 extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long 
size);
 extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct 
block_device_operations *ops, long size);
@@ -174,8 +173,6 @@
 extern int * max_readahead[MAX_BLKDEV];
 
 extern int * max_sectors[MAX_BLKDEV];
-
-extern int * max_segments[MAX_BLKDEV];
 
 extern atomic_t queued_sectors;
 

Reply via email to