aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_error.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r--drivers/scsi/scsi_error.c146
1 files changed, 133 insertions, 13 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 83e591b60193..e8bee9f0ad0f 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -87,6 +87,18 @@ void scsi_schedule_eh(struct Scsi_Host *shost)
87} 87}
88EXPORT_SYMBOL_GPL(scsi_schedule_eh); 88EXPORT_SYMBOL_GPL(scsi_schedule_eh);
89 89
90static int scsi_host_eh_past_deadline(struct Scsi_Host *shost)
91{
92 if (!shost->last_reset || !shost->eh_deadline)
93 return 0;
94
95 if (time_before(jiffies,
96 shost->last_reset + shost->eh_deadline))
97 return 0;
98
99 return 1;
100}
101
90/** 102/**
91 * scsi_eh_scmd_add - add scsi cmd to error handling. 103 * scsi_eh_scmd_add - add scsi cmd to error handling.
92 * @scmd: scmd to run eh on. 104 * @scmd: scmd to run eh on.
@@ -109,6 +121,9 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
109 if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) 121 if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY))
110 goto out_unlock; 122 goto out_unlock;
111 123
124 if (shost->eh_deadline && !shost->last_reset)
125 shost->last_reset = jiffies;
126
112 ret = 1; 127 ret = 1;
113 scmd->eh_eflags |= eh_flag; 128 scmd->eh_eflags |= eh_flag;
114 list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); 129 list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
@@ -138,6 +153,9 @@ enum blk_eh_timer_return scsi_times_out(struct request *req)
138 trace_scsi_dispatch_cmd_timeout(scmd); 153 trace_scsi_dispatch_cmd_timeout(scmd);
139 scsi_log_completion(scmd, TIMEOUT_ERROR); 154 scsi_log_completion(scmd, TIMEOUT_ERROR);
140 155
156 if (host->eh_deadline && !host->last_reset)
157 host->last_reset = jiffies;
158
141 if (host->transportt->eh_timed_out) 159 if (host->transportt->eh_timed_out)
142 rtn = host->transportt->eh_timed_out(scmd); 160 rtn = host->transportt->eh_timed_out(scmd);
143 else if (host->hostt->eh_timed_out) 161 else if (host->hostt->eh_timed_out)
@@ -990,13 +1008,26 @@ int scsi_eh_get_sense(struct list_head *work_q,
990 struct list_head *done_q) 1008 struct list_head *done_q)
991{ 1009{
992 struct scsi_cmnd *scmd, *next; 1010 struct scsi_cmnd *scmd, *next;
1011 struct Scsi_Host *shost;
993 int rtn; 1012 int rtn;
1013 unsigned long flags;
994 1014
995 list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 1015 list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
996 if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) || 1016 if ((scmd->eh_eflags & SCSI_EH_CANCEL_CMD) ||
997 SCSI_SENSE_VALID(scmd)) 1017 SCSI_SENSE_VALID(scmd))
998 continue; 1018 continue;
999 1019
1020 shost = scmd->device->host;
1021 spin_lock_irqsave(shost->host_lock, flags);
1022 if (scsi_host_eh_past_deadline(shost)) {
1023 spin_unlock_irqrestore(shost->host_lock, flags);
1024 SCSI_LOG_ERROR_RECOVERY(3,
1025 shost_printk(KERN_INFO, shost,
1026 "skip %s, past eh deadline\n",
1027 __func__));
1028 break;
1029 }
1030 spin_unlock_irqrestore(shost->host_lock, flags);
1000 SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd, 1031 SCSI_LOG_ERROR_RECOVERY(2, scmd_printk(KERN_INFO, scmd,
1001 "%s: requesting sense\n", 1032 "%s: requesting sense\n",
1002 current->comm)); 1033 current->comm));
@@ -1082,11 +1113,28 @@ static int scsi_eh_test_devices(struct list_head *cmd_list,
1082 struct scsi_cmnd *scmd, *next; 1113 struct scsi_cmnd *scmd, *next;
1083 struct scsi_device *sdev; 1114 struct scsi_device *sdev;
1084 int finish_cmds; 1115 int finish_cmds;
1116 unsigned long flags;
1085 1117
1086 while (!list_empty(cmd_list)) { 1118 while (!list_empty(cmd_list)) {
1087 scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry); 1119 scmd = list_entry(cmd_list->next, struct scsi_cmnd, eh_entry);
1088 sdev = scmd->device; 1120 sdev = scmd->device;
1089 1121
1122 if (!try_stu) {
1123 spin_lock_irqsave(sdev->host->host_lock, flags);
1124 if (scsi_host_eh_past_deadline(sdev->host)) {
1125 /* Push items back onto work_q */
1126 list_splice_init(cmd_list, work_q);
1127 spin_unlock_irqrestore(sdev->host->host_lock,
1128 flags);
1129 SCSI_LOG_ERROR_RECOVERY(3,
1130 shost_printk(KERN_INFO, sdev->host,
1131 "skip %s, past eh deadline",
1132 __func__));
1133 break;
1134 }
1135 spin_unlock_irqrestore(sdev->host->host_lock, flags);
1136 }
1137
1090 finish_cmds = !scsi_device_online(scmd->device) || 1138 finish_cmds = !scsi_device_online(scmd->device) ||
1091 (try_stu && !scsi_eh_try_stu(scmd) && 1139 (try_stu && !scsi_eh_try_stu(scmd) &&
1092 !scsi_eh_tur(scmd)) || 1140 !scsi_eh_tur(scmd)) ||
@@ -1122,26 +1170,42 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
1122 struct scsi_cmnd *scmd, *next; 1170 struct scsi_cmnd *scmd, *next;
1123 LIST_HEAD(check_list); 1171 LIST_HEAD(check_list);
1124 int rtn; 1172 int rtn;
1173 struct Scsi_Host *shost;
1174 unsigned long flags;
1125 1175
1126 list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 1176 list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1127 if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD)) 1177 if (!(scmd->eh_eflags & SCSI_EH_CANCEL_CMD))
1128 continue; 1178 continue;
1179 shost = scmd->device->host;
1180 spin_lock_irqsave(shost->host_lock, flags);
1181 if (scsi_host_eh_past_deadline(shost)) {
1182 spin_unlock_irqrestore(shost->host_lock, flags);
1183 list_splice_init(&check_list, work_q);
1184 SCSI_LOG_ERROR_RECOVERY(3,
1185 shost_printk(KERN_INFO, shost,
1186 "skip %s, past eh deadline\n",
1187 __func__));
1188 return list_empty(work_q);
1189 }
1190 spin_unlock_irqrestore(shost->host_lock, flags);
1129 SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:" 1191 SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:"
1130 "0x%p\n", current->comm, 1192 "0x%p\n", current->comm,
1131 scmd)); 1193 scmd));
1132 rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd); 1194 rtn = scsi_try_to_abort_cmd(shost->hostt, scmd);
1133 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { 1195 if (rtn == FAILED) {
1134 scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
1135 if (rtn == FAST_IO_FAIL)
1136 scsi_eh_finish_cmd(scmd, done_q);
1137 else
1138 list_move_tail(&scmd->eh_entry, &check_list);
1139 } else
1140 SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting" 1196 SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting"
1141 " cmd failed:" 1197 " cmd failed:"
1142 "0x%p\n", 1198 "0x%p\n",
1143 current->comm, 1199 current->comm,
1144 scmd)); 1200 scmd));
1201 list_splice_init(&check_list, work_q);
1202 return list_empty(work_q);
1203 }
1204 scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
1205 if (rtn == FAST_IO_FAIL)
1206 scsi_eh_finish_cmd(scmd, done_q);
1207 else
1208 list_move_tail(&scmd->eh_entry, &check_list);
1145 } 1209 }
1146 1210
1147 return scsi_eh_test_devices(&check_list, work_q, done_q, 0); 1211 return scsi_eh_test_devices(&check_list, work_q, done_q, 0);
@@ -1187,8 +1251,19 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
1187{ 1251{
1188 struct scsi_cmnd *scmd, *stu_scmd, *next; 1252 struct scsi_cmnd *scmd, *stu_scmd, *next;
1189 struct scsi_device *sdev; 1253 struct scsi_device *sdev;
1254 unsigned long flags;
1190 1255
1191 shost_for_each_device(sdev, shost) { 1256 shost_for_each_device(sdev, shost) {
1257 spin_lock_irqsave(shost->host_lock, flags);
1258 if (scsi_host_eh_past_deadline(shost)) {
1259 spin_unlock_irqrestore(shost->host_lock, flags);
1260 SCSI_LOG_ERROR_RECOVERY(3,
1261 shost_printk(KERN_INFO, shost,
1262 "skip %s, past eh deadline\n",
1263 __func__));
1264 break;
1265 }
1266 spin_unlock_irqrestore(shost->host_lock, flags);
1192 stu_scmd = NULL; 1267 stu_scmd = NULL;
1193 list_for_each_entry(scmd, work_q, eh_entry) 1268 list_for_each_entry(scmd, work_q, eh_entry)
1194 if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) && 1269 if (scmd->device == sdev && SCSI_SENSE_VALID(scmd) &&
@@ -1241,9 +1316,20 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
1241{ 1316{
1242 struct scsi_cmnd *scmd, *bdr_scmd, *next; 1317 struct scsi_cmnd *scmd, *bdr_scmd, *next;
1243 struct scsi_device *sdev; 1318 struct scsi_device *sdev;
1319 unsigned long flags;
1244 int rtn; 1320 int rtn;
1245 1321
1246 shost_for_each_device(sdev, shost) { 1322 shost_for_each_device(sdev, shost) {
1323 spin_lock_irqsave(shost->host_lock, flags);
1324 if (scsi_host_eh_past_deadline(shost)) {
1325 spin_unlock_irqrestore(shost->host_lock, flags);
1326 SCSI_LOG_ERROR_RECOVERY(3,
1327 shost_printk(KERN_INFO, shost,
1328 "skip %s, past eh deadline\n",
1329 __func__));
1330 break;
1331 }
1332 spin_unlock_irqrestore(shost->host_lock, flags);
1247 bdr_scmd = NULL; 1333 bdr_scmd = NULL;
1248 list_for_each_entry(scmd, work_q, eh_entry) 1334 list_for_each_entry(scmd, work_q, eh_entry)
1249 if (scmd->device == sdev) { 1335 if (scmd->device == sdev) {
@@ -1303,6 +1389,21 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
1303 struct scsi_cmnd *next, *scmd; 1389 struct scsi_cmnd *next, *scmd;
1304 int rtn; 1390 int rtn;
1305 unsigned int id; 1391 unsigned int id;
1392 unsigned long flags;
1393
1394 spin_lock_irqsave(shost->host_lock, flags);
1395 if (scsi_host_eh_past_deadline(shost)) {
1396 spin_unlock_irqrestore(shost->host_lock, flags);
1397 /* push back on work queue for further processing */
1398 list_splice_init(&check_list, work_q);
1399 list_splice_init(&tmp_list, work_q);
1400 SCSI_LOG_ERROR_RECOVERY(3,
1401 shost_printk(KERN_INFO, shost,
1402 "skip %s, past eh deadline\n",
1403 __func__));
1404 return list_empty(work_q);
1405 }
1406 spin_unlock_irqrestore(shost->host_lock, flags);
1306 1407
1307 scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry); 1408 scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry);
1308 id = scmd_id(scmd); 1409 id = scmd_id(scmd);
@@ -1347,6 +1448,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
1347 LIST_HEAD(check_list); 1448 LIST_HEAD(check_list);
1348 unsigned int channel; 1449 unsigned int channel;
1349 int rtn; 1450 int rtn;
1451 unsigned long flags;
1350 1452
1351 /* 1453 /*
1352 * we really want to loop over the various channels, and do this on 1454 * we really want to loop over the various channels, and do this on
@@ -1356,6 +1458,18 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
1356 */ 1458 */
1357 1459
1358 for (channel = 0; channel <= shost->max_channel; channel++) { 1460 for (channel = 0; channel <= shost->max_channel; channel++) {
1461 spin_lock_irqsave(shost->host_lock, flags);
1462 if (scsi_host_eh_past_deadline(shost)) {
1463 spin_unlock_irqrestore(shost->host_lock, flags);
1464 list_splice_init(&check_list, work_q);
1465 SCSI_LOG_ERROR_RECOVERY(3,
1466 shost_printk(KERN_INFO, shost,
1467 "skip %s, past eh deadline\n",
1468 __func__));
1469 return list_empty(work_q);
1470 }
1471 spin_unlock_irqrestore(shost->host_lock, flags);
1472
1359 chan_scmd = NULL; 1473 chan_scmd = NULL;
1360 list_for_each_entry(scmd, work_q, eh_entry) { 1474 list_for_each_entry(scmd, work_q, eh_entry) {
1361 if (channel == scmd_channel(scmd)) { 1475 if (channel == scmd_channel(scmd)) {
@@ -1755,8 +1869,9 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
1755 * will be requests for character device operations, and also for 1869 * will be requests for character device operations, and also for
1756 * ioctls to queued block devices. 1870 * ioctls to queued block devices.
1757 */ 1871 */
1758 SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", 1872 SCSI_LOG_ERROR_RECOVERY(3,
1759 __func__)); 1873 printk("scsi_eh_%d waking up host to restart\n",
1874 shost->host_no));
1760 1875
1761 spin_lock_irqsave(shost->host_lock, flags); 1876 spin_lock_irqsave(shost->host_lock, flags);
1762 if (scsi_host_set_state(shost, SHOST_RUNNING)) 1877 if (scsi_host_set_state(shost, SHOST_RUNNING))
@@ -1883,6 +1998,10 @@ static void scsi_unjam_host(struct Scsi_Host *shost)
1883 if (!scsi_eh_abort_cmds(&eh_work_q, &eh_done_q)) 1998 if (!scsi_eh_abort_cmds(&eh_work_q, &eh_done_q))
1884 scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q); 1999 scsi_eh_ready_devs(shost, &eh_work_q, &eh_done_q);
1885 2000
2001 spin_lock_irqsave(shost->host_lock, flags);
2002 if (shost->eh_deadline)
2003 shost->last_reset = 0;
2004 spin_unlock_irqrestore(shost->host_lock, flags);
1886 scsi_eh_flush_done_q(&eh_done_q); 2005 scsi_eh_flush_done_q(&eh_done_q);
1887} 2006}
1888 2007
@@ -1909,7 +2028,7 @@ int scsi_error_handler(void *data)
1909 if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || 2028 if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
1910 shost->host_failed != shost->host_busy) { 2029 shost->host_failed != shost->host_busy) {
1911 SCSI_LOG_ERROR_RECOVERY(1, 2030 SCSI_LOG_ERROR_RECOVERY(1,
1912 printk("Error handler scsi_eh_%d sleeping\n", 2031 printk("scsi_eh_%d: sleeping\n",
1913 shost->host_no)); 2032 shost->host_no));
1914 schedule(); 2033 schedule();
1915 continue; 2034 continue;
@@ -1917,8 +2036,9 @@ int scsi_error_handler(void *data)
1917 2036
1918 __set_current_state(TASK_RUNNING); 2037 __set_current_state(TASK_RUNNING);
1919 SCSI_LOG_ERROR_RECOVERY(1, 2038 SCSI_LOG_ERROR_RECOVERY(1,
1920 printk("Error handler scsi_eh_%d waking up\n", 2039 printk("scsi_eh_%d: waking up %d/%d/%d\n",
1921 shost->host_no)); 2040 shost->host_no, shost->host_eh_scheduled,
2041 shost->host_failed, shost->host_busy));
1922 2042
1923 /* 2043 /*
1924 * We have a host that is failing for some reason. Figure out 2044 * We have a host that is failing for some reason. Figure out