Skip to contentSkip to conversation

2.4.1 SCSI reservation/reset handling

PATCH New James Bottomley 1 participant 1 message Feb 13, 2001 SCSI

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 2.4.1 SCSI reservation/reset handling

The attached patch corrects the linux kernel reservation handling. Currently linux fails badly when presented with SCSI reservations in a clustered environment. The patch also completes Doug Gilbert's reset injection system in the sg driver. The patches have no effect on the main line SCSI code, but they are fairly essential to those of us working in clustering and using reservations for I/O fencing.

I've run the patch through a 12 hour stress test in a two node cluster using the sym53c875 and aic7xxx (AHA 2944/UW) SCSI cards.

James Bottomley

Index: linux/drivers/scsi/scsi.c
===================================================================
RCS file: /home/cvs/CVSROOT/linux/2.4/drivers/scsi/scsi.c,v retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.6.4

drivers/scsi/scsi.c +66 -0
diff -u -r1.1.1.4 -r1.1.1.4.6.4
@@ -146,7 +146,12 @@
  */
 extern void scsi_old_done(Scsi_Cmnd * SCpnt);
 extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
+extern int scsi_old_reset(Scsi_Cmnd *SCpnt, unsigned int flag);
 
+/* 
+ * private interface into the new error handling code
+ */
+extern int scsi_new_reset(Scsi_Cmnd *SCpnt, unsigned int flag);
 
 /*
  * Function:    scsi_initialize_queue()
@@ -2657,6 +2662,67 @@
          */
 	scsi_release_commandblocks(SDpnt);
         kfree(SDpnt);
+}
+
+/* Dummy done routine.  We don't want the bogus command used for the
+ * bus/device reset to find its way into the mid-layer so we intercept
+ * it here */
+static void
+scsi_reset_provider_done_command(Scsi_Cmnd *SCpnt) {
+        /* Empty function.  Some low level drivers will call scsi_done
+         * (and end up here), others won't bother */
+}
+
+
+/*
+ * Function:	scsi_reset_provider
+ *
+ * Purpose:	Send requested reset to a bus or device at any phase.
+ *
+ * Arguments:	device	- device to send reset to
+ *		flag - reset type (see scsi.h)
+ *
+ * Returns:	SUCCESS/FAILURE.
+ *
+ * Notes:	This is used by the SCSI Generic driver to provide
+ *		Bus/Device reset capability.
+ */
+int
+scsi_reset_provider(Scsi_Device *dev, int flag)
+{
+        int rtn;
+        Scsi_Cmnd *SCpnt;
+
+        /* get a dummy command to issue the reset to */
+        SCpnt = scsi_allocate_device(dev, 1, 1);
+        /* NULL indicates interrupt */
+        if(SCpnt == NULL)
+                return -EINTR;
+
+        /* initialise the command */
+        memset(&SCpnt->cmnd, '\0', sizeof(SCpnt->cmnd));
+
+        SCpnt->channel = dev->channel;
+        SCpnt->lun = dev->lun;
+        SCpnt->target = dev->id;
+        SCpnt->owner = SCSI_OWNER_MIDLEVEL;
+        SCpnt->scsi_done = scsi_reset_provider_done_command;
+        SCpnt->done = NULL;
+        SCpnt->reset_chain = NULL;
+
+        SCpnt->internal_timeout = NORMAL_TIMEOUT;
+        SCpnt->abort_reason = DID_ABORT;
+        
+        if(dev->host->hostt->use_new_eh_code) {
+                rtn = scsi_new_reset(SCpnt, flag);
+        } else {
+                rtn = scsi_old_reset(SCpnt, flag);
+        }
+        if(timer_pending(&SCpnt->eh_timeout))
+                scsi_delete_timer(SCpnt);
+        scsi_release_command(SCpnt);
+
+        return rtn;
 }
 
 /*

Index: linux/drivers/scsi/scsi.h
===================================================================
RCS file: /home/cvs/CVSROOT/linux/2.4/drivers/scsi/scsi.h,v retrieving revision 1.1.1.3

drivers/scsi/scsi.h +8 -0
diff -u -r1.1.1.3 scsi.h
@@ -842,6 +842,14 @@
 	remove_wait_queue(QUEUE, &wait);\
 	current->state = TASK_RUNNING;	\
     }; }
+/* reset request from external source (private to sg.c, scsi.c
+ * scsi_error.c and scsi_obsolete.c)
+ * */
+#define SCSI_TRY_RESET_DEVICE	1
+#define SCSI_TRY_RESET_BUS	2
+#define SCSI_TRY_RESET_HOST	3
+
+extern int scsi_reset_provider(Scsi_Device *, int);
 
 #endif
 

Index: linux/drivers/scsi/scsi_error.c
===================================================================
RCS file: /home/cvs/CVSROOT/linux/2.4/drivers/scsi/scsi_error.c,v retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.6.1

drivers/scsi/scsi_error.c +53 -3

76 lines not on this page · raw message

Index: linux/drivers/scsi/scsi_obsolete.c
===================================================================
RCS file: /home/cvs/CVSROOT/linux/2.4/drivers/scsi/scsi_obsolete.c,v retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.6.1

drivers/scsi/scsi_obsolete.c +44 -5

67 lines not on this page · raw message

Index: linux/drivers/scsi/scsi_syms.c
===================================================================
RCS file: /home/cvs/CVSROOT/linux/2.4/drivers/scsi/scsi_syms.c,v retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.6.1

drivers/scsi/scsi_syms.c +4 -0
diff -u -r1.1.1.2 -r1.1.1.2.6.1
@@ -84,6 +84,10 @@
 EXPORT_SYMBOL(scsi_deregister_blocked_host);
 
 /*
+ * This symbol is for the sg device only
+ */
+EXPORT_SYMBOL(scsi_reset_provider);
+/*
  * These are here only while I debug the rest of the scsi stuff.
  */
 EXPORT_SYMBOL(scsi_hostlist);