diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2007-07-26 13:46:48 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-07-27 09:12:05 -0400 |
commit | e07264071f7f2b02a2973cb28d9fdf5eb8866cc1 (patch) | |
tree | 25ca60eeb25dbb519428d3e4bbea77d978e5a4a1 | |
parent | 7974392c0b0d4e7a2a17ca3597d51a29b9841aa5 (diff) |
[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>
-rw-r--r-- | drivers/scsi/libiscsi.c | 46 | ||||
-rw-r--r-- | include/scsi/libiscsi.h | 3 |
2 files changed, 28 insertions, 21 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 271a2d671b89..5606d1e62978 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -596,9 +596,16 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn, | |||
596 | nop->cmdsn = cpu_to_be32(session->cmdsn); | 596 | nop->cmdsn = cpu_to_be32(session->cmdsn); |
597 | if (hdr->itt != RESERVED_ITT) { | 597 | if (hdr->itt != RESERVED_ITT) { |
598 | hdr->itt = build_itt(mtask->itt, conn->id, session->age); | 598 | hdr->itt = build_itt(mtask->itt, conn->id, session->age); |
599 | /* | ||
600 | * TODO: We always use immediate, so we never hit this. | ||
601 | * If we start to send tmfs or nops as non-immediate then | ||
602 | * we should start checking the cmdsn numbers for mgmt tasks. | ||
603 | */ | ||
599 | if (conn->c_stage == ISCSI_CONN_STARTED && | 604 | if (conn->c_stage == ISCSI_CONN_STARTED && |
600 | !(hdr->opcode & ISCSI_OP_IMMEDIATE)) | 605 | !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { |
606 | session->queued_cmdsn++; | ||
601 | session->cmdsn++; | 607 | session->cmdsn++; |
608 | } | ||
602 | } | 609 | } |
603 | 610 | ||
604 | if (session->tt->init_mgmt_task) | 611 | if (session->tt->init_mgmt_task) |
@@ -641,9 +648,11 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) | |||
641 | /* | 648 | /* |
642 | * Check for iSCSI window and take care of CmdSN wrap-around | 649 | * Check for iSCSI window and take care of CmdSN wrap-around |
643 | */ | 650 | */ |
644 | if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) { | 651 | if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) { |
645 | debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n", | 652 | debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u " |
646 | session->max_cmdsn, session->cmdsn); | 653 | "CmdSN %u/%u\n", session->exp_cmdsn, |
654 | session->max_cmdsn, session->cmdsn, | ||
655 | session->queued_cmdsn); | ||
647 | return -ENOSPC; | 656 | return -ENOSPC; |
648 | } | 657 | } |
649 | return 0; | 658 | return 0; |
@@ -722,11 +731,6 @@ check_mgmt: | |||
722 | 731 | ||
723 | /* process command queue */ | 732 | /* process command queue */ |
724 | while (!list_empty(&conn->xmitqueue)) { | 733 | while (!list_empty(&conn->xmitqueue)) { |
725 | rc = iscsi_check_cmdsn_window_closed(conn); | ||
726 | if (rc) { | ||
727 | spin_unlock_bh(&conn->session->lock); | ||
728 | return rc; | ||
729 | } | ||
730 | /* | 734 | /* |
731 | * iscsi tcp may readd the task to the xmitqueue to send | 735 | * iscsi tcp may readd the task to the xmitqueue to send |
732 | * write data | 736 | * write data |
@@ -834,12 +838,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
834 | goto fault; | 838 | goto fault; |
835 | } | 839 | } |
836 | 840 | ||
837 | /* | ||
838 | * We check this here and in data xmit, because if we get to the point | ||
839 | * that this check is hitting the window then we have enough IO in | ||
840 | * flight and enough IO waiting to be transmitted it is better | ||
841 | * to let the scsi/block layer queue up. | ||
842 | */ | ||
843 | if (iscsi_check_cmdsn_window_closed(conn)) { | 841 | if (iscsi_check_cmdsn_window_closed(conn)) { |
844 | reason = FAILURE_WINDOW_CLOSED; | 842 | reason = FAILURE_WINDOW_CLOSED; |
845 | goto reject; | 843 | goto reject; |
@@ -850,6 +848,8 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
850 | reason = FAILURE_OOM; | 848 | reason = FAILURE_OOM; |
851 | goto reject; | 849 | goto reject; |
852 | } | 850 | } |
851 | session->queued_cmdsn++; | ||
852 | |||
853 | sc->SCp.phase = session->age; | 853 | sc->SCp.phase = session->age; |
854 | sc->SCp.ptr = (char *)ctask; | 854 | sc->SCp.ptr = (char *)ctask; |
855 | 855 | ||
@@ -1140,7 +1140,13 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1140 | if (!sc) | 1140 | if (!sc) |
1141 | return; | 1141 | return; |
1142 | 1142 | ||
1143 | if (ctask->state != ISCSI_TASK_PENDING) | 1143 | if (ctask->state == ISCSI_TASK_PENDING) |
1144 | /* | ||
1145 | * cmd never made it to the xmit thread, so we should not count | ||
1146 | * the cmd in the sequencing | ||
1147 | */ | ||
1148 | conn->session->queued_cmdsn--; | ||
1149 | else | ||
1144 | conn->session->tt->cleanup_cmd_task(conn, ctask); | 1150 | conn->session->tt->cleanup_cmd_task(conn, ctask); |
1145 | iscsi_ctask_mtask_cleanup(ctask); | 1151 | iscsi_ctask_mtask_cleanup(ctask); |
1146 | 1152 | ||
@@ -1392,7 +1398,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, | |||
1392 | session->state = ISCSI_STATE_FREE; | 1398 | session->state = ISCSI_STATE_FREE; |
1393 | session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; | 1399 | session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; |
1394 | session->cmds_max = cmds_max; | 1400 | session->cmds_max = cmds_max; |
1395 | session->cmdsn = initial_cmdsn; | 1401 | session->queued_cmdsn = session->cmdsn = initial_cmdsn; |
1396 | session->exp_cmdsn = initial_cmdsn + 1; | 1402 | session->exp_cmdsn = initial_cmdsn + 1; |
1397 | session->max_cmdsn = initial_cmdsn + 1; | 1403 | session->max_cmdsn = initial_cmdsn + 1; |
1398 | session->max_r2t = 1; | 1404 | session->max_r2t = 1; |
@@ -1616,11 +1622,8 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) | |||
1616 | kfree(conn->persistent_address); | 1622 | kfree(conn->persistent_address); |
1617 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, | 1623 | __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, |
1618 | sizeof(void*)); | 1624 | sizeof(void*)); |
1619 | if (session->leadconn == conn) { | 1625 | if (session->leadconn == conn) |
1620 | session->leadconn = NULL; | 1626 | session->leadconn = NULL; |
1621 | /* no connections exits.. reset sequencing */ | ||
1622 | session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; | ||
1623 | } | ||
1624 | spin_unlock_bh(&session->lock); | 1627 | spin_unlock_bh(&session->lock); |
1625 | 1628 | ||
1626 | kfifo_free(conn->mgmtqueue); | 1629 | kfifo_free(conn->mgmtqueue); |
@@ -1650,6 +1653,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) | |||
1650 | spin_lock_bh(&session->lock); | 1653 | spin_lock_bh(&session->lock); |
1651 | conn->c_stage = ISCSI_CONN_STARTED; | 1654 | conn->c_stage = ISCSI_CONN_STARTED; |
1652 | session->state = ISCSI_STATE_LOGGED_IN; | 1655 | session->state = ISCSI_STATE_LOGGED_IN; |
1656 | session->queued_cmdsn = session->cmdsn; | ||
1653 | 1657 | ||
1654 | switch(conn->stop_stage) { | 1658 | switch(conn->stop_stage) { |
1655 | case STOP_CONN_RECOVER: | 1659 | case STOP_CONN_RECOVER: |
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 3f631b08a1ab..007d442412e2 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h | |||
@@ -210,6 +210,9 @@ struct iscsi_session { | |||
210 | uint32_t exp_cmdsn; | 210 | uint32_t exp_cmdsn; |
211 | uint32_t max_cmdsn; | 211 | uint32_t max_cmdsn; |
212 | 212 | ||
213 | /* This tracks the reqs queued into the initiator */ | ||
214 | uint32_t queued_cmdsn; | ||
215 | |||
213 | /* configuration */ | 216 | /* configuration */ |
214 | int initial_r2t_en; | 217 | int initial_r2t_en; |
215 | unsigned max_r2t; | 218 | unsigned max_r2t; |