提交 b3cd5050 编写于 作者: M Mike Christie 提交者: James Bottomley

[SCSI] libiscsi: add task aborted state

If a task did not complete normally due to a TMF, libiscsi will
now complete the task with the state ISCSI_TASK_ABRT_TMF. Drivers
like bnx2i that need to free resources if a command did not complete normally
can then check the task state. If a driver does not need to send
a special command if we have dropped the session then they can check
for ISCSI_TASK_ABRT_SESS_RECOV.
Signed-off-by: NMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: NJames Bottomley <James.Bottomley@HansenPartnership.com>
上级 1336aed1
...@@ -257,11 +257,8 @@ static void iscsi_iser_cleanup_task(struct iscsi_task *task) ...@@ -257,11 +257,8 @@ static void iscsi_iser_cleanup_task(struct iscsi_task *task)
{ {
struct iscsi_iser_task *iser_task = task->dd_data; struct iscsi_iser_task *iser_task = task->dd_data;
/* /* mgmt tasks do not need special cleanup */
* mgmt tasks do not need special cleanup and we do not if (!task->sc)
* allocate anything in the init task callout
*/
if (!task->sc || task->state == ISCSI_TASK_PENDING)
return; return;
if (iser_task->status == ISER_TASK_STATUS_STARTED) { if (iser_task->status == ISER_TASK_STATUS_STARTED) {
......
...@@ -443,18 +443,20 @@ EXPORT_SYMBOL_GPL(iscsi_put_task); ...@@ -443,18 +443,20 @@ EXPORT_SYMBOL_GPL(iscsi_put_task);
/** /**
* iscsi_complete_task - finish a task * iscsi_complete_task - finish a task
* @task: iscsi cmd task * @task: iscsi cmd task
* @state: state to complete task with
* *
* Must be called with session lock. * Must be called with session lock.
*/ */
static void iscsi_complete_task(struct iscsi_task *task) static void iscsi_complete_task(struct iscsi_task *task, int state)
{ {
struct iscsi_conn *conn = task->conn; struct iscsi_conn *conn = task->conn;
if (task->state == ISCSI_TASK_COMPLETED) if (task->state == ISCSI_TASK_COMPLETED ||
task->state == ISCSI_TASK_ABRT_TMF ||
task->state == ISCSI_TASK_ABRT_SESS_RECOV)
return; return;
WARN_ON_ONCE(task->state == ISCSI_TASK_FREE); WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
task->state = state;
task->state = ISCSI_TASK_COMPLETED;
if (!list_empty(&task->running)) if (!list_empty(&task->running))
list_del_init(&task->running); list_del_init(&task->running);
...@@ -478,6 +480,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err) ...@@ -478,6 +480,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
{ {
struct iscsi_conn *conn = task->conn; struct iscsi_conn *conn = task->conn;
struct scsi_cmnd *sc; struct scsi_cmnd *sc;
int state;
/* /*
* if a command completes and we get a successful tmf response * if a command completes and we get a successful tmf response
...@@ -488,14 +491,20 @@ static void fail_scsi_task(struct iscsi_task *task, int err) ...@@ -488,14 +491,20 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
if (!sc) if (!sc)
return; return;
if (task->state == ISCSI_TASK_PENDING) if (task->state == ISCSI_TASK_PENDING) {
/* /*
* cmd never made it to the xmit thread, so we should not count * cmd never made it to the xmit thread, so we should not count
* the cmd in the sequencing * the cmd in the sequencing
*/ */
conn->session->queued_cmdsn--; conn->session->queued_cmdsn--;
/* it was never sent so just complete like normal */
state = ISCSI_TASK_COMPLETED;
} else if (err == DID_TRANSPORT_DISRUPTED)
state = ISCSI_TASK_ABRT_SESS_RECOV;
else
state = ISCSI_TASK_ABRT_TMF;
sc->result = err; sc->result = err << 16;
if (!scsi_bidi_cmnd(sc)) if (!scsi_bidi_cmnd(sc))
scsi_set_resid(sc, scsi_bufflen(sc)); scsi_set_resid(sc, scsi_bufflen(sc));
else { else {
...@@ -503,7 +512,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err) ...@@ -503,7 +512,7 @@ static void fail_scsi_task(struct iscsi_task *task, int err)
scsi_in(sc)->resid = scsi_in(sc)->length; scsi_in(sc)->resid = scsi_in(sc)->length;
} }
iscsi_complete_task(task); iscsi_complete_task(task, state);
} }
static int iscsi_prep_mgmt_task(struct iscsi_conn *conn, static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
...@@ -731,7 +740,7 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, ...@@ -731,7 +740,7 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n", ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n",
sc, sc->result, task->itt); sc, sc->result, task->itt);
conn->scsirsp_pdus_cnt++; conn->scsirsp_pdus_cnt++;
iscsi_complete_task(task); iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
} }
/** /**
...@@ -769,7 +778,7 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, ...@@ -769,7 +778,7 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
"[sc %p res %d itt 0x%x]\n", "[sc %p res %d itt 0x%x]\n",
sc, sc->result, task->itt); sc, sc->result, task->itt);
conn->scsirsp_pdus_cnt++; conn->scsirsp_pdus_cnt++;
iscsi_complete_task(task); iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
} }
static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
...@@ -990,7 +999,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, ...@@ -990,7 +999,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
} }
iscsi_tmf_rsp(conn, hdr); iscsi_tmf_rsp(conn, hdr);
iscsi_complete_task(task); iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
break; break;
case ISCSI_OP_NOOP_IN: case ISCSI_OP_NOOP_IN:
iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
...@@ -1008,7 +1017,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, ...@@ -1008,7 +1017,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
goto recv_pdu; goto recv_pdu;
mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
iscsi_complete_task(task); iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
break; break;
default: default:
rc = ISCSI_ERR_BAD_OPCODE; rc = ISCSI_ERR_BAD_OPCODE;
...@@ -1020,7 +1029,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, ...@@ -1020,7 +1029,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
recv_pdu: recv_pdu:
if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
rc = ISCSI_ERR_CONN_FAILED; rc = ISCSI_ERR_CONN_FAILED;
iscsi_complete_task(task); iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
...@@ -1262,7 +1271,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) ...@@ -1262,7 +1271,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
struct iscsi_task, running); struct iscsi_task, running);
list_del_init(&conn->task->running); list_del_init(&conn->task->running);
if (conn->session->state == ISCSI_STATE_LOGGING_OUT) { if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
fail_scsi_task(conn->task, DID_IMM_RETRY << 16); fail_scsi_task(conn->task, DID_IMM_RETRY);
continue; continue;
} }
rc = iscsi_prep_scsi_cmd_pdu(conn->task); rc = iscsi_prep_scsi_cmd_pdu(conn->task);
...@@ -1273,7 +1282,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) ...@@ -1273,7 +1282,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
conn->task = NULL; conn->task = NULL;
goto again; goto again;
} else } else
fail_scsi_task(conn->task, DID_ABORT << 16); fail_scsi_task(conn->task, DID_ABORT);
continue; continue;
} }
rc = iscsi_xmit_task(conn); rc = iscsi_xmit_task(conn);
...@@ -1469,7 +1478,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) ...@@ -1469,7 +1478,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
prepd_reject: prepd_reject:
sc->scsi_done = NULL; sc->scsi_done = NULL;
iscsi_complete_task(task); iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
reject: reject:
spin_unlock(&session->lock); spin_unlock(&session->lock);
ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n", ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
...@@ -1479,7 +1488,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) ...@@ -1479,7 +1488,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
prepd_fault: prepd_fault:
sc->scsi_done = NULL; sc->scsi_done = NULL;
iscsi_complete_task(task); iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
fault: fault:
spin_unlock(&session->lock); spin_unlock(&session->lock);
ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n", ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
...@@ -1665,7 +1674,7 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun, ...@@ -1665,7 +1674,7 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun,
ISCSI_DBG_SESSION(conn->session, ISCSI_DBG_SESSION(conn->session,
"failing sc %p itt 0x%x state %d\n", "failing sc %p itt 0x%x state %d\n",
task->sc, task->itt, task->state); task->sc, task->itt, task->state);
fail_scsi_task(task, error << 16); fail_scsi_task(task, error);
} }
} }
...@@ -1868,7 +1877,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) ...@@ -1868,7 +1877,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
} }
if (task->state == ISCSI_TASK_PENDING) { if (task->state == ISCSI_TASK_PENDING) {
fail_scsi_task(task, DID_ABORT << 16); fail_scsi_task(task, DID_ABORT);
goto success; goto success;
} }
...@@ -1899,7 +1908,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) ...@@ -1899,7 +1908,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
* then sent more data for the cmd. * then sent more data for the cmd.
*/ */
spin_lock(&session->lock); spin_lock(&session->lock);
fail_scsi_task(task, DID_ABORT << 16); fail_scsi_task(task, DID_ABORT);
conn->tmf_state = TMF_INITIAL; conn->tmf_state = TMF_INITIAL;
spin_unlock(&session->lock); spin_unlock(&session->lock);
iscsi_start_tx(conn); iscsi_start_tx(conn);
...@@ -2572,7 +2581,7 @@ static void ...@@ -2572,7 +2581,7 @@ static void
fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
{ {
struct iscsi_task *task; struct iscsi_task *task;
int i; int i, state;
for (i = 0; i < conn->session->cmds_max; i++) { for (i = 0; i < conn->session->cmds_max; i++) {
task = conn->session->cmds[i]; task = conn->session->cmds[i];
...@@ -2585,7 +2594,11 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) ...@@ -2585,7 +2594,11 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
ISCSI_DBG_SESSION(conn->session, ISCSI_DBG_SESSION(conn->session,
"failing mgmt itt 0x%x state %d\n", "failing mgmt itt 0x%x state %d\n",
task->itt, task->state); task->itt, task->state);
iscsi_complete_task(task); state = ISCSI_TASK_ABRT_SESS_RECOV;
if (task->state == ISCSI_TASK_PENDING)
state = ISCSI_TASK_COMPLETED;
iscsi_complete_task(task, state);
} }
} }
...@@ -2642,10 +2655,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, ...@@ -2642,10 +2655,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
* flush queues. * flush queues.
*/ */
spin_lock_bh(&session->lock); spin_lock_bh(&session->lock);
if (flag == STOP_CONN_RECOVER) fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
else
fail_scsi_tasks(conn, -1, DID_ERROR);
fail_mgmt_tasks(session, conn); fail_mgmt_tasks(session, conn);
spin_unlock_bh(&session->lock); spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex); mutex_unlock(&session->eh_mutex);
......
...@@ -440,8 +440,8 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task) ...@@ -440,8 +440,8 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task)
struct iscsi_tcp_task *tcp_task = task->dd_data; struct iscsi_tcp_task *tcp_task = task->dd_data;
struct iscsi_r2t_info *r2t; struct iscsi_r2t_info *r2t;
/* nothing to do for mgmt or pending tasks */ /* nothing to do for mgmt */
if (!task->sc || task->state == ISCSI_TASK_PENDING) if (!task->sc)
return; return;
/* flush task's r2t queues */ /* flush task's r2t queues */
......
...@@ -86,6 +86,8 @@ enum { ...@@ -86,6 +86,8 @@ enum {
ISCSI_TASK_COMPLETED, ISCSI_TASK_COMPLETED,
ISCSI_TASK_PENDING, ISCSI_TASK_PENDING,
ISCSI_TASK_RUNNING, ISCSI_TASK_RUNNING,
ISCSI_TASK_ABRT_TMF, /* aborted due to TMF */
ISCSI_TASK_ABRT_SESS_RECOV, /* aborted due to session recovery */
}; };
struct iscsi_r2t_info { struct iscsi_r2t_info {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册