Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Mike Christie and committed by
James Bottomley
e0726407 7974392c

+28 -21
+25 -21
drivers/scsi/libiscsi.c
··· 596 596 nop->cmdsn = cpu_to_be32(session->cmdsn); 597 597 if (hdr->itt != RESERVED_ITT) { 598 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 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 607 session->cmdsn++; 608 + } 602 609 } 603 610 604 611 if (session->tt->init_mgmt_task) ··· 648 641 /* 649 642 * Check for iSCSI window and take care of CmdSN wrap-around 650 643 */ 651 - if (!iscsi_sna_lte(session->cmdsn, session->max_cmdsn)) { 652 - debug_scsi("iSCSI CmdSN closed. MaxCmdSN %u CmdSN %u\n", 653 - session->max_cmdsn, session->cmdsn); 644 + if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) { 645 + debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u " 646 + "CmdSN %u/%u\n", session->exp_cmdsn, 647 + session->max_cmdsn, session->cmdsn, 648 + session->queued_cmdsn); 654 649 return -ENOSPC; 655 650 } 656 651 return 0; ··· 731 722 732 723 /* process command queue */ 733 724 while (!list_empty(&conn->xmitqueue)) { 734 - rc = iscsi_check_cmdsn_window_closed(conn); 735 - if (rc) { 736 - spin_unlock_bh(&conn->session->lock); 737 - return rc; 738 - } 739 725 /* 740 726 * iscsi tcp may readd the task to the xmitqueue to send 741 727 * write data ··· 838 834 goto fault; 839 835 } 840 836 841 - /* 842 - * We check this here and in data xmit, because if we get to the point 843 - * that this check is hitting the window then we have enough IO in 844 - * flight and enough IO waiting to be transmitted it is better 845 - * to let the scsi/block layer queue up. 846 - */ 847 837 if (iscsi_check_cmdsn_window_closed(conn)) { 848 838 reason = FAILURE_WINDOW_CLOSED; 849 839 goto reject; ··· 848 850 reason = FAILURE_OOM; 849 851 goto reject; 850 852 } 853 + session->queued_cmdsn++; 854 + 851 855 sc->SCp.phase = session->age; 852 856 sc->SCp.ptr = (char *)ctask; 853 857 ··· 1140 1140 if (!sc) 1141 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 1150 conn->session->tt->cleanup_cmd_task(conn, ctask); 1145 1151 iscsi_ctask_mtask_cleanup(ctask); 1146 1152 ··· 1398 1392 session->state = ISCSI_STATE_FREE; 1399 1393 session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; 1400 1394 session->cmds_max = cmds_max; 1401 - session->cmdsn = initial_cmdsn; 1395 + session->queued_cmdsn = session->cmdsn = initial_cmdsn; 1402 1396 session->exp_cmdsn = initial_cmdsn + 1; 1403 1397 session->max_cmdsn = initial_cmdsn + 1; 1404 1398 session->max_r2t = 1; ··· 1622 1616 kfree(conn->persistent_address); 1623 1617 __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, 1624 1618 sizeof(void*)); 1625 - if (session->leadconn == conn) { 1619 + if (session->leadconn == conn) 1626 1620 session->leadconn = NULL; 1627 - /* no connections exits.. reset sequencing */ 1628 - session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; 1629 - } 1630 1621 spin_unlock_bh(&session->lock); 1631 1622 1632 1623 kfifo_free(conn->mgmtqueue); ··· 1653 1650 spin_lock_bh(&session->lock); 1654 1651 conn->c_stage = ISCSI_CONN_STARTED; 1655 1652 session->state = ISCSI_STATE_LOGGED_IN; 1653 + session->queued_cmdsn = session->cmdsn; 1656 1654 1657 1655 switch(conn->stop_stage) { 1658 1656 case STOP_CONN_RECOVER:
+3
include/scsi/libiscsi.h
··· 210 210 uint32_t exp_cmdsn; 211 211 uint32_t max_cmdsn; 212 212 213 + /* This tracks the reqs queued into the initiator */ 214 + uint32_t queued_cmdsn; 215 + 213 216 /* configuration */ 214 217 int initial_r2t_en; 215 218 unsigned max_r2t;