Commit e0726407 authored by Mike Christie's avatar Mike Christie Committed by James Bottomley

[SCSI] libiscsi: fix cmd seqeunce number checking

We should not be checking the cmd windown for just handling r2t responses.
And if the window closes in on us, always have scsi-ml requeue the command
from our queuecommand function.
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 7974392c
...@@ -596,10 +596,17 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn, ...@@ -596,10 +596,17 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn,
nop->cmdsn = cpu_to_be32(session->cmdsn); nop->cmdsn = cpu_to_be32(session->cmdsn);
if (hdr->itt != RESERVED_ITT) { if (hdr->itt != RESERVED_ITT) {
hdr->itt = build_itt(mtask->itt, conn->id, session->age); hdr->itt = build_itt(mtask->itt, conn->id, session->age);
/*
* TODO: We always use immediate, so we never hit this.
* If we start to send tmfs or nops as non-immediate then
* we should start checking the cmdsn numbers for mgmt tasks.
*/
if (conn->c_stage == ISCSI_CONN_STARTED && if (conn->c_stage == ISCSI_CONN_STARTED &&
!(hdr->opcode & ISCSI_OP_IMMEDIATE)) !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
session->queued_cmdsn++;
session->cmdsn++; session->cmdsn++;
} }
}
if (session->tt->init_mgmt_task) if (session->tt->init_mgmt_task)
session->tt->init_mgmt_task(conn, mtask); session->tt->init_mgmt_task(conn, mtask);
...@@ -641,9 +648,11 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) ...@@ -641,9 +648,11 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
/* /*
* Check for iSCSI window and take care of CmdSN wrap-around * Check for iSCSI window and take care of CmdSN wrap-around
*/ */
if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) { if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) {
debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n", debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u "
session->max_cmdsn, session->cmdsn); "CmdSN %u/%u\n", session->exp_cmdsn,
session->max_cmdsn, session->cmdsn,
session->queued_cmdsn);
return -ENOSPC; return -ENOSPC;
} }
return 0; return 0;
...@@ -722,11 +731,6 @@ check_mgmt: ...@@ -722,11 +731,6 @@ check_mgmt:
/* process command queue */ /* process command queue */
while (!list_empty(&conn->xmitqueue)) { while (!list_empty(&conn->xmitqueue)) {
rc = iscsi_check_cmdsn_window_closed(conn);
if (rc) {
spin_unlock_bh(&conn->session->lock);
return rc;
}
/* /*
* iscsi tcp may readd the task to the xmitqueue to send * iscsi tcp may readd the task to the xmitqueue to send
* write data * write data
...@@ -834,12 +838,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) ...@@ -834,12 +838,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
goto fault; goto fault;
} }
/*
* We check this here and in data xmit, because if we get to the point
* that this check is hitting the window then we have enough IO in
* flight and enough IO waiting to be transmitted it is better
* to let the scsi/block layer queue up.
*/
if (iscsi_check_cmdsn_window_closed(conn)) { if (iscsi_check_cmdsn_window_closed(conn)) {
reason = FAILURE_WINDOW_CLOSED; reason = FAILURE_WINDOW_CLOSED;
goto reject; goto reject;
...@@ -850,6 +848,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) ...@@ -850,6 +848,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
reason = FAILURE_OOM; reason = FAILURE_OOM;
goto reject; goto reject;
} }
session->queued_cmdsn++;
sc->SCp.phase = session->age; sc->SCp.phase = session->age;
sc->SCp.ptr = (char *)ctask; sc->SCp.ptr = (char *)ctask;
...@@ -1140,7 +1140,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, ...@@ -1140,7 +1140,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
if (!sc) if (!sc)
return; return;
if (ctask->state != ISCSI_TASK_PENDING) if (ctask->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--;
else
conn->session->tt->cleanup_cmd_task(conn, ctask); conn->session->tt->cleanup_cmd_task(conn, ctask);
iscsi_ctask_mtask_cleanup(ctask); iscsi_ctask_mtask_cleanup(ctask);
...@@ -1392,7 +1398,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, ...@@ -1392,7 +1398,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
session->state = ISCSI_STATE_FREE; session->state = ISCSI_STATE_FREE;
session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
session->cmds_max = cmds_max; session->cmds_max = cmds_max;
session->cmdsn = initial_cmdsn; session->queued_cmdsn = session->cmdsn = initial_cmdsn;
session->exp_cmdsn = initial_cmdsn + 1; session->exp_cmdsn = initial_cmdsn + 1;
session->max_cmdsn = initial_cmdsn + 1; session->max_cmdsn = initial_cmdsn + 1;
session->max_r2t = 1; session->max_r2t = 1;
...@@ -1616,11 +1622,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) ...@@ -1616,11 +1622,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
kfree(conn->persistent_address); kfree(conn->persistent_address);
__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
sizeof(void*)); sizeof(void*));
if (session->leadconn == conn) { if (session->leadconn == conn)
session->leadconn = NULL; session->leadconn = NULL;
/* no connections exits.. reset sequencing */
session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
}
spin_unlock_bh(&session->lock); spin_unlock_bh(&session->lock);
kfifo_free(conn->mgmtqueue); kfifo_free(conn->mgmtqueue);
...@@ -1650,6 +1653,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) ...@@ -1650,6 +1653,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
spin_lock_bh(&session->lock); spin_lock_bh(&session->lock);
conn->c_stage = ISCSI_CONN_STARTED; conn->c_stage = ISCSI_CONN_STARTED;
session->state = ISCSI_STATE_LOGGED_IN; session->state = ISCSI_STATE_LOGGED_IN;
session->queued_cmdsn = session->cmdsn;
switch(conn->stop_stage) { switch(conn->stop_stage) {
case STOP_CONN_RECOVER: case STOP_CONN_RECOVER:
......
...@@ -210,6 +210,9 @@ struct iscsi_session { ...@@ -210,6 +210,9 @@ struct iscsi_session {
uint32_t exp_cmdsn; uint32_t exp_cmdsn;
uint32_t max_cmdsn; uint32_t max_cmdsn;
/* This tracks the reqs queued into the initiator */
uint32_t queued_cmdsn;
/* configuration */ /* configuration */
int initial_r2t_en; int initial_r2t_en;
unsigned max_r2t; unsigned max_r2t;
......
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