Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Martin K. Petersen and committed by
James Bottomley
18a4d0a2 a78e21dc

+137 -9
-6
drivers/scsi/scsi.c
··· 782 782 blk_complete_request(cmd->request); 783 783 } 784 784 785 - /* Move this to a header if it becomes more generally useful */ 786 - static 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 786 * scsi_finish_command - cleanup and pass command back to upper layer 793 787 * @cmd: the command
+4
drivers/scsi/scsi_debug.c
··· 126 126 #define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 127 127 #define SCSI_DEBUG_OPT_DIF_ERR 32 128 128 #define SCSI_DEBUG_OPT_DIX_ERR 64 129 + #define SCSI_DEBUG_OPT_MAC_TIMEOUT 128 129 130 /* When "every_nth" > 0 then modulo "every_nth" commands: 130 131 * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set 131 132 * - a RECOVERED_ERROR is simulated on successful read and write ··· 3616 3615 scsi_debug_every_nth = -1; 3617 3616 if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) 3618 3617 return 0; /* ignore command causing timeout */ 3618 + else if (SCSI_DEBUG_OPT_MAC_TIMEOUT & scsi_debug_opts && 3619 + scsi_medium_access_command(SCpnt)) 3620 + return 0; /* time out reads and writes */ 3619 3621 else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) 3620 3622 inj_recovered = 1; /* to reads and writes below */ 3621 3623 else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
+9 -3
drivers/scsi/scsi_error.c
··· 30 30 #include <scsi/scsi_cmnd.h> 31 31 #include <scsi/scsi_dbg.h> 32 32 #include <scsi/scsi_device.h> 33 + #include <scsi/scsi_driver.h> 33 34 #include <scsi/scsi_eh.h> 34 35 #include <scsi/scsi_transport.h> 35 36 #include <scsi/scsi_host.h> ··· 142 141 else if (host->hostt->eh_timed_out) 143 142 rtn = host->hostt->eh_timed_out(scmd); 144 143 144 + scmd->result |= DID_TIME_OUT << 16; 145 + 145 146 if (unlikely(rtn == BLK_EH_NOT_HANDLED && 146 - !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { 147 - scmd->result |= DID_TIME_OUT << 16; 147 + !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) 148 148 rtn = BLK_EH_HANDLED; 149 - } 150 149 151 150 return rtn; 152 151 } ··· 779 778 int cmnd_size, int timeout, unsigned sense_bytes) 780 779 { 781 780 struct scsi_device *sdev = scmd->device; 781 + struct scsi_driver *sdrv = scsi_cmd_to_driver(scmd); 782 782 struct Scsi_Host *shost = sdev->host; 783 783 DECLARE_COMPLETION_ONSTACK(done); 784 784 unsigned long timeleft; ··· 834 832 } 835 833 836 834 scsi_eh_restore_cmnd(scmd, &ses); 835 + 836 + if (sdrv->eh_action) 837 + rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn); 838 + 837 839 return rtn; 838 840 } 839 841
+82
drivers/scsi/sd.c
··· 107 107 static int sd_resume(struct device *); 108 108 static void sd_rescan(struct device *); 109 109 static int sd_done(struct scsi_cmnd *); 110 + static int sd_eh_action(struct scsi_cmnd *, unsigned char *, int, int); 110 111 static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); 111 112 static void scsi_disk_release(struct device *cdev); 112 113 static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); ··· 347 346 return count; 348 347 } 349 348 349 + static ssize_t 350 + sd_show_max_medium_access_timeouts(struct device *dev, 351 + struct device_attribute *attr, char *buf) 352 + { 353 + struct scsi_disk *sdkp = to_scsi_disk(dev); 354 + 355 + return snprintf(buf, 20, "%u\n", sdkp->max_medium_access_timeouts); 356 + } 357 + 358 + static ssize_t 359 + sd_store_max_medium_access_timeouts(struct device *dev, 360 + struct device_attribute *attr, 361 + const char *buf, size_t count) 362 + { 363 + struct scsi_disk *sdkp = to_scsi_disk(dev); 364 + int err; 365 + 366 + if (!capable(CAP_SYS_ADMIN)) 367 + return -EACCES; 368 + 369 + err = kstrtouint(buf, 10, &sdkp->max_medium_access_timeouts); 370 + 371 + return err ? err : count; 372 + } 373 + 350 374 static struct device_attribute sd_disk_attrs[] = { 351 375 __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, 352 376 sd_store_cache_type), ··· 386 360 __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL), 387 361 __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode, 388 362 sd_store_provisioning_mode), 363 + __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR, 364 + sd_show_max_medium_access_timeouts, 365 + sd_store_max_medium_access_timeouts), 389 366 __ATTR_NULL, 390 367 }; 391 368 ··· 411 382 }, 412 383 .rescan = sd_rescan, 413 384 .done = sd_done, 385 + .eh_action = sd_eh_action, 414 386 }; 415 387 416 388 /* ··· 1343 1313 .unlock_native_capacity = sd_unlock_native_capacity, 1344 1314 }; 1345 1315 1316 + /** 1317 + * sd_eh_action - error handling callback 1318 + * @scmd: sd-issued command that has failed 1319 + * @eh_cmnd: The command that was sent during error handling 1320 + * @eh_cmnd_len: Length of eh_cmnd in bytes 1321 + * @eh_disp: The recovery disposition suggested by the midlayer 1322 + * 1323 + * This function is called by the SCSI midlayer upon completion of 1324 + * an error handling command (TEST UNIT READY, START STOP UNIT, 1325 + * etc.) The command sent to the device by the error handler is 1326 + * stored in eh_cmnd. The result of sending the eh command is 1327 + * passed in eh_disp. 1328 + **/ 1329 + static int sd_eh_action(struct scsi_cmnd *scmd, unsigned char *eh_cmnd, 1330 + int eh_cmnd_len, int eh_disp) 1331 + { 1332 + struct scsi_disk *sdkp = scsi_disk(scmd->request->rq_disk); 1333 + 1334 + if (!scsi_device_online(scmd->device) || 1335 + !scsi_medium_access_command(scmd)) 1336 + return eh_disp; 1337 + 1338 + /* 1339 + * The device has timed out executing a medium access command. 1340 + * However, the TEST UNIT READY command sent during error 1341 + * handling completed successfully. Either the device is in the 1342 + * process of recovering or has it suffered an internal failure 1343 + * that prevents access to the storage medium. 1344 + */ 1345 + if (host_byte(scmd->result) == DID_TIME_OUT && eh_disp == SUCCESS && 1346 + eh_cmnd_len && eh_cmnd[0] == TEST_UNIT_READY) 1347 + sdkp->medium_access_timed_out++; 1348 + 1349 + /* 1350 + * If the device keeps failing read/write commands but TEST UNIT 1351 + * READY always completes successfully we assume that medium 1352 + * access is no longer possible and take the device offline. 1353 + */ 1354 + if (sdkp->medium_access_timed_out >= sdkp->max_medium_access_timeouts) { 1355 + scmd_printk(KERN_ERR, scmd, 1356 + "Medium access timeout failure. Offlining disk!\n"); 1357 + scsi_device_set_state(scmd->device, SDEV_OFFLINE); 1358 + 1359 + return FAILED; 1360 + } 1361 + 1362 + return eh_disp; 1363 + } 1364 + 1346 1365 static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) 1347 1366 { 1348 1367 u64 start_lba = blk_rq_pos(scmd->request); ··· 1480 1401 if (driver_byte(result) != DRIVER_SENSE && 1481 1402 (!sense_valid || sense_deferred)) 1482 1403 goto out; 1404 + 1405 + sdkp->medium_access_timed_out = 0; 1483 1406 1484 1407 switch (sshdr.sense_key) { 1485 1408 case HARDWARE_ERROR: ··· 2604 2523 sdkp->RCD = 0; 2605 2524 sdkp->ATO = 0; 2606 2525 sdkp->first_scan = 1; 2526 + sdkp->max_medium_access_timeouts = SD_MAX_MEDIUM_TIMEOUTS; 2607 2527 2608 2528 sd_revalidate_disk(gd); 2609 2529
+35
drivers/scsi/sd.h
··· 20 20 */ 21 21 #define SD_MAX_RETRIES 5 22 22 #define SD_PASSTHROUGH_RETRIES 1 23 + #define SD_MAX_MEDIUM_TIMEOUTS 2 23 24 24 25 /* 25 26 * Size of the initial data buffer for mode and read capacity data ··· 60 59 u32 unmap_alignment; 61 60 u32 index; 62 61 unsigned int physical_block_size; 62 + unsigned int max_medium_access_timeouts; 63 + unsigned int medium_access_timed_out; 63 64 u8 media_present; 64 65 u8 write_prot; 65 66 u8 protection_type;/* Data Integrity Field */ ··· 90 87 sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ 91 88 (sdsk)->disk->disk_name, ##a) : \ 92 89 sdev_printk(prefix, (sdsk)->device, fmt, ##a) 90 + 91 + static inline int scsi_medium_access_command(struct scsi_cmnd *scmd) 92 + { 93 + switch (scmd->cmnd[0]) { 94 + case READ_6: 95 + case READ_10: 96 + case READ_12: 97 + case READ_16: 98 + case SYNCHRONIZE_CACHE: 99 + case VERIFY: 100 + case VERIFY_12: 101 + case VERIFY_16: 102 + case WRITE_6: 103 + case WRITE_10: 104 + case WRITE_12: 105 + case WRITE_16: 106 + case WRITE_SAME: 107 + case WRITE_SAME_16: 108 + case UNMAP: 109 + return 1; 110 + case VARIABLE_LENGTH_CMD: 111 + switch (scmd->cmnd[9]) { 112 + case READ_32: 113 + case VERIFY_32: 114 + case WRITE_32: 115 + case WRITE_SAME_32: 116 + return 1; 117 + } 118 + } 119 + 120 + return 0; 121 + } 93 122 94 123 /* 95 124 * A DIF-capable target device can be formatted with different
+6
include/scsi/scsi_cmnd.h
··· 10 10 11 11 struct Scsi_Host; 12 12 struct scsi_device; 13 + struct scsi_driver; 13 14 14 15 /* 15 16 * MAX_COMMAND_SIZE is: ··· 131 130 132 131 unsigned char tag; /* SCSI-II queued command tag */ 133 132 }; 133 + 134 + static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) 135 + { 136 + return *(struct scsi_driver **)cmd->request->rq_disk->private_data; 137 + } 134 138 135 139 extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); 136 140 extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t);
+1
include/scsi/scsi_driver.h
··· 16 16 17 17 void (*rescan)(struct device *); 18 18 int (*done)(struct scsi_cmnd *); 19 + int (*eh_action)(struct scsi_cmnd *, unsigned char *, int, int); 19 20 }; 20 21 #define to_scsi_driver(drv) \ 21 22 container_of((drv), struct scsi_driver, gendrv)