Skip to content

Commit

Permalink
[SCSI] libiscsi: fix cmd seqeunce number checking
Browse files Browse the repository at this point in the history
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: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
Mike Christie authored and James Bottomley committed Jul 27, 2007
1 parent 7974392 commit e072640
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 21 deletions.
46 changes: 25 additions & 21 deletions drivers/scsi/libiscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,9 +596,16 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn,
nop->cmdsn = cpu_to_be32(session->cmdsn);
if (hdr->itt != RESERVED_ITT) {
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 &&
!(hdr->opcode & ISCSI_OP_IMMEDIATE))
!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
session->queued_cmdsn++;
session->cmdsn++;
}
}

if (session->tt->init_mgmt_task)
Expand Down Expand Up @@ -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
*/
if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) {
debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n",
session->max_cmdsn, session->cmdsn);
if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) {
debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u "
"CmdSN %u/%u\n", session->exp_cmdsn,
session->max_cmdsn, session->cmdsn,
session->queued_cmdsn);
return -ENOSPC;
}
return 0;
Expand Down Expand Up @@ -722,11 +731,6 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)

/* process command queue */
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
* write data
Expand Down Expand Up @@ -834,12 +838,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
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)) {
reason = FAILURE_WINDOW_CLOSED;
goto reject;
Expand All @@ -850,6 +848,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
reason = FAILURE_OOM;
goto reject;
}
session->queued_cmdsn++;

sc->SCp.phase = session->age;
sc->SCp.ptr = (char *)ctask;

Expand Down Expand Up @@ -1140,7 +1140,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
if (!sc)
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);
iscsi_ctask_mtask_cleanup(ctask);

Expand Down Expand Up @@ -1392,7 +1398,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit,
session->state = ISCSI_STATE_FREE;
session->mgmtpool_max = ISCSI_MGMT_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->max_cmdsn = initial_cmdsn + 1;
session->max_r2t = 1;
Expand Down Expand Up @@ -1616,11 +1622,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
kfree(conn->persistent_address);
__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
sizeof(void*));
if (session->leadconn == conn) {
if (session->leadconn == conn)
session->leadconn = NULL;
/* no connections exits.. reset sequencing */
session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
}
spin_unlock_bh(&session->lock);

kfifo_free(conn->mgmtqueue);
Expand Down Expand Up @@ -1650,6 +1653,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
spin_lock_bh(&session->lock);
conn->c_stage = ISCSI_CONN_STARTED;
session->state = ISCSI_STATE_LOGGED_IN;
session->queued_cmdsn = session->cmdsn;

switch(conn->stop_stage) {
case STOP_CONN_RECOVER:
Expand Down
3 changes: 3 additions & 0 deletions include/scsi/libiscsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ struct iscsi_session {
uint32_t exp_cmdsn;
uint32_t max_cmdsn;

/* This tracks the reqs queued into the initiator */
uint32_t queued_cmdsn;

/* configuration */
int initial_r2t_en;
unsigned max_r2t;
Expand Down

0 comments on commit e072640

Please sign in to comment.