aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_error.c
diff options
context:
space:
mode:
authorMartin K. Petersen <martin.petersen@oracle.com>2012-02-09 13:48:53 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 11:14:52 -0500
commit18a4d0a22ed6c54b67af7718c305cd010f09ddf8 (patch)
tree06e22a92290ff84b2c1d5abb09424493de384c4b /drivers/scsi/scsi_error.c
parenta78e21dc5e9f896ecee5b1fbe189690dfcca38e1 (diff)
[SCSI] Handle disk devices which can not process medium access commands
We have experienced several devices which fail in a fashion we do not currently handle gracefully in SCSI. After a failure these devices will respond to the SCSI primary command set (INQUIRY, TEST UNIT READY, etc.) but any command accessing the storage medium will time out. The following patch adds an callback that can be used by upper level drivers to inspect the results of an error handling command. This in turn has been used to implement additional checking in the SCSI disk driver. If a medium access command fails twice but TEST UNIT READY succeeds both times in the subsequent error handling we will offline the device. The maximum number of failed commands required to take a device offline can be tweaked in sysfs. Also add a new error flag to scsi_debug which allows this scenario to be easily reproduced. [jejb: fix up integer parsing to use kstrtouint] Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r--drivers/scsi/scsi_error.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index f66e90db3bee..2cfcbffa41fd 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -30,6 +30,7 @@
30#include <scsi/scsi_cmnd.h> 30#include <scsi/scsi_cmnd.h>
31#include <scsi/scsi_dbg.h> 31#include <scsi/scsi_dbg.h>
32#include <scsi/scsi_device.h> 32#include <scsi/scsi_device.h>
33#include <scsi/scsi_driver.h>
33#include <scsi/scsi_eh.h> 34#include <scsi/scsi_eh.h>
34#include <scsi/scsi_transport.h> 35#include <scsi/scsi_transport.h>
35#include <scsi/scsi_host.h> 36#include <scsi/scsi_host.h>
@@ -141,11 +142,11 @@ enum blk_eh_timer_return scsi_times_out(struct request *req)
141 else if (host->hostt->eh_timed_out) 142 else if (host->hostt->eh_timed_out)
142 rtn = host->hostt->eh_timed_out(scmd); 143 rtn = host->hostt->eh_timed_out(scmd);
143 144
145 scmd->result |= DID_TIME_OUT << 16;
146
144 if (unlikely(rtn == BLK_EH_NOT_HANDLED && 147 if (unlikely(rtn == BLK_EH_NOT_HANDLED &&
145 !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { 148 !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)))
146 scmd->result |= DID_TIME_OUT << 16;
147 rtn = BLK_EH_HANDLED; 149 rtn = BLK_EH_HANDLED;
148 }
149 150
150 return rtn; 151 return rtn;
151} 152}
@@ -778,6 +779,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
778 int cmnd_size, int timeout, unsigned sense_bytes) 779 int cmnd_size, int timeout, unsigned sense_bytes)
779{ 780{
780 struct scsi_device *sdev = scmd->device; 781 struct scsi_device *sdev = scmd->device;
782 struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd);
781 struct Scsi_Host *shost = sdev->host; 783 struct Scsi_Host *shost = sdev->host;
782 DECLARE_COMPLETION_ONSTACK(done); 784 DECLARE_COMPLETION_ONSTACK(done);
783 unsigned long timeleft; 785 unsigned long timeleft;
@@ -832,6 +834,10 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
832 } 834 }
833 835
834 scsi_eh_restore_cmnd(scmd, &ses); 836 scsi_eh_restore_cmnd(scmd, &ses);
837
838 if (sdrv->eh_action)
839 rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn);
840
835 return rtn; 841 return rtn;
836} 842}
837 843