diff options
-rw-r--r-- | drivers/scsi/libiscsi.c | 71 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 1 |
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 | ||
279 | static 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 | ||
1102 | success: | 1122 | success_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 | ||
1136 | success_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 |