aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi.c6
-rw-r--r--drivers/scsi/scsi_debug.c4
-rw-r--r--drivers/scsi/scsi_error.c12
-rw-r--r--drivers/scsi/sd.c82
-rw-r--r--drivers/scsi/sd.h35
-rw-r--r--include/scsi/scsi_cmnd.h6
-rw-r--r--include/scsi/scsi_driver.h1
7 files changed, 137 insertions, 9 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 2aeb2e9c4d3b..07322ecff90d 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -782,12 +782,6 @@ static void scsi_done(struct scsi_cmnd *cmd)
782 blk_complete_request(cmd->request); 782 blk_complete_request(cmd->request);
783} 783}
784 784
785/* Move this to a header if it becomes more generally useful */
786static struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
787{
788 return *(struct scsi_driver **)cmd->request->rq_disk->private_data;
789}
790
791/** 785/**
792 * scsi_finish_command - cleanup and pass command back to upper layer 786 * scsi_finish_command - cleanup and pass command back to upper layer
793 * @cmd: the command 787 * @cmd: the command
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index d2fd0efca565..8917154d96c7 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -126,6 +126,7 @@ static const char * scsi_debug_version_date = "20100324";
126#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 126#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16
127#define SCSI_DEBUG_OPT_DIF_ERR 32 127#define SCSI_DEBUG_OPT_DIF_ERR 32
128#define SCSI_DEBUG_OPT_DIX_ERR 64 128#define SCSI_DEBUG_OPT_DIX_ERR 64
129#define SCSI_DEBUG_OPT_MAC_TIMEOUT 128
129/* When "every_nth" > 0 then modulo "every_nth" commands: 130/* When "every_nth" > 0 then modulo "every_nth" commands:
130 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set 131 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
131 * - a RECOVERED_ERROR is simulated on successful read and write 132 * - a RECOVERED_ERROR is simulated on successful read and write
@@ -3615,6 +3616,9 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
3615 scsi_debug_every_nth = -1; 3616 scsi_debug_every_nth = -1;
3616 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) 3617 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
3617 return 0; /* ignore command causing timeout */ 3618 return 0; /* ignore command causing timeout */
3619 else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts &&
3620 scsi_medium_access_command(SCpnt))
3621 return 0; /* time out reads and writes */
3618 else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) 3622 else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
3619 inj_recovered = 1; /* to reads and writes below */ 3623 inj_recovered = 1; /* to reads and writes below */
3620 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) 3624 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
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
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8c525aa1b858..bd17cf8af013 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -107,6 +107,7 @@ static int sd_suspend(struct device *, pm_message_t state);
107static int sd_resume(struct device *); 107static int sd_resume(struct device *);
108static void sd_rescan(struct device *); 108static void sd_rescan(struct device *);
109static int sd_done(struct scsi_cmnd *); 109static int sd_done(struct scsi_cmnd *);
110static int sd_eh_action(struct scsi_cmnd *, unsigned char *, int, int);
110static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); 111static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer);
111static void scsi_disk_release(struct device *cdev); 112static void scsi_disk_release(struct device *cdev);
112static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); 113static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
@@ -346,6 +347,31 @@ sd_store_provisioning_mode(struct device *dev, struct device_attribute *attr,
346 return count; 347 return count;
347} 348}
348 349
350static ssize_t
351sd_show_max_medium_access_timeouts(struct device *dev,
352 struct device_attribute *attr, char *buf)
353{
354 struct scsi_disk *sdkp = to_scsi_disk(dev);
355
356 return snprintf(buf, 20, "%u\n", sdkp->max_medium_access_timeouts);
357}
358
359static ssize_t
360sd_store_max_medium_access_timeouts(struct device *dev,
361 struct device_attribute *attr,
362 const char *buf, size_t count)
363{
364 struct scsi_disk *sdkp = to_scsi_disk(dev);
365 int err;
366
367 if (!capable(CAP_SYS_ADMIN))
368 return -EACCES;
369
370 err = kstrtouint(buf, 10, &sdkp->max_medium_access_timeouts);
371
372 return err ? err : count;
373}
374
349static struct device_attribute sd_disk_attrs[] = { 375static struct device_attribute sd_disk_attrs[] = {
350 __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, 376 __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
351 sd_store_cache_type), 377 sd_store_cache_type),
@@ -360,6 +386,9 @@ static struct device_attribute sd_disk_attrs[] = {
360 __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL), 386 __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
361 __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode, 387 __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
362 sd_store_provisioning_mode), 388 sd_store_provisioning_mode),
389 __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR,
390 sd_show_max_medium_access_timeouts,
391 sd_store_max_medium_access_timeouts),
363 __ATTR_NULL, 392 __ATTR_NULL,
364}; 393};
365 394
@@ -382,6 +411,7 @@ static struct scsi_driver sd_template = {
382 }, 411 },
383 .rescan = sd_rescan, 412 .rescan = sd_rescan,
384 .done = sd_done, 413 .done = sd_done,
414 .eh_action = sd_eh_action,
385}; 415};
386 416
387/* 417/*
@@ -1313,6 +1343,55 @@ static const struct block_device_operations sd_fops = {
1313 .unlock_native_capacity = sd_unlock_native_capacity, 1343 .unlock_native_capacity = sd_unlock_native_capacity,
1314}; 1344};
1315 1345
1346/**
1347 * sd_eh_action - error handling callback
1348 * @scmd: sd-issued command that has failed
1349 * @eh_cmnd: The command that was sent during error handling
1350 * @eh_cmnd_len: Length of eh_cmnd in bytes
1351 * @eh_disp: The recovery disposition suggested by the midlayer
1352 *
1353 * This function is called by the SCSI midlayer upon completion of
1354 * an error handling command (TEST UNIT READY, START STOP UNIT,
1355 * etc.) The command sent to the device by the error handler is
1356 * stored in eh_cmnd. The result of sending the eh command is
1357 * passed in eh_disp.
1358 **/
1359static int sd_eh_action(struct scsi_cmnd *scmd, unsigned char *eh_cmnd,
1360 int eh_cmnd_len, int eh_disp)
1361{
1362 struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk);
1363
1364 if (!scsi_device_online(scmd->device) ||
1365 !scsi_medium_access_command(scmd))
1366 return eh_disp;
1367
1368 /*
1369 * The device has timed out executing a medium access command.
1370 * However, the TEST UNIT READY command sent during error
1371 * handling completed successfully. Either the device is in the
1372 * process of recovering or has it suffered an internal failure
1373 * that prevents access to the storage medium.
1374 */
1375 if (host_byte(scmd->result) == DID_TIME_OUT && eh_disp == SUCCESS &&
1376 eh_cmnd_len && eh_cmnd[0] == TEST_UNIT_READY)
1377 sdkp->medium_access_timed_out++;
1378
1379 /*
1380 * If the device keeps failing read/write commands but TEST UNIT
1381 * READY always completes successfully we assume that medium
1382 * access is no longer possible and take the device offline.
1383 */
1384 if (sdkp->medium_access_timed_out >= sdkp->max_medium_access_timeouts) {
1385 scmd_printk(KERN_ERR, scmd,
1386 "Medium access timeout failure. Offlining disk!\n");
1387 scsi_device_set_state(scmd->device, SDEV_OFFLINE);
1388
1389 return FAILED;
1390 }
1391
1392 return eh_disp;
1393}
1394
1316static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) 1395static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd)
1317{ 1396{
1318 u64 start_lba = blk_rq_pos(scmd->request); 1397 u64 start_lba = blk_rq_pos(scmd->request);
@@ -1402,6 +1481,8 @@ static int sd_done(struct scsi_cmnd *SCpnt)
1402 (!sense_valid || sense_deferred)) 1481 (!sense_valid || sense_deferred))
1403 goto out; 1482 goto out;
1404 1483
1484 sdkp->medium_access_timed_out = 0;
1485
1405 switch (sshdr.sense_key) { 1486 switch (sshdr.sense_key) {
1406 case HARDWARE_ERROR: 1487 case HARDWARE_ERROR:
1407 case MEDIUM_ERROR: 1488 case MEDIUM_ERROR:
@@ -2523,6 +2604,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
2523 sdkp->RCD = 0; 2604 sdkp->RCD = 0;
2524 sdkp->ATO = 0; 2605 sdkp->ATO = 0;
2525 sdkp->first_scan = 1; 2606 sdkp->first_scan = 1;
2607 sdkp->max_medium_access_timeouts = SD_MAX_MEDIUM_TIMEOUTS;
2526 2608
2527 sd_revalidate_disk(gd); 2609 sd_revalidate_disk(gd);
2528 2610
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 4163f2910e3d..f703f4827b6f 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -20,6 +20,7 @@
20 */ 20 */
21#define SD_MAX_RETRIES 5 21#define SD_MAX_RETRIES 5
22#define SD_PASSTHROUGH_RETRIES 1 22#define SD_PASSTHROUGH_RETRIES 1
23#define SD_MAX_MEDIUM_TIMEOUTS 2
23 24
24/* 25/*
25 * Size of the initial data buffer for mode and read capacity data 26 * Size of the initial data buffer for mode and read capacity data
@@ -59,6 +60,8 @@ struct scsi_disk {
59 u32 unmap_alignment; 60 u32 unmap_alignment;
60 u32 index; 61 u32 index;
61 unsigned int physical_block_size; 62 unsigned int physical_block_size;
63 unsigned int max_medium_access_timeouts;
64 unsigned int medium_access_timed_out;
62 u8 media_present; 65 u8 media_present;
63 u8 write_prot; 66 u8 write_prot;
64 u8 protection_type;/* Data Integrity Field */ 67 u8 protection_type;/* Data Integrity Field */
@@ -88,6 +91,38 @@ static inline struct scsi_disk *scsi_disk(struct gendisk *disk)
88 (sdsk)->disk->disk_name, ##a) : \ 91 (sdsk)->disk->disk_name, ##a) : \
89 sdev_printk(prefix, (sdsk)->device, fmt, ##a) 92 sdev_printk(prefix, (sdsk)->device, fmt, ##a)
90 93
94static inline int scsi_medium_access_command(struct scsi_cmnd *scmd)
95{
96 switch (scmd->cmnd[0]) {
97 case READ_6:
98 case READ_10:
99 case READ_12:
100 case READ_16:
101 case SYNCHRONIZE_CACHE:
102 case VERIFY:
103 case VERIFY_12:
104 case VERIFY_16:
105 case WRITE_6:
106 case WRITE_10:
107 case WRITE_12:
108 case WRITE_16:
109 case WRITE_SAME:
110 case WRITE_SAME_16:
111 case UNMAP:
112 return 1;
113 case VARIABLE_LENGTH_CMD:
114 switch (scmd->cmnd[9]) {
115 case READ_32:
116 case VERIFY_32:
117 case WRITE_32:
118 case WRITE_SAME_32:
119 return 1;
120 }
121 }
122
123 return 0;
124}
125
91/* 126/*
92 * A DIF-capable target device can be formatted with different 127 * A DIF-capable target device can be formatted with different
93 * protection schemes. Currently 0 through 3 are defined: 128 * protection schemes. Currently 0 through 3 are defined:
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 9be0128bf303..377df4a28512 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -10,6 +10,7 @@
10 10
11struct Scsi_Host; 11struct Scsi_Host;
12struct scsi_device; 12struct scsi_device;
13struct scsi_driver;
13 14
14/* 15/*
15 * MAX_COMMAND_SIZE is: 16 * MAX_COMMAND_SIZE is:
@@ -131,6 +132,11 @@ struct scsi_cmnd {
131 unsigned char tag; /* SCSI-II queued command tag */ 132 unsigned char tag; /* SCSI-II queued command tag */
132}; 133};
133 134
135static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
136{
137 return *(struct scsi_driver **)cmd->request->rq_disk->private_data;
138}
139
134extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); 140extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t);
135extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t); 141extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t);
136extern void scsi_put_command(struct scsi_cmnd *); 142extern void scsi_put_command(struct scsi_cmnd *);
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
index 9fd6702f02e2..d443aa06a722 100644
--- a/include/scsi/scsi_driver.h
+++ b/include/scsi/scsi_driver.h
@@ -16,6 +16,7 @@ struct scsi_driver {
16 16
17 void (*rescan)(struct device *); 17 void (*rescan)(struct device *);
18 int (*done)(struct scsi_cmnd *); 18 int (*done)(struct scsi_cmnd *);
19 int (*eh_action)(struct scsi_cmnd *, unsigned char *, int, int);
19}; 20};
20#define to_scsi_driver(drv) \ 21#define to_scsi_driver(drv) \
21 container_of((drv), struct scsi_driver, gendrv) 22 container_of((drv), struct scsi_driver, gendrv)