aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2008-08-19 19:45:31 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-10-13 09:28:52 -0400
commit4a27446f3e39b06c28d1c8e31d33a5340826ed5c (patch)
treee55c982632ab6e0a8484f8267fce8f159b6f78dc /drivers/scsi
parent6000a368cd8e6da1caf101411bdb494cd6fb8b09 (diff)
[SCSI] modify scsi to handle new fail fast flags.
This checks the errors the scsi-ml determined were retryable and returns if we should fast fail it based on the request fail fast flags. Without the patch, drivers like lpfc, qla2xxx and fcoe would return DID_ERROR for what it determines is a temporary communication problem. There is no loss of connectivity at that time and the driver thinks that it would be fast to retry at the driver level. SCSI-ml will however sees fast fail on the request and DID_ERROR and will fast fail the io. This will then cause dm-multipath to fail the path and possibley switch target controllers when we should be retrying at the scsi layer. We also were fast failing device errors to dm multiapth when unless the scsi_dh modules think otherwis we want to retry at the scsi layer because multipath can only retry the IO like scsi should have done. multipath is a little dumber though because it does not what the error was for and assumes that it should fail the paths. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_error.c38
-rw-r--r--drivers/scsi/scsi_lib.c2
-rw-r--r--drivers/scsi/scsi_priv.h1
3 files changed, 38 insertions, 3 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 5bf8be21a165..ad019ece2139 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1219,6 +1219,40 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q,
1219} 1219}
1220 1220
1221/** 1221/**
1222 * scsi_noretry_cmd - determinte if command should be failed fast
1223 * @scmd: SCSI cmd to examine.
1224 */
1225int scsi_noretry_cmd(struct scsi_cmnd *scmd)
1226{
1227 switch (host_byte(scmd->result)) {
1228 case DID_OK:
1229 break;
1230 case DID_BUS_BUSY:
1231 return blk_failfast_transport(scmd->request);
1232 case DID_PARITY:
1233 return blk_failfast_dev(scmd->request);
1234 case DID_ERROR:
1235 if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
1236 status_byte(scmd->result) == RESERVATION_CONFLICT)
1237 return 0;
1238 /* fall through */
1239 case DID_SOFT_ERROR:
1240 return blk_failfast_driver(scmd->request);
1241 }
1242
1243 switch (status_byte(scmd->result)) {
1244 case CHECK_CONDITION:
1245 /*
1246 * assume caller has checked sense and determinted
1247 * the check condition was retryable.
1248 */
1249 return blk_failfast_dev(scmd->request);
1250 }
1251
1252 return 0;
1253}
1254
1255/**
1222 * scsi_decide_disposition - Disposition a cmd on return from LLD. 1256 * scsi_decide_disposition - Disposition a cmd on return from LLD.
1223 * @scmd: SCSI cmd to examine. 1257 * @scmd: SCSI cmd to examine.
1224 * 1258 *
@@ -1396,7 +1430,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
1396 * even if the request is marked fast fail, we still requeue 1430 * even if the request is marked fast fail, we still requeue
1397 * for queue congestion conditions (QUEUE_FULL or BUSY) */ 1431 * for queue congestion conditions (QUEUE_FULL or BUSY) */
1398 if ((++scmd->retries) <= scmd->allowed 1432 if ((++scmd->retries) <= scmd->allowed
1399 && !blk_noretry_request(scmd->request)) { 1433 && !scsi_noretry_cmd(scmd)) {
1400 return NEEDS_RETRY; 1434 return NEEDS_RETRY;
1401 } else { 1435 } else {
1402 /* 1436 /*
@@ -1521,7 +1555,7 @@ void scsi_eh_flush_done_q(struct list_head *done_q)
1521 list_for_each_entry_safe(scmd, next, done_q, eh_entry) { 1555 list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
1522 list_del_init(&scmd->eh_entry); 1556 list_del_init(&scmd->eh_entry);
1523 if (scsi_device_online(scmd->device) && 1557 if (scsi_device_online(scmd->device) &&
1524 !blk_noretry_request(scmd->request) && 1558 !scsi_noretry_cmd(scmd) &&
1525 (++scmd->retries <= scmd->allowed)) { 1559 (++scmd->retries <= scmd->allowed)) {
1526 SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush" 1560 SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush"
1527 " retry cmd: %p\n", 1561 " retry cmd: %p\n",
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 91c74c55aa5e..e5a9526d2037 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -706,7 +706,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error,
706 leftover = req->data_len; 706 leftover = req->data_len;
707 707
708 /* kill remainder if no retrys */ 708 /* kill remainder if no retrys */
709 if (error && blk_noretry_request(req)) 709 if (error && scsi_noretry_cmd(cmd))
710 blk_end_request(req, error, leftover); 710 blk_end_request(req, error, leftover);
711 else { 711 else {
712 if (requeue) { 712 if (requeue) {
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 6cddd5dd323c..e1850904ff73 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -59,6 +59,7 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost,
59 struct list_head *done_q); 59 struct list_head *done_q);
60int scsi_eh_get_sense(struct list_head *work_q, 60int scsi_eh_get_sense(struct list_head *work_q,
61 struct list_head *done_q); 61 struct list_head *done_q);
62int scsi_noretry_cmd(struct scsi_cmnd *scmd);
62 63
63/* scsi_lib.c */ 64/* scsi_lib.c */
64extern int scsi_maybe_unblock_host(struct scsi_device *sdev); 65extern int scsi_maybe_unblock_host(struct scsi_device *sdev);