aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2009-05-13 18:57:49 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-05-23 16:44:13 -0400
commitb3cd5050bf8eb32ceecee129cac7c59e6f1668c4 (patch)
tree5aa4999dd1c5c7fe83354f3965764f0849afaff3
parent1336aed10b8af791378b017f0fa8da4e5b827b8d (diff)
[SCSI] libiscsi: add task aborted state
If a task did not complete normally due to a TMF, libiscsi will now complete the task with the state ISCSI_TASK_ABRT_TMF. Drivers like bnx2i that need to free resources if a command did not complete normally can then check the task state. If a driver does not need to send a special command if we have dropped the session then they can check for ISCSI_TASK_ABRT_SESS_RECOV. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c7
-rw-r--r--drivers/scsi/libiscsi.c60
-rw-r--r--drivers/scsi/libiscsi_tcp.c4
-rw-r--r--include/scsi/libiscsi.h2
4 files changed, 41 insertions, 32 deletions
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index ffbe0c76bc11..0ba6ec876296 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -257,11 +257,8 @@ static void iscsi_iser_cleanup_task(struct iscsi_task *task)
257{ 257{
258 struct iscsi_iser_task *iser_task = task->dd_data; 258 struct iscsi_iser_task *iser_task = task->dd_data;
259 259
260 /* 260 /* mgmt tasks do not need special cleanup */
261 * mgmt tasks do not need special cleanup and we do not 261 if (!task->sc)
262 * allocate anything in the init task callout
263 */
264 if (!task->sc || task->state == ISCSI_TASK_PENDING)
265 return; 262 return;
266 263
267 if (iser_task->status == ISER_TASK_STATUS_STARTED) { 264 if (iser_task->status == ISER_TASK_STATUS_STARTED) {
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index dafa054537f6..b00be6c3efc1 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -443,18 +443,20 @@ EXPORT_SYMBOL_GPL(iscsi_put_task);
443/** 443/**
444 * iscsi_complete_task - finish a task 444 * iscsi_complete_task - finish a task
445 * @task: iscsi cmd task 445 * @task: iscsi cmd task
446 * @state: state to complete task with
446 * 447 *
447 * Must be called with session lock. 448 * Must be called with session lock.
448 */ 449 */
449static void iscsi_complete_task(struct iscsi_task *task) 450static void iscsi_complete_task(struct iscsi_task *task, int state)
450{ 451{
451 struct iscsi_conn *conn = task->conn; 452 struct iscsi_conn *conn = task->conn;
452 453
453 if (task->state == ISCSI_TASK_COMPLETED) 454 if (task->state == ISCSI_TASK_COMPLETED ||
455 task->state == ISCSI_TASK_ABRT_TMF ||
456 task->state == ISCSI_TASK_ABRT_SESS_RECOV)
454 return; 457 return;
455 WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); 458 WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
456 459 task->state = state;
457 task->state = ISCSI_TASK_COMPLETED;
458 460
459 if (!list_empty(&task->running)) 461 if (!list_empty(&task->running))
460 list_del_init(&task->running); 462 list_del_init(&task->running);
@@ -478,6 +480,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
478{ 480{
479 struct iscsi_conn *conn = task->conn; 481 struct iscsi_conn *conn = task->conn;
480 struct scsi_cmnd *sc; 482 struct scsi_cmnd *sc;
483 int state;
481 484
482 /* 485 /*
483 * if a command completes and we get a successful tmf response 486 * if a command completes and we get a successful tmf response
@@ -488,14 +491,20 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
488 if (!sc) 491 if (!sc)
489 return; 492 return;
490 493
491 if (task->state == ISCSI_TASK_PENDING) 494 if (task->state == ISCSI_TASK_PENDING) {
492 /* 495 /*
493 * cmd never made it to the xmit thread, so we should not count 496 * cmd never made it to the xmit thread, so we should not count
494 * the cmd in the sequencing 497 * the cmd in the sequencing
495 */ 498 */
496 conn->session->queued_cmdsn--; 499 conn->session->queued_cmdsn--;
500 /* it was never sent so just complete like normal */
501 state = ISCSI_TASK_COMPLETED;
502 } else if (err == DID_TRANSPORT_DISRUPTED)
503 state = ISCSI_TASK_ABRT_SESS_RECOV;
504 else
505 state = ISCSI_TASK_ABRT_TMF;
497 506
498 sc->result = err; 507 sc->result = err << 16;
499 if (!scsi_bidi_cmnd(sc)) 508 if (!scsi_bidi_cmnd(sc))
500 scsi_set_resid(sc, scsi_bufflen(sc)); 509 scsi_set_resid(sc, scsi_bufflen(sc));
501 else { 510 else {
@@ -503,7 +512,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
503 scsi_in(sc)->resid = scsi_in(sc)->length; 512 scsi_in(sc)->resid = scsi_in(sc)->length;
504 } 513 }
505 514
506 iscsi_complete_task(task); 515 iscsi_complete_task(task, state);
507} 516}
508 517
509static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, 518static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
@@ -731,7 +740,7 @@ out:
731 ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n", 740 ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n",
732 sc, sc->result, task->itt); 741 sc, sc->result, task->itt);
733 conn->scsirsp_pdus_cnt++; 742 conn->scsirsp_pdus_cnt++;
734 iscsi_complete_task(task); 743 iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
735} 744}
736 745
737/** 746/**
@@ -769,7 +778,7 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
769 "[sc %p res %d itt 0x%x]\n", 778 "[sc %p res %d itt 0x%x]\n",
770 sc, sc->result, task->itt); 779 sc, sc->result, task->itt);
771 conn->scsirsp_pdus_cnt++; 780 conn->scsirsp_pdus_cnt++;
772 iscsi_complete_task(task); 781 iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
773} 782}
774 783
775static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) 784static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
@@ -990,7 +999,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
990 } 999 }
991 1000
992 iscsi_tmf_rsp(conn, hdr); 1001 iscsi_tmf_rsp(conn, hdr);
993 iscsi_complete_task(task); 1002 iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
994 break; 1003 break;
995 case ISCSI_OP_NOOP_IN: 1004 case ISCSI_OP_NOOP_IN:
996 iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); 1005 iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
@@ -1008,7 +1017,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
1008 goto recv_pdu; 1017 goto recv_pdu;
1009 1018
1010 mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); 1019 mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
1011 iscsi_complete_task(task); 1020 iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
1012 break; 1021 break;
1013 default: 1022 default:
1014 rc = ISCSI_ERR_BAD_OPCODE; 1023 rc = ISCSI_ERR_BAD_OPCODE;
@@ -1020,7 +1029,7 @@ out:
1020recv_pdu: 1029recv_pdu:
1021 if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) 1030 if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
1022 rc = ISCSI_ERR_CONN_FAILED; 1031 rc = ISCSI_ERR_CONN_FAILED;
1023 iscsi_complete_task(task); 1032 iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
1024 return rc; 1033 return rc;
1025} 1034}
1026EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); 1035EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
@@ -1262,7 +1271,7 @@ check_mgmt:
1262 struct iscsi_task, running); 1271 struct iscsi_task, running);
1263 list_del_init(&conn->task->running); 1272 list_del_init(&conn->task->running);
1264 if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { 1273 if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
1265 fail_scsi_task(conn->task, DID_IMM_RETRY << 16); 1274 fail_scsi_task(conn->task, DID_IMM_RETRY);
1266 continue; 1275 continue;
1267 } 1276 }
1268 rc = iscsi_prep_scsi_cmd_pdu(conn->task); 1277 rc = iscsi_prep_scsi_cmd_pdu(conn->task);
@@ -1273,7 +1282,7 @@ check_mgmt:
1273 conn->task = NULL; 1282 conn->task = NULL;
1274 goto again; 1283 goto again;
1275 } else 1284 } else
1276 fail_scsi_task(conn->task, DID_ABORT << 16); 1285 fail_scsi_task(conn->task, DID_ABORT);
1277 continue; 1286 continue;
1278 } 1287 }
1279 rc = iscsi_xmit_task(conn); 1288 rc = iscsi_xmit_task(conn);
@@ -1469,7 +1478,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
1469 1478
1470prepd_reject: 1479prepd_reject:
1471 sc->scsi_done = NULL; 1480 sc->scsi_done = NULL;
1472 iscsi_complete_task(task); 1481 iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
1473reject: 1482reject:
1474 spin_unlock(&session->lock); 1483 spin_unlock(&session->lock);
1475 ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", 1484 ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
@@ -1479,7 +1488,7 @@ reject:
1479 1488
1480prepd_fault: 1489prepd_fault:
1481 sc->scsi_done = NULL; 1490 sc->scsi_done = NULL;
1482 iscsi_complete_task(task); 1491 iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
1483fault: 1492fault:
1484 spin_unlock(&session->lock); 1493 spin_unlock(&session->lock);
1485 ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", 1494 ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
@@ -1665,7 +1674,7 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun,
1665 ISCSI_DBG_SESSION(conn->session, 1674 ISCSI_DBG_SESSION(conn->session,
1666 "failing sc %p itt 0x%x state %d\n", 1675 "failing sc %p itt 0x%x state %d\n",
1667 task->sc, task->itt, task->state); 1676 task->sc, task->itt, task->state);
1668 fail_scsi_task(task, error << 16); 1677 fail_scsi_task(task, error);
1669 } 1678 }
1670} 1679}
1671 1680
@@ -1868,7 +1877,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
1868 } 1877 }
1869 1878
1870 if (task->state == ISCSI_TASK_PENDING) { 1879 if (task->state == ISCSI_TASK_PENDING) {
1871 fail_scsi_task(task, DID_ABORT << 16); 1880 fail_scsi_task(task, DID_ABORT);
1872 goto success; 1881 goto success;
1873 } 1882 }
1874 1883
@@ -1899,7 +1908,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
1899 * then sent more data for the cmd. 1908 * then sent more data for the cmd.
1900 */ 1909 */
1901 spin_lock(&session->lock); 1910 spin_lock(&session->lock);
1902 fail_scsi_task(task, DID_ABORT << 16); 1911 fail_scsi_task(task, DID_ABORT);
1903 conn->tmf_state = TMF_INITIAL; 1912 conn->tmf_state = TMF_INITIAL;
1904 spin_unlock(&session->lock); 1913 spin_unlock(&session->lock);
1905 iscsi_start_tx(conn); 1914 iscsi_start_tx(conn);
@@ -2572,7 +2581,7 @@ static void
2572fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) 2581fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
2573{ 2582{
2574 struct iscsi_task *task; 2583 struct iscsi_task *task;
2575 int i; 2584 int i, state;
2576 2585
2577 for (i = 0; i < conn->session->cmds_max; i++) { 2586 for (i = 0; i < conn->session->cmds_max; i++) {
2578 task = conn->session->cmds[i]; 2587 task = conn->session->cmds[i];
@@ -2585,7 +2594,11 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
2585 ISCSI_DBG_SESSION(conn->session, 2594 ISCSI_DBG_SESSION(conn->session,
2586 "failing mgmt itt 0x%x state %d\n", 2595 "failing mgmt itt 0x%x state %d\n",
2587 task->itt, task->state); 2596 task->itt, task->state);
2588 iscsi_complete_task(task); 2597 state = ISCSI_TASK_ABRT_SESS_RECOV;
2598 if (task->state == ISCSI_TASK_PENDING)
2599 state = ISCSI_TASK_COMPLETED;
2600 iscsi_complete_task(task, state);
2601
2589 } 2602 }
2590} 2603}
2591 2604
@@ -2642,10 +2655,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
2642 * flush queues. 2655 * flush queues.
2643 */ 2656 */
2644 spin_lock_bh(&session->lock); 2657 spin_lock_bh(&session->lock);
2645 if (flag == STOP_CONN_RECOVER) 2658 fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
2646 fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
2647 else
2648 fail_scsi_tasks(conn, -1, DID_ERROR);
2649 fail_mgmt_tasks(session, conn); 2659 fail_mgmt_tasks(session, conn);
2650 spin_unlock_bh(&session->lock); 2660 spin_unlock_bh(&session->lock);
2651 mutex_unlock(&session->eh_mutex); 2661 mutex_unlock(&session->eh_mutex);
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index b84a1d853f29..2bc07090321d 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -440,8 +440,8 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task)
440 struct iscsi_tcp_task *tcp_task = task->dd_data; 440 struct iscsi_tcp_task *tcp_task = task->dd_data;
441 struct iscsi_r2t_info *r2t; 441 struct iscsi_r2t_info *r2t;
442 442
443 /* nothing to do for mgmt or pending tasks */ 443 /* nothing to do for mgmt */
444 if (!task->sc || task->state == ISCSI_TASK_PENDING) 444 if (!task->sc)
445 return; 445 return;
446 446
447 /* flush task's r2t queues */ 447 /* flush task's r2t queues */
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index facae71183a5..196525cd402f 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -86,6 +86,8 @@ enum {
86 ISCSI_TASK_COMPLETED, 86 ISCSI_TASK_COMPLETED,
87 ISCSI_TASK_PENDING, 87 ISCSI_TASK_PENDING,
88 ISCSI_TASK_RUNNING, 88 ISCSI_TASK_RUNNING,
89 ISCSI_TASK_ABRT_TMF, /* aborted due to TMF */
90 ISCSI_TASK_ABRT_SESS_RECOV, /* aborted due to session recovery */
89}; 91};
90 92
91struct iscsi_r2t_info { 93struct iscsi_r2t_info {