aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libiscsi.c71
-rw-r--r--include/scsi/libiscsi.h1
2 files changed, 47 insertions, 25 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 1a8cd20f484f..4e2ca8f7d9a1 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -276,6 +276,25 @@ out:
276 return rc; 276 return rc;
277} 277}
278 278
279static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
280{
281 struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
282
283 conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
284 conn->tmfrsp_pdus_cnt++;
285
286 if (conn->tmabort_state != TMABORT_INITIAL)
287 return;
288
289 if (tmf->response == ISCSI_TMF_RSP_COMPLETE)
290 conn->tmabort_state = TMABORT_SUCCESS;
291 else if (tmf->response == ISCSI_TMF_RSP_NO_TASK)
292 conn->tmabort_state = TMABORT_NOT_FOUND;
293 else
294 conn->tmabort_state = TMABORT_FAILED;
295 wake_up(&conn->ehwait);
296}
297
279/** 298/**
280 * __iscsi_complete_pdu - complete pdu 299 * __iscsi_complete_pdu - complete pdu
281 * @conn: iscsi conn 300 * @conn: iscsi conn
@@ -361,16 +380,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
361 break; 380 break;
362 } 381 }
363 382
364 conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; 383 iscsi_tmf_rsp(conn, hdr);
365 conn->tmfrsp_pdus_cnt++;
366 if (conn->tmabort_state == TMABORT_INITIAL) {
367 conn->tmabort_state =
368 ((struct iscsi_tm_rsp *)hdr)->
369 response == ISCSI_TMF_RSP_COMPLETE ?
370 TMABORT_SUCCESS:TMABORT_FAILED;
371 /* unblock eh_abort() */
372 wake_up(&conn->ehwait);
373 }
374 break; 384 break;
375 case ISCSI_OP_NOOP_IN: 385 case ISCSI_OP_NOOP_IN:
376 if (hdr->ttt != ISCSI_RESERVED_TAG) { 386 if (hdr->ttt != ISCSI_RESERVED_TAG) {
@@ -1029,12 +1039,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1029{ 1039{
1030 struct scsi_cmnd *sc; 1040 struct scsi_cmnd *sc;
1031 1041
1032 conn->session->tt->cleanup_cmd_task(conn, ctask);
1033 iscsi_ctask_mtask_cleanup(ctask);
1034
1035 sc = ctask->sc; 1042 sc = ctask->sc;
1036 if (!sc) 1043 if (!sc)
1037 return; 1044 return;
1045
1046 conn->session->tt->cleanup_cmd_task(conn, ctask);
1047 iscsi_ctask_mtask_cleanup(ctask);
1048
1038 sc->result = err; 1049 sc->result = err;
1039 sc->resid = sc->request_bufflen; 1050 sc->resid = sc->request_bufflen;
1040 iscsi_complete_command(conn->session, ctask); 1051 iscsi_complete_command(conn->session, ctask);
@@ -1062,8 +1073,11 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
1062 goto failed; 1073 goto failed;
1063 1074
1064 /* ctask completed before time out */ 1075 /* ctask completed before time out */
1065 if (!ctask->sc) 1076 if (!ctask->sc) {
1066 goto success; 1077 spin_unlock_bh(&session->lock);
1078 debug_scsi("sc completed while abort in progress\n");
1079 goto success_rel_mutex;
1080 }
1067 1081
1068 /* what should we do here ? */ 1082 /* what should we do here ? */
1069 if (conn->ctask == ctask) { 1083 if (conn->ctask == ctask) {
@@ -1073,7 +1087,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
1073 } 1087 }
1074 1088
1075 if (ctask->state == ISCSI_TASK_PENDING) 1089 if (ctask->state == ISCSI_TASK_PENDING)
1076 goto success; 1090 goto success_cleanup;
1077 1091
1078 conn->tmabort_state = TMABORT_INITIAL; 1092 conn->tmabort_state = TMABORT_INITIAL;
1079 1093
@@ -1081,25 +1095,31 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
1081 rc = iscsi_exec_abort_task(sc, ctask); 1095 rc = iscsi_exec_abort_task(sc, ctask);
1082 spin_lock_bh(&session->lock); 1096 spin_lock_bh(&session->lock);
1083 1097
1084 iscsi_ctask_mtask_cleanup(ctask);
1085 if (rc || sc->SCp.phase != session->age || 1098 if (rc || sc->SCp.phase != session->age ||
1086 session->state != ISCSI_STATE_LOGGED_IN) 1099 session->state != ISCSI_STATE_LOGGED_IN)
1087 goto failed; 1100 goto failed;
1101 iscsi_ctask_mtask_cleanup(ctask);
1088 1102
1089 /* ctask completed before tmf abort response */ 1103 switch (conn->tmabort_state) {
1090 if (!ctask->sc) { 1104 case TMABORT_SUCCESS:
1091 debug_scsi("sc completed while abort in progress\n"); 1105 goto success_cleanup;
1092 goto success; 1106 case TMABORT_NOT_FOUND:
1093 } 1107 if (!ctask->sc) {
1094 1108 /* ctask completed before tmf abort response */
1095 if (conn->tmabort_state != TMABORT_SUCCESS) { 1109 spin_unlock_bh(&session->lock);
1110 debug_scsi("sc completed while abort in progress\n");
1111 goto success_rel_mutex;
1112 }
1113 /* fall through */
1114 default:
1115 /* timedout or failed */
1096 spin_unlock_bh(&session->lock); 1116 spin_unlock_bh(&session->lock);
1097 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); 1117 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
1098 spin_lock_bh(&session->lock); 1118 spin_lock_bh(&session->lock);
1099 goto failed; 1119 goto failed;
1100 } 1120 }
1101 1121
1102success: 1122success_cleanup:
1103 debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); 1123 debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
1104 spin_unlock_bh(&session->lock); 1124 spin_unlock_bh(&session->lock);
1105 1125
@@ -1113,6 +1133,7 @@ success:
1113 spin_unlock(&session->lock); 1133 spin_unlock(&session->lock);
1114 write_unlock_bh(conn->recv_lock); 1134 write_unlock_bh(conn->recv_lock);
1115 1135
1136success_rel_mutex:
1116 mutex_unlock(&conn->xmitmutex); 1137 mutex_unlock(&conn->xmitmutex);
1117 return SUCCESS; 1138 return SUCCESS;
1118 1139
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index e71d6e96eca6..3f69f7e58f89 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -60,6 +60,7 @@ struct iscsi_nopin;
60#define TMABORT_SUCCESS 0x1 60#define TMABORT_SUCCESS 0x1
61#define TMABORT_FAILED 0x2 61#define TMABORT_FAILED 0x2
62#define TMABORT_TIMEDOUT 0x3 62#define TMABORT_TIMEDOUT 0x3
63#define TMABORT_NOT_FOUND 0x4
63 64
64/* Connection suspend "bit" */ 65/* Connection suspend "bit" */
65#define ISCSI_SUSPEND_BIT 1 66#define ISCSI_SUSPEND_BIT 1