patch-2.1.75 linux/drivers/scsi/sd.c

Next file: linux/drivers/scsi/sd_ioctl.c
Previous file: linux/drivers/scsi/scsicam.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.74/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
@@ -87,6 +87,26 @@
 static int sd_detect(Scsi_Device *);
 static void sd_detach(Scsi_Device *);
 
+static void sd_devname(unsigned int disknum, char * buffer)
+{
+    if( disknum <= 26 )
+    {
+        sprintf(buffer, "sd%c", 'a' + (disknum >> 4));
+    }
+    else
+    {
+        unsigned int min1;
+        unsigned int min2;
+        /*
+         * For larger numbers of disks, we need to go to a new
+         * naming scheme.
+         */
+        min1 = (disknum >> 4) / 26;
+        min2 = (disknum >> 4) % 26;
+        sprintf(buffer, "sd%c%c", 'a' + min1, 'a' + min2);
+    }
+}
+
 struct Scsi_Device_Template sd_template =
 { NULL, "disk", "sd", NULL, TYPE_DISK,
       SCSI_DISK_MAJOR, 0, 0, 0, 1,
@@ -99,10 +119,21 @@
     int target;
     target =  DEVICE_NR(inode->i_rdev);
 
+    SCSI_LOG_HLQUEUE(1,printk("target=%d, max=%d\n", target, sd_template.dev_max));
+
     if(target >= sd_template.dev_max || !rscsi_disks[target].device)
 	return -ENXIO;   /* No such device */
 
     /*
+     * If the device is in error recovery, wait until it is done.
+     * If the device is offline, then disallow any access to it.
+     */
+    if( !scsi_block_when_processing_errors(rscsi_disks[target].device) )
+      {
+        return -ENXIO;
+      }
+
+    /*
      * Make sure that only one process can do a check_change_disk at one time.
      * This is also used to lock out further access when the partition table
      * is being re-read.
@@ -129,6 +160,16 @@
     }
 
     /*
+     * It is possible that the disk changing stuff resulted in the device being taken
+     * offline.  If this is the case, report this to the user, and don't pretend that
+     * the open actually succeeded.
+     */
+    if( !rscsi_disks[target].device->online )
+    {
+        return -ENXIO;
+    }
+
+    /*
      * See if we are requesting a non-existent partition.  Do this
      * after checking for disk change.
      */
@@ -222,14 +263,18 @@
 static void rw_intr (Scsi_Cmnd *SCpnt)
 {
     int result = SCpnt->result;
+    char nbuff[6];
     int this_count = SCpnt->bufflen >> 9;
     int good_sectors = (result == 0 ? this_count : 0);
     int block_sectors = 1;
 
-#ifdef DEBUG
-    printk("sd%c : rw_intr(%d, %d)\n", 'a' + MINOR(SCpnt->request.rq_dev),
-	   SCpnt->host->host_no, result);
-#endif
+    sd_devname(MINOR(SCpnt->request.rq_dev) >> 4, nbuff);
+
+    SCSI_LOG_HLCOMPLETE(1,printk("%s : rw_intr(%d, %x [%x %x])\n", nbuff,
+	   SCpnt->host->host_no, 
+                                 result, 
+                                 SCpnt->sense_buffer[0],
+                                 SCpnt->sense_buffer[2]));
 
     /*
       Handle MEDIUM ERRORs that indicate partial success.  Since this is a
@@ -276,20 +321,21 @@
 
     if (good_sectors > 0) {
 
-#ifdef DEBUG
-	printk("sd%c : %d sectors remain.\n", 'a' + MINOR(SCpnt->request.rq_dev),
-	       SCpnt->request.nr_sectors);
-	printk("use_sg is %d\n ",SCpnt->use_sg);
-#endif
+	SCSI_LOG_HLCOMPLETE(1,printk("%s : %ld sectors remain.\n", nbuff,
+	       SCpnt->request.nr_sectors));
+	SCSI_LOG_HLCOMPLETE(1,printk("use_sg is %d\n ",SCpnt->use_sg));
+
 	if (SCpnt->use_sg) {
 	    struct scatterlist * sgpnt;
 	    int i;
 	    sgpnt = (struct scatterlist *) SCpnt->buffer;
 	    for(i=0; i<SCpnt->use_sg; i++) {
-#ifdef DEBUG
-		printk(":%x %x %d\n",sgpnt[i].alt_address, sgpnt[i].address,
-		       sgpnt[i].length);
+
+#if 0
+		SCSI_LOG_HLCOMPLETE(3,printk(":%p %p %d\n",sgpnt[i].alt_address, sgpnt[i].address,
+		       sgpnt[i].length));
 #endif
+
 		if (sgpnt[i].alt_address) {
 		    if (SCpnt->request.cmd == READ)
 			memcpy(sgpnt[i].alt_address, sgpnt[i].address,
@@ -302,10 +348,10 @@
 	    scsi_free(SCpnt->buffer, SCpnt->sglist_len);
 	} else {
 	    if (SCpnt->buffer != SCpnt->request.buffer) {
-#ifdef DEBUG
-		printk("nosg: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
-		       SCpnt->bufflen);
-#endif
+		SCSI_LOG_HLCOMPLETE(3,printk("nosg: %p %p %d\n",
+                                             SCpnt->request.buffer, SCpnt->buffer,
+                                             SCpnt->bufflen));
+
 		if (SCpnt->request.cmd == READ)
 		    memcpy(SCpnt->request.buffer, SCpnt->buffer,
 			   SCpnt->bufflen);
@@ -323,10 +369,9 @@
 
 	    if (!SCpnt->request.bh)
 	    {
-#ifdef DEBUG
-		printk("sd%c : handling page request, no buffer\n",
-		       'a' + MINOR(SCpnt->request.rq_dev));
-#endif
+		SCSI_LOG_HLCOMPLETE(2,printk("%s : handling page request, no buffer\n",
+		       nbuff));
+
 		/*
 		 * The SCpnt->request.nr_sectors field is always done in
 		 * 512 byte sectors, even if this really isn't the case.
@@ -351,20 +396,18 @@
 	int i;
 	sgpnt = (struct scatterlist *) SCpnt->buffer;
 	for(i=0; i<SCpnt->use_sg; i++) {
-#ifdef DEBUG
-	    printk("err: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
-		   SCpnt->bufflen);
-#endif
+	    SCSI_LOG_HLCOMPLETE(3,printk("err: %p %p %d\n",
+                                         SCpnt->request.buffer, SCpnt->buffer,
+                                         SCpnt->bufflen));
 	    if (sgpnt[i].alt_address) {
 		scsi_free(sgpnt[i].address, sgpnt[i].length);
 	    }
 	}
 	scsi_free(SCpnt->buffer, SCpnt->sglist_len);  /* Free list of scatter-gather pointers */
     } else {
-#ifdef DEBUG
-	printk("nosgerr: %x %x %d\n",SCpnt->request.buffer, SCpnt->buffer,
-	       SCpnt->bufflen);
-#endif
+	SCSI_LOG_HLCOMPLETE(2,printk("nosgerr: %p %p %d\n",
+                                     SCpnt->request.buffer, SCpnt->buffer,
+                                     SCpnt->bufflen));
 	if (SCpnt->buffer != SCpnt->request.buffer)
 	    scsi_free(SCpnt->buffer, SCpnt->bufflen);
     }
@@ -485,6 +528,17 @@
         SDev = rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device;
 
         /*
+         * If the host for this device is in error recovery mode, don't
+         * do anything at all here.  When the host leaves error recovery
+         * mode, it will automatically restart things and start queueing
+         * commands again.
+         */
+        if( SDev->host->in_recovery )
+          {
+            return;
+          }
+
+        /*
          * I am not sure where the best place to do this is.  We need
          * to hook in a place where we are likely to come if in user
          * space.
@@ -495,7 +549,8 @@
 	     * We need to relock the door, but we might
 	     * be in an interrupt handler.  Only do this
 	     * from user space, since we do not want to
-	     * sleep from an interrupt.
+	     * sleep from an interrupt.  FIXME(eric) - do this
+             * from the kernel error handling thred.
 	     */
 	    if( SDev->removable && !in_interrupt() )
 	    {
@@ -507,21 +562,21 @@
 	    SDev->was_reset = 0;
         }
 
-	/* We have to be careful here. allocate_device will get a free pointer,
+	/* We have to be careful here. scsi_allocate_device will get a free pointer,
 	 * but there is no guarantee that it is queueable.  In normal usage,
 	 * we want to call this, because other types of devices may have the
 	 * host all tied up, and we want to make sure that we have at least
 	 * one request pending for this type of device. We can also come
 	 * through here while servicing an interrupt, because of the need to
-	 * start another command. If we call allocate_device more than once,
+	 * start another command. If we call scsi_allocate_device more than once,
 	 * then the system can wedge if the command is not queueable. The
-	 * request_queueable function is safe because it checks to make sure
+	 * scsi_request_queueable function is safe because it checks to make sure
 	 * that the host is able to take another command before it returns
 	 * a pointer.
 	 */
 
 	if (flag++ == 0)
-	    SCpnt = allocate_device(&CURRENT,
+	    SCpnt = scsi_allocate_device(&CURRENT,
 			   rscsi_disks[DEVICE_NR(CURRENT->rq_dev)].device, 0);
 	else SCpnt = NULL;
 
@@ -539,15 +594,19 @@
 	 * one disk drive.  We want to have the interrupts off when monkeying
 	 * with the request list, because otherwise the kernel might try to
 	 * slip in a request in between somewhere.
+         *
+         * FIXME(eric) - this doesn't belong at this level.  The device code in
+         * ll_rw_blk.c should know how to dig down into the device queue to
+         * figure out what it can deal with, and what it can't.  Consider
+         * possibility of pulling entire queue down into scsi layer.
 	 */
-
 	if (!SCpnt && sd_template.nr_dev > 1){
 	    struct request *req1;
 	    req1 = NULL;
 	    cli();
 	    req = CURRENT;
 	    while(req){
-		SCpnt = request_queueable(req,
+		SCpnt = scsi_request_queueable(req,
                                    rscsi_disks[DEVICE_NR(req->rq_dev)].device);
 		if(SCpnt) break;
 		req1 = req;
@@ -573,6 +632,7 @@
 {
     int dev, devm, block, this_count;
     unsigned char cmd[10];
+    char nbuff[6];
     int bounce_size, contiguous;
     int max_sg;
     struct buffer_head * bh, *bhp;
@@ -591,15 +651,16 @@
     block = SCpnt->request.sector;
     this_count = 0;
 
-#ifdef DEBUG
-    printk("Doing sd request, dev = %d, block = %d\n", devm, block);
-#endif
+    SCSI_LOG_HLQUEUE(1,printk("Doing sd request, dev = %d, block = %d\n", devm, block));
 
     if (devm >= (sd_template.dev_max << 4) ||
 	!rscsi_disks[dev].device ||
+	!rscsi_disks[dev].device->online ||
 	block + SCpnt->request.nr_sectors > sd[devm].nr_sects)
     {
+        SCSI_LOG_HLQUEUE(2,printk("Finishing %ld sectors\n", SCpnt->request.nr_sectors));
 	SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+        SCSI_LOG_HLQUEUE(2,printk("Retry with 0x%p\n", SCpnt));
 	goto repeat;
     }
 
@@ -616,10 +677,9 @@
 	goto repeat;
     }
 
-#ifdef DEBUG
-    printk("sd%c : real dev = /dev/sd%c, block = %d\n",
-	   'a' + devm, dev, block);
-#endif
+    sd_devname(devm, nbuff);
+    SCSI_LOG_HLQUEUE(2,printk("%s : real dev = /dev/%d, block = %d\n",
+	   nbuff, dev, block));
 
     /*
      * If we have a 1K hardware sectorsize, prevent access to single
@@ -702,7 +762,7 @@
 	SCpnt->use_sg = 0;
 
     } else if (SCpnt->host->sg_tablesize == 0 ||
-	       (need_isa_buffer && dma_free_sectors <= 10)) {
+	       (scsi_need_isa_buffer && scsi_dma_free_sectors <= 10)) {
 
 	/* Case of host adapter that cannot scatter-gather.  We also
 	 * come here if we are running low on DMA buffer memory.  We set
@@ -712,8 +772,8 @@
 	 * we have no choice but to panic.
 	 */
 	if (SCpnt->host->sg_tablesize != 0 &&
-	    need_isa_buffer &&
-	    dma_free_sectors <= 10)
+	    scsi_need_isa_buffer &&
+	    scsi_dma_free_sectors <= 10)
 	    printk("Warning: SCSI DMA buffer space running low.  Using non scatter-gather I/O.\n");
 
 	this_count = SCpnt->request.current_nr_sectors;
@@ -787,7 +847,7 @@
 		     * easier to control usage here. In other places we might
 		     * have a more pressing need, and we would be screwed if
 		     * we ran out */
-		    if(dma_free_sectors < (sgpnt[count].length >> 9) + 10) {
+		    if(scsi_dma_free_sectors < (sgpnt[count].length >> 9) + 10) {
 			sgpnt[count].address = NULL;
 		    } else {
 			sgpnt[count].address =
@@ -832,7 +892,7 @@
 			!sgpnt[count].alt_address) continue;
 
 		    if(!sgpnt[count].alt_address) {count--; continue; }
-		    if(dma_free_sectors > 10)
+		    if(scsi_dma_free_sectors > 10)
 			tmp = (char *) scsi_malloc(sgpnt[count].length
 						   + bhp->b_size);
 		    else {
@@ -861,7 +921,7 @@
 	       > SCpnt->host->sg_tablesize){
 		bh = SCpnt->request.bh;
 		printk("Use sg, count %d %x %d\n",
-		       SCpnt->use_sg, count, dma_free_sectors);
+		       SCpnt->use_sg, count, scsi_dma_free_sectors);
 		printk("maxsg = %x, counted = %d this_count = %d\n",
 		       max_sg, counted, this_count);
 		while(bh){
@@ -903,12 +963,10 @@
 		memcpy(buff, (char *)SCpnt->request.buffer, this_count << 9);
 	}
     }
-#ifdef DEBUG
-    printk("sd%c : %s %d/%d 512 byte blocks.\n",
-	   'a' + devm,
-	   (SCpnt->request.cmd == WRITE) ? "writing" : "reading",
-	   this_count, SCpnt->request.nr_sectors);
-#endif
+    SCSI_LOG_HLQUEUE(2,printk("%s : %s %d/%ld 512 byte blocks.\n",
+                              nbuff,
+                              (SCpnt->request.cmd == WRITE) ? "writing" : "reading",
+                              this_count, SCpnt->request.nr_sectors));
 
     cmd[1] = (SCpnt->lun << 5) & 0xe0;
 
@@ -989,6 +1047,20 @@
 
     if(!rscsi_disks[target].device->removable) return 0;
 
+    /*
+     * If the device is offline, don't send any commands - just pretend as if
+     * the command failed.  If the device ever comes back online, we can deal with
+     * it then.  It is only because of unrecoverable errors that we would ever
+     * take a device offline in the first place.
+     */
+    if( rscsi_disks[target].device->online == FALSE )
+    {
+	rscsi_disks[target].ready = 0;
+	rscsi_disks[target].device->changed = 1;
+	return 1; /* This will force a flush, if called from
+		   * check_disk_change */
+    }
+
     inode.i_rdev = full_dev;  /* This is all we really need here */
     retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0);
 
@@ -1031,17 +1103,32 @@
 static int sd_init_onedisk(int i)
 {
     unsigned char cmd[10];
+    char          nbuff[6];
     unsigned char *buffer;
     unsigned long spintime;
     int the_result, retries;
     Scsi_Cmnd * SCpnt;
 
+    /*
+     * Get the name of the disk, in case we need to log it somewhere.
+     */
+    sd_devname(i, nbuff);
+
+    /*
+     * If the device is offline, don't try and read capacity or any of the other
+     * nicities.
+     */
+    if( rscsi_disks[i].device->online == FALSE )
+    {
+        return i;
+    }
+
     /* We need to retry the READ_CAPACITY because a UNIT_ATTENTION is
      * considered a fatal error, and many devices report such an error
      * just after a scsi bus reset.
      */
 
-    SCpnt = allocate_device(NULL, rscsi_disks[i].device, 1);
+    SCpnt = scsi_allocate_device(NULL, rscsi_disks[i].device, 1);
     buffer = (unsigned char *) scsi_malloc(512);
 
     spintime = 0;
@@ -1069,6 +1156,7 @@
 				 512, sd_init_done,  SD_TIMEOUT,
 				 MAX_RETRIES);
 		    down(&sem);
+                    SCpnt->request.sem = NULL;
 		}
 
 		the_result = SCpnt->result;
@@ -1084,7 +1172,7 @@
 	       SCpnt->sense_buffer[2] == NOT_READY) {
 		unsigned long time1;
 		if(!spintime){
-		    printk( "sd%c: Spinning up disk...", 'a' + i );
+		    printk( "%s: Spinning up disk...", nbuff );
 		    cmd[0] = START_STOP;
 		    cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
 		    cmd[1] |= 1;  /* Return immediately */
@@ -1104,6 +1192,7 @@
 				     512, sd_init_done,  SD_TIMEOUT,
 				     MAX_RETRIES);
 			down(&sem);
+                        SCpnt->request.sem = NULL;
 		    }
 
 		    spintime = jiffies;
@@ -1141,6 +1230,7 @@
 			 8, sd_init_done,  SD_TIMEOUT,
 			 MAX_RETRIES);
 	    down(&sem);	/* sleep until it is ready */
+            SCpnt->request.sem = NULL;
 	}
 
 	the_result = SCpnt->result;
@@ -1148,12 +1238,6 @@
 
     } while(the_result && retries);
 
-    SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
-
-    wake_up(&SCpnt->device->device_wait);
-
-    /* Wake up a process waiting for device */
-
     /*
      * The SCSI standard says:
      * "READ CAPACITY is necessary for self configuring software"
@@ -1170,22 +1254,22 @@
 
     if (the_result)
     {
-	printk ("sd%c : READ CAPACITY failed.\n"
-		"sd%c : status = %x, message = %02x, host = %d, driver = %02x \n",
-		'a' + i, 'a' + i,
+	printk ("%s : READ CAPACITY failed.\n"
+		"%s : status = %x, message = %02x, host = %d, driver = %02x \n",
+		nbuff, nbuff,
 		status_byte(the_result),
 		msg_byte(the_result),
 		host_byte(the_result),
 		driver_byte(the_result)
 		);
 	if (driver_byte(the_result)  & DRIVER_SENSE)
-	    printk("sd%c : extended sense code = %1x \n",
-		   'a' + i, SCpnt->sense_buffer[2] & 0xf);
+	    printk("%s : extended sense code = %1x \n",
+		   nbuff, SCpnt->sense_buffer[2] & 0xf);
 	else
-	    printk("sd%c : sense not available. \n", 'a' + i);
+	    printk("%s : sense not available. \n", nbuff);
 
-	printk("sd%c : block size assumed to be 512 bytes, disk size 1GB.  \n",
-	       'a' + i);
+	printk("%s : block size assumed to be 512 bytes, disk size 1GB.  \n",
+	       nbuff);
 	rscsi_disks[i].capacity = 0x1fffff;
 	rscsi_disks[i].sector_size = 512;
 
@@ -1213,7 +1297,7 @@
 
 	if (rscsi_disks[i].sector_size == 0) {
 	  rscsi_disks[i].sector_size = 512;
-	  printk("sd%c : sector size 0 reported, assuming 512.\n", 'a' + i);
+	  printk("%s : sector size 0 reported, assuming 512.\n", nbuff);
 	}
 
 
@@ -1222,8 +1306,8 @@
 	    rscsi_disks[i].sector_size != 2048 &&
 	    rscsi_disks[i].sector_size != 256)
 	{
-	    printk ("sd%c : unsupported sector size %d.\n",
-		    'a' + i, rscsi_disks[i].sector_size);
+	    printk ("%s : unsupported sector size %d.\n",
+		    nbuff, rscsi_disks[i].sector_size);
 	    if(rscsi_disks[i].device->removable){
 		rscsi_disks[i].capacity = 0;
 	    } else {
@@ -1231,6 +1315,12 @@
 		rscsi_disks[i].device = NULL;
 		sd_template.nr_dev--;
 		sd_gendisk.nr_real--;
+
+                /* Wake up a process waiting for device */
+                wake_up(&SCpnt->device->device_wait);
+                scsi_release_command(SCpnt);
+                SCpnt = NULL;
+                
 		return i;
 	    }
 	}
@@ -1268,9 +1358,9 @@
         m = (mb + 50) / 100;
         sz_quot = m / 10;
         sz_rem = m - (10 * sz_quot);
-	printk ("SCSI device sd%c: hdwr sector= %d bytes."
+	printk ("SCSI device %s: hdwr sector= %d bytes."
                " Sectors= %d [%d MB] [%d.%1d GB]\n",
-		i+'a', hard_sector, rscsi_disks[i].capacity,
+		nbuff, hard_sector, rscsi_disks[i].capacity,
                 mb, sz_quot, sz_rem);
     }
 	if(rscsi_disks[i].sector_size == 2048)
@@ -1315,23 +1405,27 @@
 			 512, sd_init_done,  SD_TIMEOUT,
 			 MAX_RETRIES);
 	    down(&sem);
+            SCpnt->request.sem = NULL;
 	}
 
 	the_result = SCpnt->result;
-	SCpnt->request.rq_status = RQ_INACTIVE;  /* Mark as not busy */
-	wake_up(&SCpnt->device->device_wait);
 
 	if ( the_result ) {
-	    printk ("sd%c: test WP failed, assume Write Protected\n",i+'a');
+	    printk ("%s: test WP failed, assume Write Protected\n",nbuff);
 	    rscsi_disks[i].write_prot = 1;
 	} else {
 	    rscsi_disks[i].write_prot = ((buffer[2] & 0x80) != 0);
-	    printk ("sd%c: Write Protect is %s\n",i+'a',
+	    printk ("%s: Write Protect is %s\n",nbuff,
 	            rscsi_disks[i].write_prot ? "on" : "off");
 	}
 
     }	/* check for write protect */
 
+    /* Wake up a process waiting for device */
+    wake_up(&SCpnt->device->device_wait);
+    scsi_release_command(SCpnt);
+    SCpnt = NULL;
+
     rscsi_disks[i].ten = 1;
     rscsi_disks[i].remap = 1;
     scsi_free(buffer, 512);
@@ -1435,11 +1529,13 @@
 }
 
 static int sd_detect(Scsi_Device * SDp){
+    char nbuff[6];
     if(SDp->type != TYPE_DISK && SDp->type != TYPE_MOD) return 0;
 
-    printk("Detected scsi %sdisk sd%c at scsi%d, channel %d, id %d, lun %d\n",
+    sd_devname(sd_template.dev_noticed++, nbuff);
+    printk("Detected scsi %sdisk %s at scsi%d, channel %d, id %d, lun %d\n",
            SDp->removable ? "removable " : "",
-	   'a'+ (sd_template.dev_noticed++),
+	   nbuff,
 	   SDp->host->host_no, SDp->channel, SDp->id, SDp->lun);
 
     return 1;
@@ -1509,7 +1605,7 @@
     for (i=max_p - 1; i >=0 ; i--) {
 	int minor = start+i;
 	kdev_t devi = MKDEV(MAJOR_NR, minor);
-	struct super_block *sb = get_super(devi);
+        struct super_block *sb = get_super(devi);
 	sync_dev(devi);
 	if (sb) invalidate_inodes(sb);
 	invalidate_buffers(devi);
@@ -1562,7 +1658,7 @@
 	    for (i=max_p - 1; i >=0 ; i--) {
 		int minor = start+i;
 		kdev_t devi = MKDEV(MAJOR_NR, minor);
-		struct super_block *sb = get_super(devi);
+                struct super_block *sb = get_super(devi);
 		sync_dev(devi);
 		if (sb) invalidate_inodes(sb);
 		invalidate_buffers(devi);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov