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 |
