diff options
| author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-07-03 03:48:24 -0700 | 
|---|---|---|
| committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-07-06 21:59:53 -0700 | 
| commit | ba159914086f06532079fc15141f46ffe7e04a41 (patch) | |
| tree | 9618efce9323083a5812cf831997e0cf560a6b0a /drivers/target | |
| parent | 3df8f68aaf7ebe3d136a22262b41b350b0a1858b (diff) | |
iscsi-target: Fix iscsit_add_reject* usage for iser
This patch changes iscsit_add_reject() + iscsit_add_reject_from_cmd()
usage to not sleep on iscsi_cmd->reject_comp to address a free-after-use
usage bug in v3.10 with iser-target code.
It saves ->reject_reason for use within iscsit_build_reject() so the
correct value for both transport cases.  It also drops the legacy
fail_conn parameter usage throughput iscsi-target code and adds
two iscsit_add_reject_cmd() and iscsit_reject_cmd helper functions,
along with various small cleanups.
(v2: Re-enable target_put_sess_cmd() to be called from
     iscsit_add_reject_from_cmd() for rejects invoked after
     target_get_sess_cmd() has been called)
Cc: Or Gerlitz <ogerlitz@mellanox.com>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: stable@vger.kernel.org  # 3.10+
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
| -rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 255 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target.h | 2 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_core.h | 8 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_erl0.c | 7 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_erl1.c | 20 | ||||
| -rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 1 | 
6 files changed, 120 insertions, 173 deletions
| diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 19a31f9bb7d5..2a25bd3b065c 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -628,25 +628,18 @@ static void __exit iscsi_target_cleanup_module(void)  }  static int iscsit_add_reject( +	struct iscsi_conn *conn,  	u8 reason, -	int fail_conn, -	unsigned char *buf, -	struct iscsi_conn *conn) +	unsigned char *buf)  {  	struct iscsi_cmd *cmd; -	struct iscsi_reject *hdr; -	int ret;  	cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);  	if (!cmd)  		return -1;  	cmd->iscsi_opcode = ISCSI_OP_REJECT; -	if (fail_conn) -		cmd->cmd_flags |= ICF_REJECT_FAIL_CONN; - -	hdr	= (struct iscsi_reject *) cmd->pdu; -	hdr->reason = reason; +	cmd->reject_reason = reason;  	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);  	if (!cmd->buf_ptr) { @@ -662,23 +655,16 @@ static int iscsit_add_reject(  	cmd->i_state = ISTATE_SEND_REJECT;  	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); -	ret = wait_for_completion_interruptible(&cmd->reject_comp); -	if (ret != 0) -		return -1; - -	return (!fail_conn) ? 0 : -1; +	return -1;  } -int iscsit_add_reject_from_cmd( +static int iscsit_add_reject_from_cmd( +	struct iscsi_cmd *cmd,  	u8 reason, -	int fail_conn, -	int add_to_conn, -	unsigned char *buf, -	struct iscsi_cmd *cmd) +	bool add_to_conn, +	unsigned char *buf)  {  	struct iscsi_conn *conn; -	struct iscsi_reject *hdr; -	int ret;  	if (!cmd->conn) {  		pr_err("cmd->conn is NULL for ITT: 0x%08x\n", @@ -688,11 +674,7 @@ int iscsit_add_reject_from_cmd(  	conn = cmd->conn;  	cmd->iscsi_opcode = ISCSI_OP_REJECT; -	if (fail_conn) -		cmd->cmd_flags |= ICF_REJECT_FAIL_CONN; - -	hdr	= (struct iscsi_reject *) cmd->pdu; -	hdr->reason = reason; +	cmd->reject_reason = reason;  	cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL);  	if (!cmd->buf_ptr) { @@ -709,8 +691,6 @@ int iscsit_add_reject_from_cmd(  	cmd->i_state = ISTATE_SEND_REJECT;  	iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); - -	ret = wait_for_completion_interruptible(&cmd->reject_comp);  	/*  	 * Perform the kref_put now if se_cmd has already been setup by  	 * scsit_setup_scsi_cmd() @@ -719,12 +699,19 @@ int iscsit_add_reject_from_cmd(  		pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");  		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);  	} -	if (ret != 0) -		return -1; +	return -1; +} -	return (!fail_conn) ? 0 : -1; +static int iscsit_add_reject_cmd(struct iscsi_cmd *cmd, u8 reason, +				 unsigned char *buf) +{ +	return iscsit_add_reject_from_cmd(cmd, reason, true, buf); +} + +int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8 reason, unsigned char *buf) +{ +	return iscsit_add_reject_from_cmd(cmd, reason, false, buf);  } -EXPORT_SYMBOL(iscsit_add_reject_from_cmd);  /*   * Map some portion of the allocated scatterlist to an iovec, suitable for @@ -844,8 +831,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  	    !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {  		pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL"  				" not set. Bad iSCSI Initiator.\n"); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_BOOKMARK_INVALID, buf);  	}  	if (((hdr->flags & ISCSI_FLAG_CMD_READ) || @@ -865,8 +852,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  		pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"  			" set when Expected Data Transfer Length is 0 for"  			" CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_BOOKMARK_INVALID, buf);  	}  done: @@ -875,62 +862,62 @@ done:  		pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE"  			" MUST be set if Expected Data Transfer Length is not 0."  			" Bad iSCSI Initiator\n"); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_BOOKMARK_INVALID, buf);  	}  	if ((hdr->flags & ISCSI_FLAG_CMD_READ) &&  	    (hdr->flags & ISCSI_FLAG_CMD_WRITE)) {  		pr_err("Bidirectional operations not supported!\n"); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_BOOKMARK_INVALID, buf);  	}  	if (hdr->opcode & ISCSI_OP_IMMEDIATE) {  		pr_err("Illegally set Immediate Bit in iSCSI Initiator"  				" Scsi Command PDU.\n"); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_BOOKMARK_INVALID, buf);  	}  	if (payload_length && !conn->sess->sess_ops->ImmediateData) {  		pr_err("ImmediateData=No but DataSegmentLength=%u,"  			" protocol error.\n", payload_length); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_PROTOCOL_ERROR, buf);  	} -	if ((be32_to_cpu(hdr->data_length )== payload_length) && +	if ((be32_to_cpu(hdr->data_length) == payload_length) &&  	    (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) {  		pr_err("Expected Data Transfer Length and Length of"  			" Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"  			" bit is not set protocol error\n"); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_PROTOCOL_ERROR, buf);  	}  	if (payload_length > be32_to_cpu(hdr->data_length)) {  		pr_err("DataSegmentLength: %u is greater than"  			" EDTL: %u, protocol error.\n", payload_length,  				hdr->data_length); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_PROTOCOL_ERROR, buf);  	}  	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {  		pr_err("DataSegmentLength: %u is greater than"  			" MaxXmitDataSegmentLength: %u, protocol error.\n",  			payload_length, conn->conn_ops->MaxXmitDataSegmentLength); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_PROTOCOL_ERROR, buf);  	}  	if (payload_length > conn->sess->sess_ops->FirstBurstLength) {  		pr_err("DataSegmentLength: %u is greater than"  			" FirstBurstLength: %u, protocol error.\n",  			payload_length, conn->sess->sess_ops->FirstBurstLength); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, -				1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_BOOKMARK_INVALID, buf);  	}  	data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE : @@ -985,9 +972,8 @@ done:  		dr = iscsit_allocate_datain_req();  		if (!dr) -			return iscsit_add_reject_from_cmd( -					ISCSI_REASON_BOOKMARK_NO_RESOURCES, -					1, 1, buf, cmd); +			return iscsit_add_reject_cmd(cmd, +					ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);  		iscsit_attach_datain_req(cmd, dr);  	} @@ -1015,18 +1001,16 @@ done:  	cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb);  	if (cmd->sense_reason) {  		if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { -			return iscsit_add_reject_from_cmd( -					ISCSI_REASON_BOOKMARK_NO_RESOURCES, -					1, 1, buf, cmd); +			return iscsit_add_reject_cmd(cmd, +					ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);  		}  		goto attach_cmd;  	}  	if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) { -		return iscsit_add_reject_from_cmd( -			ISCSI_REASON_BOOKMARK_NO_RESOURCES, -			1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);  	}  attach_cmd: @@ -1075,10 +1059,6 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  			target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);  			return 0; -		} else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { -			return iscsit_add_reject_from_cmd( -				ISCSI_REASON_PROTOCOL_ERROR, -				1, 0, (unsigned char *)hdr, cmd);  		}  	} @@ -1149,11 +1129,6 @@ after_immediate_data:  		} else if (cmd->unsolicited_data)  			iscsit_set_unsoliticed_dataout(cmd); -		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) -			return iscsit_add_reject_from_cmd( -				ISCSI_REASON_PROTOCOL_ERROR, -				1, 0, (unsigned char *)hdr, cmd); -  	} else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {  		/*  		 * Immediate Data failed DataCRC and ERL>=1, @@ -1190,9 +1165,8 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  	 * traditional iSCSI block I/O.  	 */  	if (iscsit_allocate_iovecs(cmd) < 0) { -		return iscsit_add_reject_from_cmd( -				ISCSI_REASON_BOOKMARK_NO_RESOURCES, -				1, 0, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);  	}  	immed_data = cmd->immediate_data; @@ -1282,8 +1256,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,  	if (!payload_length) {  		pr_err("DataOUT payload is ZERO, protocol error.\n"); -		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, -					buf, conn); +		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, +					 buf);  	}  	/* iSCSI write */ @@ -1300,8 +1274,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,  		pr_err("DataSegmentLength: %u is greater than"  			" MaxXmitDataSegmentLength: %u\n", payload_length,  			conn->conn_ops->MaxXmitDataSegmentLength); -		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, -					buf, conn); +		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, +					 buf);  	}  	cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, @@ -1324,8 +1298,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,  	if (cmd->data_direction != DMA_TO_DEVICE) {  		pr_err("Command ITT: 0x%08x received DataOUT for a"  			" NON-WRITE command.\n", cmd->init_task_tag); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -				1, 0, buf, cmd); +		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);  	}  	se_cmd = &cmd->se_cmd;  	iscsit_mod_dataout_timer(cmd); @@ -1334,8 +1307,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,  		pr_err("DataOut Offset: %u, Length %u greater than"  			" iSCSI Command EDTL %u, protocol error.\n",  			hdr->offset, payload_length, cmd->se_cmd.data_length); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, -				1, 0, buf, cmd); +		return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf);  	}  	if (cmd->unsolicited_data) { @@ -1543,8 +1515,8 @@ int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  	if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {  		pr_err("NOPOUT ITT is reserved, but Immediate Bit is"  			" not set, protocol error.\n"); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -					1, 0, (unsigned char *)hdr, cmd); +		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, +					 (unsigned char *)hdr);  	}  	if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { @@ -1552,8 +1524,8 @@ int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  			" greater than MaxXmitDataSegmentLength: %u, protocol"  			" error.\n", payload_length,  			conn->conn_ops->MaxXmitDataSegmentLength); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -					1, 0, (unsigned char *)hdr, cmd); +		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, +					 (unsigned char *)hdr);  	}  	pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x," @@ -1612,9 +1584,7 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  			return 0;  		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) -			return iscsit_add_reject_from_cmd( -					ISCSI_REASON_PROTOCOL_ERROR, -					1, 0, (unsigned char *)hdr, cmd); +			return -1;  		return 0;  	} @@ -1780,8 +1750,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  		pr_err("Task Management Request TASK_REASSIGN not"  			" issued as immediate command, bad iSCSI Initiator"  				"implementation\n"); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -					1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_PROTOCOL_ERROR, buf);  	}  	if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&  	    be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG) @@ -1793,9 +1763,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  	if (!cmd->tmr_req) {  		pr_err("Unable to allocate memory for"  			" Task Management command!\n"); -		return iscsit_add_reject_from_cmd( -			ISCSI_REASON_BOOKMARK_NO_RESOURCES, -			1, 1, buf, cmd); +		return iscsit_add_reject_cmd(cmd, +					     ISCSI_REASON_BOOKMARK_NO_RESOURCES, +					     buf);  	}  	/* @@ -1837,17 +1807,15 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  		default:  			pr_err("Unknown iSCSI TMR Function:"  			       " 0x%02x\n", function); -			return iscsit_add_reject_from_cmd( -				ISCSI_REASON_BOOKMARK_NO_RESOURCES, -				1, 1, buf, cmd); +			return iscsit_add_reject_cmd(cmd, +				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);  		}  		ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req,  					 tcm_function, GFP_KERNEL);  		if (ret < 0) -			return iscsit_add_reject_from_cmd( -				ISCSI_REASON_BOOKMARK_NO_RESOURCES, -				1, 1, buf, cmd); +			return iscsit_add_reject_cmd(cmd, +				ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);  		cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req;  	} @@ -1906,9 +1874,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  			break;  		if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) -			return iscsit_add_reject_from_cmd( -					ISCSI_REASON_BOOKMARK_INVALID, 1, 1, -					buf, cmd); +			return iscsit_add_reject_cmd(cmd, +					ISCSI_REASON_BOOKMARK_INVALID, buf);  		break;  	default:  		pr_err("Unknown TMR function: 0x%02x, protocol" @@ -1932,9 +1899,7 @@ attach:  		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)  			return 0;  		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) -			return iscsit_add_reject_from_cmd( -					ISCSI_REASON_PROTOCOL_ERROR, -					1, 0, buf, cmd); +			return -1;  	}  	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); @@ -1970,8 +1935,8 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  		pr_err("Unable to accept text parameter length: %u"  			"greater than MaxXmitDataSegmentLength %u.\n",  		       payload_length, conn->conn_ops->MaxXmitDataSegmentLength); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -					1, 0, (unsigned char *)hdr, cmd); +		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, +					 (unsigned char *)hdr);  	}  	pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x," @@ -2033,17 +1998,16 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {  		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, (unsigned char *)hdr, cmd); +			return -1; +  		return 0;  	}  	return iscsit_execute_cmd(cmd, 0);  reject: -	return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -					  0, 0, (unsigned char *)hdr, cmd); +	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, +				 (unsigned char *)hdr);  }  EXPORT_SYMBOL(iscsit_process_text_cmd); @@ -2139,8 +2103,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  reject:  	kfree(cmd->text_in_ptr);  	cmd->text_in_ptr = NULL; -	return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -					  0, 0, buf, cmd); +	return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);  }  EXPORT_SYMBOL(iscsit_handle_text_cmd); @@ -2322,13 +2285,10 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,  			return ret;  	} else {  		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); -		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { +		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); -		} +		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) +			return -1;  	}  	return logout_remove; @@ -2352,8 +2312,8 @@ static int iscsit_handle_snack(  	if (!conn->sess->sess_ops->ErrorRecoveryLevel) {  		pr_err("Initiator sent SNACK request while in"  			" ErrorRecoveryLevel=0.\n"); -		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, -					buf, conn); +		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, +					 buf);  	}  	/*  	 * SNACK_DATA and SNACK_R2T are both 0,  so check which function to @@ -2377,13 +2337,13 @@ static int iscsit_handle_snack(  	case ISCSI_FLAG_SNACK_TYPE_RDATA:  		/* FIXME: Support R-Data SNACK */  		pr_err("R-Data SNACK Not Supported.\n"); -		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, -					buf, conn); +		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, +					 buf);  	default:  		pr_err("Unknown SNACK type 0x%02x, protocol"  			" error.\n", hdr->flags & 0x0f); -		return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, -					buf, conn); +		return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, +					 buf);  	}  	return 0; @@ -2455,14 +2415,14 @@ static int iscsit_handle_immediate_data(  				pr_err("Unable to recover from"  					" Immediate Data digest failure while"  					" in ERL=0.\n"); -				iscsit_add_reject_from_cmd( +				iscsit_reject_cmd(cmd,  						ISCSI_REASON_DATA_DIGEST_ERROR, -						1, 0, (unsigned char *)hdr, cmd); +						(unsigned char *)hdr);  				return IMMEDIATE_DATA_CANNOT_RECOVER;  			} else { -				iscsit_add_reject_from_cmd( +				iscsit_reject_cmd(cmd,  						ISCSI_REASON_DATA_DIGEST_ERROR, -						0, 0, (unsigned char *)hdr, cmd); +						(unsigned char *)hdr);  				return IMMEDIATE_DATA_ERL1_CRC_FAILURE;  			}  		} else { @@ -3595,6 +3555,7 @@ iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn,  		    struct iscsi_reject *hdr)  {  	hdr->opcode		= ISCSI_OP_REJECT; +	hdr->reason		= cmd->reject_reason;  	hdr->flags		|= ISCSI_FLAG_CMD_FINAL;  	hton24(hdr->dlength, ISCSI_HDR_LEN);  	hdr->ffffffff		= cpu_to_be32(0xffffffff); @@ -3868,18 +3829,11 @@ check_rsp_state:  	case ISTATE_SEND_STATUS_RECOVERY:  	case ISTATE_SEND_TEXTRSP:  	case ISTATE_SEND_TASKMGTRSP: +	case ISTATE_SEND_REJECT:  		spin_lock_bh(&cmd->istate_lock);  		cmd->i_state = ISTATE_SENT_STATUS;  		spin_unlock_bh(&cmd->istate_lock);  		break; -	case ISTATE_SEND_REJECT: -		if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) { -			cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN; -			complete(&cmd->reject_comp); -			goto err; -		} -		complete(&cmd->reject_comp); -		break;  	default:  		pr_err("Unknown Opcode: 0x%02x ITT:"  		       " 0x%08x, i_state: %d on CID: %hu\n", @@ -3984,8 +3938,7 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)  	case ISCSI_OP_SCSI_CMD:  		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);  		if (!cmd) -			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, -						1, buf, conn); +			goto reject;  		ret = iscsit_handle_scsi_cmd(conn, cmd, buf);  		break; @@ -3997,32 +3950,28 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)  		if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {  			cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);  			if (!cmd) -				return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, -						1, buf, conn); +				goto reject;  		}  		ret = iscsit_handle_nop_out(conn, cmd, buf);  		break;  	case ISCSI_OP_SCSI_TMFUNC:  		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);  		if (!cmd) -			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, -						1, buf, conn); +			goto reject;  		ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);  		break;  	case ISCSI_OP_TEXT:  		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);  		if (!cmd) -			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, -						1, buf, conn); +			goto reject;  		ret = iscsit_handle_text_cmd(conn, cmd, buf);  		break;  	case ISCSI_OP_LOGOUT:  		cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);  		if (!cmd) -			return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, -						1, buf, conn); +			goto reject;  		ret = iscsit_handle_logout_cmd(conn, cmd, buf);  		if (ret > 0) @@ -4054,6 +4003,8 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)  	}  	return ret; +reject: +	return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);  }  int iscsi_target_rx_thread(void *arg) @@ -4148,8 +4099,8 @@ restart:  		    (!(opcode & ISCSI_OP_LOGOUT)))) {  			pr_err("Received illegal iSCSI Opcode: 0x%02x"  			" while in Discovery Session, rejecting.\n", opcode); -			iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, -					buffer, conn); +			iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, +					  buffer);  			goto transport_err;  		} diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h index a0050b2f294e..2c437cb8ca00 100644 --- a/drivers/target/iscsi/iscsi_target.h +++ b/drivers/target/iscsi/iscsi_target.h @@ -15,7 +15,7 @@ extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *,  extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,  				struct iscsi_portal_group *);  extern int iscsit_del_np(struct iscsi_np *); -extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, struct iscsi_cmd *); +extern int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8, unsigned char *);  extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);  extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *);  extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *); diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index caa0ad9a778b..4f77a78edef9 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -132,9 +132,8 @@ enum cmd_flags_table {  	ICF_CONTIG_MEMORY			= 0x00000020,  	ICF_ATTACHED_TO_RQUEUE			= 0x00000040,  	ICF_OOO_CMDSN				= 0x00000080, -	ICF_REJECT_FAIL_CONN			= 0x00000100, -	IFC_SENDTARGETS_ALL			= 0x00000200, -	IFC_SENDTARGETS_SINGLE			= 0x00000400, +	IFC_SENDTARGETS_ALL			= 0x00000100, +	IFC_SENDTARGETS_SINGLE			= 0x00000200,  };  /* struct iscsi_cmd->i_state */ @@ -368,6 +367,8 @@ struct iscsi_cmd {  	u8			maxcmdsn_inc;  	/* Immediate Unsolicited Dataout */  	u8			unsolicited_data; +	/* Reject reason code */ +	u8			reject_reason;  	/* CID contained in logout PDU when opcode == ISCSI_INIT_LOGOUT_CMND */  	u16			logout_cid;  	/* Command flags */ @@ -450,7 +451,6 @@ struct iscsi_cmd {  	struct list_head	datain_list;  	/* R2T List */  	struct list_head	cmd_r2t_list; -	struct completion	reject_comp;  	/* Timer for DataOUT */  	struct timer_list	dataout_timer;  	/* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */ diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index 8e6298cc8839..8f074e0b6099 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c @@ -746,13 +746,12 @@ int iscsit_check_post_dataout(  		if (!conn->sess->sess_ops->ErrorRecoveryLevel) {  			pr_err("Unable to recover from DataOUT CRC"  				" failure while ERL=0, closing session.\n"); -			iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR, -					1, 0, buf, cmd); +			iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, +					  buf);  			return DATAOUT_CANNOT_RECOVER;  		} -		iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR, -				0, 0, buf, cmd); +		iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, buf);  		return iscsit_dataout_post_crc_failed(cmd, buf);  	}  } diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 40d9dbca987b..d00f1326f0c8 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -162,9 +162,8 @@ static int iscsit_handle_r2t_snack(  			" protocol error.\n", cmd->init_task_tag, begrun,  			(begrun + runlength), cmd->acked_data_sn); -			return iscsit_add_reject_from_cmd( -					ISCSI_REASON_PROTOCOL_ERROR, -					1, 0, buf, cmd); +			return iscsit_reject_cmd(cmd, +					ISCSI_REASON_PROTOCOL_ERROR, buf);  	}  	if (runlength) { @@ -173,8 +172,8 @@ static int iscsit_handle_r2t_snack(  			" with BegRun: 0x%08x, RunLength: 0x%08x, exceeds"  			" current R2TSN: 0x%08x, protocol error.\n",  			cmd->init_task_tag, begrun, runlength, cmd->r2t_sn); -			return iscsit_add_reject_from_cmd( -				ISCSI_REASON_BOOKMARK_INVALID, 1, 0, buf, cmd); +			return iscsit_reject_cmd(cmd, +					ISCSI_REASON_BOOKMARK_INVALID, buf);  		}  		last_r2tsn = (begrun + runlength);  	} else @@ -433,8 +432,7 @@ static int iscsit_handle_recovery_datain(  			" protocol error.\n", cmd->init_task_tag, begrun,  			(begrun + runlength), cmd->acked_data_sn); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, -				1, 0, buf, cmd); +		return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf);  	}  	/* @@ -445,14 +443,14 @@ static int iscsit_handle_recovery_datain(  		pr_err("Initiator requesting BegRun: 0x%08x, RunLength"  			": 0x%08x greater than maximum DataSN: 0x%08x.\n",  				begrun, runlength, (cmd->data_sn - 1)); -		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, -				1, 0, buf, cmd); +		return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, +					 buf);  	}  	dr = iscsit_allocate_datain_req();  	if (!dr) -		return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_NO_RESOURCES, -				1, 0, buf, cmd); +		return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_NO_RESOURCES, +					 buf);  	dr->data_sn = dr->begrun = begrun;  	dr->runlength = runlength; diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index fe712d6cc478..96ce6f2ec428 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -178,7 +178,6 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)  	INIT_LIST_HEAD(&cmd->i_conn_node);  	INIT_LIST_HEAD(&cmd->datain_list);  	INIT_LIST_HEAD(&cmd->cmd_r2t_list); -	init_completion(&cmd->reject_comp);  	spin_lock_init(&cmd->datain_lock);  	spin_lock_init(&cmd->dataout_timeout_lock);  	spin_lock_init(&cmd->istate_lock); | 
