Re: [PATCH 23/42] target: Simplify CmdSN sequencing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 2011-05-27 at 12:07 -0700, Andy Grover wrote:
> Turn iscsit_check_received_cmdsn into a similar function that just
> checks cmdsn (and increments it if it's the next expected sn). Add
> a new function iscsit_sequence_cmd that dispositions the cmd based on
> the result.
> 
> Change callsites accordingly and simplify, based on sequence_cmd queuing
> lower-than-expected cmdsns for removal on callee's behalf.
> 
> Reorder logic in handle_logout_cmd() a little.
> 
> Signed-off-by: Andy Grover <agrover@xxxxxxxxxx>
> ---

This does need to be tested, but AFAICT the changes look OK to be merged
now..

Committed as 60ab5356375.

Thanks,

--nab

>  drivers/target/iscsi/iscsi_target.c      |  113 ++++++++-----------------
>  drivers/target/iscsi/iscsi_target_util.c |  136 +++++++++++++-----------------
>  drivers/target/iscsi/iscsi_target_util.h |    2 +-
>  3 files changed, 93 insertions(+), 158 deletions(-)
> 
> diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
> index 2ef6436..b5b6981 100644
> --- a/drivers/target/iscsi/iscsi_target.c
> +++ b/drivers/target/iscsi/iscsi_target.c
> @@ -1211,22 +1211,13 @@ attach_cmd:
>  	 * be acknowledged. (See below)
>  	 */
>  	if (!cmd->immediate_data) {
> -		cmdsn_ret = iscsit_check_received_cmdsn(conn,
> -				cmd, hdr->cmdsn);
> -		if ((cmdsn_ret == CMDSN_NORMAL_OPERATION) ||
> -		    (cmdsn_ret == CMDSN_HIGHER_THAN_EXP))
> -			do {} while (0);
> -		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
> -			cmd->i_state = ISTATE_REMOVE;
> -			iscsit_add_cmd_to_immediate_queue(cmd,
> -					conn, cmd->i_state);
> -			return 0;
> -		} else { /* (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) */
> +		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
> +		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
>  			return iscsit_add_reject_from_cmd(
> -					ISCSI_REASON_PROTOCOL_ERROR,
> -					1, 0, buf, cmd);
> -		}
> +				ISCSI_REASON_PROTOCOL_ERROR,
> +				1, 0, buf, cmd);
>  	}
> +
>  	iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
>  
>  	/*
> @@ -1281,8 +1272,7 @@ after_immediate_data:
>  		 * DataCRC, check against ExpCmdSN/MaxCmdSN if
>  		 * Immediate Bit is not set.
>  		 */
> -		cmdsn_ret = iscsit_check_received_cmdsn(conn,
> -				cmd, hdr->cmdsn);
> +		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
>  		/*
>  		 * Special case for Unsupported SAM WRITE Opcodes
>  		 * and ImmediateData=Yes.
> @@ -1298,20 +1288,11 @@ after_immediate_data:
>  			spin_unlock_bh(&cmd->dataout_timeout_lock);
>  		}
>  
> -		if (cmdsn_ret == CMDSN_NORMAL_OPERATION)
> -			return 0;
> -		else if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)
> -			return 0;
> -		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
> -			cmd->i_state = ISTATE_REMOVE;
> -			iscsit_add_cmd_to_immediate_queue(cmd,
> -					conn, cmd->i_state);
> -			return 0;
> -		} else { /* (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) */
> +		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
>  			return iscsit_add_reject_from_cmd(
> -					ISCSI_REASON_PROTOCOL_ERROR,
> -					1, 0, buf, cmd);
> -		}
> +				ISCSI_REASON_PROTOCOL_ERROR,
> +				1, 0, buf, cmd);
> +
>  	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
>  		/*
>  		 * Immediate Data failed DataCRC and ERL>=1,
> @@ -1835,23 +1816,15 @@ static int iscsit_handle_nop_out(
>  			return 0;
>  		}
>  
> -		cmdsn_ret = iscsit_check_received_cmdsn(conn, cmd, hdr->cmdsn);
> -		if ((cmdsn_ret == CMDSN_NORMAL_OPERATION) ||
> -		    (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)) {
> -			return 0;
> -		} else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
> -			cmd->i_state = ISTATE_REMOVE;
> -			iscsit_add_cmd_to_immediate_queue(cmd, conn,
> -					cmd->i_state);
> +		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
> +		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
>  			ret = 0;
>  			goto ping_out;
> -		} else { /* (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) */
> +		}
> +		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
>  			return iscsit_add_reject_from_cmd(
>  					ISCSI_REASON_PROTOCOL_ERROR,
>  					1, 0, buf, cmd);
> -			ret = -1;
> -			goto ping_out;
> -		}
>  
>  		return 0;
>  	}
> @@ -1901,7 +1874,8 @@ static int iscsit_handle_task_mgt_cmd(
>  	struct iscsi_tmr_req *tmr_req;
>  	struct iscsi_tm *hdr;
>  	u32 payload_length;
> -	int cmdsn_ret, out_of_order_cmdsn = 0, ret;
> +	int out_of_order_cmdsn = 0;
> +	int ret;
>  	u8 function;
>  
>  	hdr			= (struct iscsi_tm *) buf;
> @@ -2024,16 +1998,10 @@ attach:
>  	spin_unlock_bh(&conn->cmd_lock);
>  
>  	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
> -		cmdsn_ret = iscsit_check_received_cmdsn(conn,
> -				cmd, hdr->cmdsn);
> -		if (cmdsn_ret == CMDSN_NORMAL_OPERATION)
> -			do {} while (0);
> -		else if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)
> +		int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
> +		if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)
>  			out_of_order_cmdsn = 1;
>  		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
> -			cmd->i_state = ISTATE_REMOVE;
> -			iscsit_add_cmd_to_immediate_queue(cmd, conn,
> -					cmd->i_state);
>  			return 0;
>  		} else { /* (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) */
>  			return iscsit_add_reject_from_cmd(
> @@ -2209,19 +2177,11 @@ static int iscsit_handle_text_cmd(
>  	iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
>  
>  	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
> -		cmdsn_ret = iscsit_check_received_cmdsn(conn, cmd, hdr->cmdsn);
> -		if ((cmdsn_ret == CMDSN_NORMAL_OPERATION) ||
> -		     (cmdsn_ret == CMDSN_HIGHER_THAN_EXP))
> -			return 0;
> -		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
> -			iscsit_add_cmd_to_immediate_queue(cmd, conn,
> -						ISTATE_REMOVE);
> -			return 0;
> -		} else { /* (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) */
> +		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
> +		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
>  			return iscsit_add_reject_from_cmd(
>  					ISCSI_REASON_PROTOCOL_ERROR,
>  					1, 0, buf, cmd);
> -		}
>  
>  		return 0;
>  	}
> @@ -2406,29 +2366,24 @@ static int iscsit_handle_logout_cmd(
>  		iscsit_ack_from_expstatsn(conn, hdr->exp_statsn);
>  
>  	/*
> -	 * Non-Immediate Logout Commands are executed in CmdSN order..
> +	 * Immediate commands are executed, well, immediately.
> +	 * Non-Immediate Logout Commands are executed in CmdSN order.
>  	 */
> -	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
> -		cmdsn_ret = iscsit_check_received_cmdsn(conn, cmd, hdr->cmdsn);
> -		if ((cmdsn_ret == CMDSN_NORMAL_OPERATION) ||
> -		    (cmdsn_ret == CMDSN_HIGHER_THAN_EXP))
> -			return logout_remove;
> -		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
> -			cmd->i_state = ISTATE_REMOVE;
> -			iscsit_add_cmd_to_immediate_queue(cmd, conn,
> -					cmd->i_state);
> -			return 0;
> -		} else { /* (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) */
> +	if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
> +		int ret = iscsit_execute_cmd(cmd, 0);
> +
> +		if (ret < 0)
> +			return ret;
> +	} else {
> +		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
> +		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
> +			logout_remove = 0;
> +		} else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
>  			return iscsit_add_reject_from_cmd(
> -					ISCSI_REASON_PROTOCOL_ERROR,
> -					1, 0, buf, cmd);
> +				ISCSI_REASON_PROTOCOL_ERROR,
> +				1, 0, buf, cmd);
>  		}
>  	}
> -	/*
> -	 * Immediate Logout Commands are executed, well, Immediately.
> -	 */
> -	if (iscsit_execute_cmd(cmd, 0) < 0)
> -		return -1;
>  
>  	return logout_remove;
>  }
> diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
> index 144f555..612658a 100644
> --- a/drivers/target/iscsi/iscsi_target_util.c
> +++ b/drivers/target/iscsi/iscsi_target_util.c
> @@ -385,100 +385,80 @@ struct iscsi_r2t *iscsit_get_holder_for_r2tsn(
>  	return NULL;
>  }
>  
> -inline int iscsit_check_received_cmdsn(
> -	struct iscsi_conn *conn,
> -	struct iscsi_cmd *cmd,
> -	u32 cmdsn)
> +static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cmdsn)
>  {
>  	int ret;
> +
>  	/*
>  	 * This is the proper method of checking received CmdSN against
>  	 * ExpCmdSN and MaxCmdSN values, as well as accounting for out
>  	 * or order CmdSNs due to multiple connection sessions and/or
>  	 * CRC failures.
>  	 */
> -	spin_lock(&conn->sess->cmdsn_lock);
> -	if (iscsi_sna_gt(cmdsn, conn->sess->max_cmd_sn)) {
> +	if (iscsi_sna_gt(cmdsn, sess->max_cmd_sn)) {
>  		printk(KERN_ERR "Received CmdSN: 0x%08x is greater than"
> -			" MaxCmdSN: 0x%08x, protocol error.\n", cmdsn,
> -				conn->sess->max_cmd_sn);
> -		spin_unlock(&conn->sess->cmdsn_lock);
> -		return CMDSN_ERROR_CANNOT_RECOVER;
> -	}
> -
> -	if (list_empty(&conn->sess->sess_ooo_cmdsn_list)) {
> -		if (cmdsn == conn->sess->exp_cmd_sn) {
> -			conn->sess->exp_cmd_sn++;
> -			TRACE(TRACE_CMDSN, "Received CmdSN matches ExpCmdSN,"
> -				" incremented ExpCmdSN to: 0x%08x\n",
> -					conn->sess->exp_cmd_sn);
> -			ret = iscsit_execute_cmd(cmd, 0);
> -			spin_unlock(&conn->sess->cmdsn_lock);
> -
> -			return (!ret) ? CMDSN_NORMAL_OPERATION :
> -					CMDSN_ERROR_CANNOT_RECOVER;
> -		} else if (iscsi_sna_gt(cmdsn, conn->sess->exp_cmd_sn)) {
> -			TRACE(TRACE_CMDSN, "Received CmdSN: 0x%08x is greater"
> -				" than ExpCmdSN: 0x%08x, not acknowledging.\n",
> -				cmdsn, conn->sess->exp_cmd_sn);
> -			goto ooo_cmdsn;
> -		} else {
> -			printk(KERN_ERR "Received CmdSN: 0x%08x is less than"
> -				" ExpCmdSN: 0x%08x, ignoring.\n", cmdsn,
> -					conn->sess->exp_cmd_sn);
> -			spin_unlock(&conn->sess->cmdsn_lock);
> -			return CMDSN_LOWER_THAN_EXP;
> -		}
> +		       " MaxCmdSN: 0x%08x, protocol error.\n", cmdsn,
> +		       sess->max_cmd_sn);
> +		ret = CMDSN_ERROR_CANNOT_RECOVER;
> +
> +	} else if (cmdsn == sess->exp_cmd_sn) {
> +		sess->exp_cmd_sn++;
> +		TRACE(TRACE_CMDSN, "Received CmdSN matches ExpCmdSN,"
> +		      " incremented ExpCmdSN to: 0x%08x\n",
> +		      sess->exp_cmd_sn);
> +		ret = CMDSN_NORMAL_OPERATION;
> +
> +	} else if (iscsi_sna_gt(cmdsn, sess->exp_cmd_sn)) {
> +		TRACE(TRACE_CMDSN, "Received CmdSN: 0x%08x is greater"
> +		      " than ExpCmdSN: 0x%08x, not acknowledging.\n",
> +		      cmdsn, sess->exp_cmd_sn);
> +		ret = CMDSN_HIGHER_THAN_EXP;
> +
>  	} else {
> -		int counter = 0;
> -		u32 old_expcmdsn = 0;
> -		if (cmdsn == conn->sess->exp_cmd_sn) {
> -			old_expcmdsn = conn->sess->exp_cmd_sn++;
> -			TRACE(TRACE_CMDSN, "Got missing CmdSN: 0x%08x matches"
> -				" ExpCmdSN, incremented ExpCmdSN to 0x%08x.\n",
> -					cmdsn, conn->sess->exp_cmd_sn);
> -
> -			if (iscsit_execute_cmd(cmd, 0) < 0) {
> -				spin_unlock(&conn->sess->cmdsn_lock);
> -				return CMDSN_ERROR_CANNOT_RECOVER;
> -			}
> -		} else if (iscsi_sna_gt(cmdsn, conn->sess->exp_cmd_sn)) {
> -			TRACE(TRACE_CMDSN, "CmdSN: 0x%08x greater than"
> -				" ExpCmdSN: 0x%08x, not acknowledging.\n",
> -				cmdsn, conn->sess->exp_cmd_sn);
> -			goto ooo_cmdsn;
> -		} else {
> -			printk(KERN_ERR "CmdSN: 0x%08x less than ExpCmdSN:"
> -				" 0x%08x, ignoring.\n", cmdsn,
> -				conn->sess->exp_cmd_sn);
> -			spin_unlock(&conn->sess->cmdsn_lock);
> -			return CMDSN_LOWER_THAN_EXP;
> -		}
> +		printk(KERN_ERR "Received CmdSN: 0x%08x is less than"
> +		       " ExpCmdSN: 0x%08x, ignoring.\n", cmdsn,
> +		       sess->exp_cmd_sn);
> +		ret = CMDSN_LOWER_THAN_EXP;
> +	}
>  
> -		counter = iscsit_execute_ooo_cmdsns(conn->sess);
> -		if (counter < 0) {
> -			spin_unlock(&conn->sess->cmdsn_lock);
> -			return CMDSN_ERROR_CANNOT_RECOVER;
> -		}
> +	return ret;
> +}
>  
> -#ifdef CONFIG_ISCSI_TARGET_DEBUG
> -		if (list_empty(&conn->sess->sess_ooo_cmdsn_list)) {
> -			TRACE(TRACE_CMDSN, "Received final missing"
> -			      " CmdSNs: 0x%08x->0x%08x.\n",
> -			      old_expcmdsn, (conn->sess->exp_cmd_sn - 1));
> -		} else {
> -			TRACE(TRACE_CMDSN, "Still missing CmdSN(s),"
> -				" continuing out of order operation.\n");
> -		}
> -#endif
> +/*
> + * Commands may be received out of order if MC/S is in use.
> + * Ensure they are executed in CmdSN order.
> + */
> +int iscsit_sequence_cmd(
> +	struct iscsi_conn *conn,
> +	struct iscsi_cmd *cmd,
> +	u32 cmdsn)
> +{
> +	int ret;
> +	int cmdsn_ret;
>  
> -		spin_unlock(&conn->sess->cmdsn_lock);
> -		return CMDSN_NORMAL_OPERATION;
> -	}
> +	spin_lock(&conn->sess->cmdsn_lock);
>  
> -ooo_cmdsn:
> -	ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, cmdsn);
> +	cmdsn_ret = iscsit_check_received_cmdsn(conn->sess, cmdsn);
> +	switch (cmdsn_ret) {
> +	case CMDSN_NORMAL_OPERATION:
> +		ret = iscsit_execute_cmd(cmd, 0);
> +		if ((ret >= 0) && !list_empty(&conn->sess->sess_ooo_cmdsn_list))
> +			iscsit_execute_ooo_cmdsns(conn->sess);
> +		break;
> +	case CMDSN_HIGHER_THAN_EXP:
> +		ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, cmdsn);
> +		break;
> +	case CMDSN_LOWER_THAN_EXP:
> +		cmd->i_state = ISTATE_REMOVE;
> +		iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state);
> +		ret = cmdsn_ret;
> +		break;
> +	default:
> +		ret = cmdsn_ret;
> +		break;
> +	}
>  	spin_unlock(&conn->sess->cmdsn_lock);
> +
>  	return ret;
>  }
>  
> diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h
> index 5015ceb..885ca6f 100644
> --- a/drivers/target/iscsi/iscsi_target_util.h
> +++ b/drivers/target/iscsi/iscsi_target_util.h
> @@ -53,7 +53,7 @@ extern int iscsit_decide_list_to_build(struct iscsi_cmd *, u32);
>  extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32);
>  extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *);
>  extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
> -extern int iscsit_check_received_cmdsn(struct iscsi_conn *, struct iscsi_cmd *, u32);
> +int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, u32 cmdsn);
>  extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *);
>  extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, u32);
>  extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
> -- 
> 1.7.1
> 

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux