aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_error.c
diff options
context:
space:
mode:
authorChristof Schmitt <christof.schmitt@de.ibm.com>2010-03-24 11:50:30 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-04-11 10:49:33 -0400
commit2f2eb58762b4dcddfe25c90800323765c1257eca (patch)
treef69788ac1afc0b7924a033cb82f33dbc55b6af1c /drivers/scsi/scsi_error.c
parent7794a5af67c672d44cfdbc7172a608b7542a66e3 (diff)
[SCSI] Allow FC LLD to fast-fail scsi eh by introducing new eh return
If the scsi eh is running and then a FC LLD calls fc_remote_port_delete, the SCSI commands sent from the eh will fail. To prevent this, a FC LLD can call fc_block_scsi_eh from the eh callback, blocking the eh thread until the dev_loss_tmo fires or the remote port is available again. If (e.g. for a multipathing setup) the dev_loss_tmo is set to a very large value, thus preventing the scsi device removal , the scsi eh can block for a long time. For multipathing, the fast_io_fail_tmo is then set to a low value to detect path problems sooner. This patch introduces a new return code FAST_IO_FAIL. The function fc_block_scsi_eh now returns FAST_IO_FAIL when the fast_io_fail_tmo fires. This indicates that the LLD terminated all pending I/O requests and there are no more pending SCSI commands for the scsi eh to wait for. This return code can be passed back to the scsi eh to stop the escalation and finish the recovery process for this device. Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r--drivers/scsi/scsi_error.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index d45c69ca573..33175974b55 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -957,9 +957,10 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
957 "0x%p\n", current->comm, 957 "0x%p\n", current->comm,
958 scmd)); 958 scmd));
959 rtn = scsi_try_to_abort_cmd(scmd); 959 rtn = scsi_try_to_abort_cmd(scmd);
960 if (rtn == SUCCESS) { 960 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
961 scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD; 961 scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
962 if (!scsi_device_online(scmd->device) || 962 if (!scsi_device_online(scmd->device) ||
963 rtn == FAST_IO_FAIL ||
963 !scsi_eh_tur(scmd)) { 964 !scsi_eh_tur(scmd)) {
964 scsi_eh_finish_cmd(scmd, done_q); 965 scsi_eh_finish_cmd(scmd, done_q);
965 } 966 }
@@ -1086,8 +1087,9 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
1086 " 0x%p\n", current->comm, 1087 " 0x%p\n", current->comm,
1087 sdev)); 1088 sdev));
1088 rtn = scsi_try_bus_device_reset(bdr_scmd); 1089 rtn = scsi_try_bus_device_reset(bdr_scmd);
1089 if (rtn == SUCCESS) { 1090 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1090 if (!scsi_device_online(sdev) || 1091 if (!scsi_device_online(sdev) ||
1092 rtn == FAST_IO_FAIL ||
1091 !scsi_eh_tur(bdr_scmd)) { 1093 !scsi_eh_tur(bdr_scmd)) {
1092 list_for_each_entry_safe(scmd, next, 1094 list_for_each_entry_safe(scmd, next,
1093 work_q, eh_entry) { 1095 work_q, eh_entry) {
@@ -1150,10 +1152,11 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
1150 "to target %d\n", 1152 "to target %d\n",
1151 current->comm, id)); 1153 current->comm, id));
1152 rtn = scsi_try_target_reset(tgtr_scmd); 1154 rtn = scsi_try_target_reset(tgtr_scmd);
1153 if (rtn == SUCCESS) { 1155 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1154 list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 1156 list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1155 if (id == scmd_id(scmd)) 1157 if (id == scmd_id(scmd))
1156 if (!scsi_device_online(scmd->device) || 1158 if (!scsi_device_online(scmd->device) ||
1159 rtn == FAST_IO_FAIL ||
1157 !scsi_eh_tur(tgtr_scmd)) 1160 !scsi_eh_tur(tgtr_scmd))
1158 scsi_eh_finish_cmd(scmd, 1161 scsi_eh_finish_cmd(scmd,
1159 done_q); 1162 done_q);
@@ -1209,10 +1212,11 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
1209 " %d\n", current->comm, 1212 " %d\n", current->comm,
1210 channel)); 1213 channel));
1211 rtn = scsi_try_bus_reset(chan_scmd); 1214 rtn = scsi_try_bus_reset(chan_scmd);
1212 if (rtn == SUCCESS) { 1215 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1213 list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 1216 list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1214 if (channel == scmd_channel(scmd)) 1217 if (channel == scmd_channel(scmd))
1215 if (!scsi_device_online(scmd->device) || 1218 if (!scsi_device_online(scmd->device) ||
1219 rtn == FAST_IO_FAIL ||
1216 !scsi_eh_tur(scmd)) 1220 !scsi_eh_tur(scmd))
1217 scsi_eh_finish_cmd(scmd, 1221 scsi_eh_finish_cmd(scmd,
1218 done_q); 1222 done_q);
@@ -1246,9 +1250,10 @@ static int scsi_eh_host_reset(struct list_head *work_q,
1246 , current->comm)); 1250 , current->comm));
1247 1251
1248 rtn = scsi_try_host_reset(scmd); 1252 rtn = scsi_try_host_reset(scmd);
1249 if (rtn == SUCCESS) { 1253 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1250 list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 1254 list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1251 if (!scsi_device_online(scmd->device) || 1255 if (!scsi_device_online(scmd->device) ||
1256 rtn == FAST_IO_FAIL ||
1252 (!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) || 1257 (!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) ||
1253 !scsi_eh_tur(scmd)) 1258 !scsi_eh_tur(scmd))
1254 scsi_eh_finish_cmd(scmd, done_q); 1259 scsi_eh_finish_cmd(scmd, done_q);