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; |
