Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0726407 authored by Mike Christie's avatar Mike Christie Committed by James Bottomley
Browse files

[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: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 7974392c
Loading
Loading
Loading
Loading
+25 −21
Original line number Diff line number Diff line
@@ -596,10 +596,17 @@ 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)
		session->tt->init_mgmt_task(conn, mtask);
@@ -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:
+3 −0
Original line number Diff line number Diff line
@@ -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;