mirror of https://gitee.com/openkylin/linux.git
[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: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
7974392c0b
commit
e07264071f
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue