/**
* iscsi_complete_task - finish a task
* @task: iscsi cmd task
+ * @state: state to complete task with
*
* 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;
- 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;
WARN_ON_ONCE(task->state == ISCSI_TASK_FREE);
-
- task->state = ISCSI_TASK_COMPLETED;
+ task->state = state;
if (!list_empty(&task->running))
list_del_init(&task->running);
{
struct iscsi_conn *conn = task->conn;
struct scsi_cmnd *sc;
+ int state;
/*
* if a command completes and we get a successful tmf response
if (!sc)
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
* the cmd in the sequencing
*/
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))
scsi_set_resid(sc, scsi_bufflen(sc));
else {
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,
ISCSI_DBG_SESSION(session, "cmd rsp done [sc %p res %d itt 0x%x]\n",
sc, sc->result, task->itt);
conn->scsirsp_pdus_cnt++;
- iscsi_complete_task(task);
+ iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
}
/**
"[sc %p res %d itt 0x%x]\n",
sc, sc->result, task->itt);
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)
}
iscsi_tmf_rsp(conn, hdr);
- iscsi_complete_task(task);
+ iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
break;
case ISCSI_OP_NOOP_IN:
iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
goto recv_pdu;
mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout);
- iscsi_complete_task(task);
+ iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
break;
default:
rc = ISCSI_ERR_BAD_OPCODE;
recv_pdu:
if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
rc = ISCSI_ERR_CONN_FAILED;
- iscsi_complete_task(task);
+ iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
return rc;
}
EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
struct iscsi_task, running);
list_del_init(&conn->task->running);
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;
}
rc = iscsi_prep_scsi_cmd_pdu(conn->task);
conn->task = NULL;
goto again;
} else
- fail_scsi_task(conn->task, DID_ABORT << 16);
+ fail_scsi_task(conn->task, DID_ABORT);
continue;
}
rc = iscsi_xmit_task(conn);
prepd_reject:
sc->scsi_done = NULL;
- iscsi_complete_task(task);
+ iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
reject:
spin_unlock(&session->lock);
ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
prepd_fault:
sc->scsi_done = NULL;
- iscsi_complete_task(task);
+ iscsi_complete_task(task, ISCSI_TASK_COMPLETED);
fault:
spin_unlock(&session->lock);
ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
ISCSI_DBG_SESSION(conn->session,
"failing sc %p itt 0x%x state %d\n",
task->sc, task->itt, task->state);
- fail_scsi_task(task, error << 16);
+ fail_scsi_task(task, error);
}
}
}
if (task->state == ISCSI_TASK_PENDING) {
- fail_scsi_task(task, DID_ABORT << 16);
+ fail_scsi_task(task, DID_ABORT);
goto success;
}
* then sent more data for the cmd.
*/
spin_lock(&session->lock);
- fail_scsi_task(task, DID_ABORT << 16);
+ fail_scsi_task(task, DID_ABORT);
conn->tmf_state = TMF_INITIAL;
spin_unlock(&session->lock);
iscsi_start_tx(conn);
fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn)
{
struct iscsi_task *task;
- int i;
+ int i, state;
for (i = 0; i < conn->session->cmds_max; i++) {
task = conn->session->cmds[i];
ISCSI_DBG_SESSION(conn->session,
"failing mgmt itt 0x%x state %d\n",
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);
+
}
}
* flush queues.
*/
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);
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);