Commit 7ea8b828 authored by Mike Christie's avatar Mike Christie Committed by James Bottomley

[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: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 275fd7d1
...@@ -276,6 +276,25 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, ...@@ -276,6 +276,25 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
return rc; return rc;
} }
static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
{
struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
conn->tmfrsp_pdus_cnt++;
if (conn->tmabort_state != TMABORT_INITIAL)
return;
if (tmf->response == ISCSI_TMF_RSP_COMPLETE)
conn->tmabort_state = TMABORT_SUCCESS;
else if (tmf->response == ISCSI_TMF_RSP_NO_TASK)
conn->tmabort_state = TMABORT_NOT_FOUND;
else
conn->tmabort_state = TMABORT_FAILED;
wake_up(&conn->ehwait);
}
/** /**
* __iscsi_complete_pdu - complete pdu * __iscsi_complete_pdu - complete pdu
* @conn: iscsi conn * @conn: iscsi conn
...@@ -361,16 +380,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, ...@@ -361,16 +380,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
break; break;
} }
conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; iscsi_tmf_rsp(conn, hdr);
conn->tmfrsp_pdus_cnt++;
if (conn->tmabort_state == TMABORT_INITIAL) {
conn->tmabort_state =
((struct iscsi_tm_rsp *)hdr)->
response == ISCSI_TMF_RSP_COMPLETE ?
TMABORT_SUCCESS:TMABORT_FAILED;
/* unblock eh_abort() */
wake_up(&conn->ehwait);
}
break; break;
case ISCSI_OP_NOOP_IN: case ISCSI_OP_NOOP_IN:
if (hdr->ttt != ISCSI_RESERVED_TAG) { if (hdr->ttt != ISCSI_RESERVED_TAG) {
...@@ -1029,12 +1039,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, ...@@ -1029,12 +1039,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
{ {
struct scsi_cmnd *sc; struct scsi_cmnd *sc;
conn->session->tt->cleanup_cmd_task(conn, ctask);
iscsi_ctask_mtask_cleanup(ctask);
sc = ctask->sc; sc = ctask->sc;
if (!sc) if (!sc)
return; return;
conn->session->tt->cleanup_cmd_task(conn, ctask);
iscsi_ctask_mtask_cleanup(ctask);
sc->result = err; sc->result = err;
sc->resid = sc->request_bufflen; sc->resid = sc->request_bufflen;
iscsi_complete_command(conn->session, ctask); iscsi_complete_command(conn->session, ctask);
...@@ -1062,8 +1073,11 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) ...@@ -1062,8 +1073,11 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
goto failed; goto failed;
/* ctask completed before time out */ /* ctask completed before time out */
if (!ctask->sc) if (!ctask->sc) {
goto success; spin_unlock_bh(&session->lock);
debug_scsi("sc completed while abort in progress\n");
goto success_rel_mutex;
}
/* what should we do here ? */ /* what should we do here ? */
if (conn->ctask == ctask) { if (conn->ctask == ctask) {
...@@ -1073,7 +1087,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) ...@@ -1073,7 +1087,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
} }
if (ctask->state == ISCSI_TASK_PENDING) if (ctask->state == ISCSI_TASK_PENDING)
goto success; goto success_cleanup;
conn->tmabort_state = TMABORT_INITIAL; conn->tmabort_state = TMABORT_INITIAL;
...@@ -1081,25 +1095,31 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) ...@@ -1081,25 +1095,31 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
rc = iscsi_exec_abort_task(sc, ctask); rc = iscsi_exec_abort_task(sc, ctask);
spin_lock_bh(&session->lock); spin_lock_bh(&session->lock);
iscsi_ctask_mtask_cleanup(ctask);
if (rc || sc->SCp.phase != session->age || if (rc || sc->SCp.phase != session->age ||
session->state != ISCSI_STATE_LOGGED_IN) session->state != ISCSI_STATE_LOGGED_IN)
goto failed; goto failed;
iscsi_ctask_mtask_cleanup(ctask);
/* ctask completed before tmf abort response */ switch (conn->tmabort_state) {
if (!ctask->sc) { case TMABORT_SUCCESS:
debug_scsi("sc completed while abort in progress\n"); goto success_cleanup;
goto success; case TMABORT_NOT_FOUND:
} if (!ctask->sc) {
/* ctask completed before tmf abort response */
if (conn->tmabort_state != TMABORT_SUCCESS) { spin_unlock_bh(&session->lock);
debug_scsi("sc completed while abort in progress\n");
goto success_rel_mutex;
}
/* fall through */
default:
/* timedout or failed */
spin_unlock_bh(&session->lock); spin_unlock_bh(&session->lock);
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
spin_lock_bh(&session->lock); spin_lock_bh(&session->lock);
goto failed; goto failed;
} }
success: success_cleanup:
debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
spin_unlock_bh(&session->lock); spin_unlock_bh(&session->lock);
...@@ -1113,6 +1133,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) ...@@ -1113,6 +1133,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
spin_unlock(&session->lock); spin_unlock(&session->lock);
write_unlock_bh(conn->recv_lock); write_unlock_bh(conn->recv_lock);
success_rel_mutex:
mutex_unlock(&conn->xmitmutex); mutex_unlock(&conn->xmitmutex);
return SUCCESS; return SUCCESS;
......
...@@ -60,6 +60,7 @@ struct iscsi_nopin; ...@@ -60,6 +60,7 @@ struct iscsi_nopin;
#define TMABORT_SUCCESS 0x1 #define TMABORT_SUCCESS 0x1
#define TMABORT_FAILED 0x2 #define TMABORT_FAILED 0x2
#define TMABORT_TIMEDOUT 0x3 #define TMABORT_TIMEDOUT 0x3
#define TMABORT_NOT_FOUND 0x4
/* Connection suspend "bit" */ /* Connection suspend "bit" */
#define ISCSI_SUSPEND_BIT 1 #define ISCSI_SUSPEND_BIT 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment