aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-07-24 16:47:22 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-07-28 12:48:16 -0400
commit7ea8b82847293c2311cf08fc3ed31ab0e452a27e (patch)
treeeab8e9be7cc779cc3c9e48774fcb4b33ebb2c8df /drivers
parent275fd7d129fdd16d1dc0ec6a8d60bd6b72a76e31 (diff)
[SCSI] iscsi bugfixes: fix abort handling
Abort handler fixes. If a connection is dropped and reconnected while an abort is running then we should assume the recovery code will clean up the abort. Not doing so causes a oops. And if a command completes then we get the status for the abort, we do not need to call into the LLD to cleanup the resources. Doing this causes and oops in iser because it ends up freeing some resources twice. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libiscsi.c71
1 files changed, 46 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