|
@@ -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 = ISCSI_TASK_COMPLETED;
|
|
|
|
|
|
+ task->state = state;
|
|
|
|
|
|
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)
|
|
{
|
|
{
|
|
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)
|
|
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)
|
|
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 @@ out:
|
|
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,
|
|
"[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,
|
|
}
|
|
}
|
|
|
|
|
|
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,
|
|
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 @@ out:
|
|
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 @@ check_mgmt:
|
|
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 @@ check_mgmt:
|
|
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 *))
|
|
|
|
|
|
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 @@ reject:
|
|
|
|
|
|
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,
|
|
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)
|
|
}
|
|
}
|
|
|
|
|
|
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)
|
|
* 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
|
|
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)
|
|
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,
|
|
* 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);
|
|
|
|
- else
|
|
|
|
- fail_scsi_tasks(conn, -1, DID_ERROR);
|
|
|
|
|
|
+ fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
|
|
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);
|