aboutsummaryrefslogtreecommitdiffstats
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
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>
-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)