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

Commit 561bf158 authored by Nicholas Bellinger's avatar Nicholas Bellinger
Browse files

iscsi-target: Fix iscsit_sequence_cmd reject handling for iser



This patch moves ISCSI_OP_REJECT failures into iscsit_sequence_cmd()
in order to avoid external iscsit_reject_cmd() reject usage for all
PDU types.

It also updates PDU specific handlers for traditional iscsi-target
code to not reset the session after posting a ISCSI_OP_REJECT during
setup.

(v2: Fix CMDSN_LOWER_THAN_EXP for ISCSI_OP_SCSI to call
     target_put_sess_cmd() after iscsit_sequence_cmd() failure)

Cc: Or Gerlitz <ogerlitz@mellanox.com>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: stable@vger.kernel.org  # 3.10+
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent ba159914
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -934,7 +934,7 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
	}

sequence_cmd:
	rc = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
	rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);

	if (!rc && dump_payload == false && unsol_data)
		iscsit_set_unsoliticed_dataout(cmd);
+34 −21
Original line number Diff line number Diff line
@@ -1052,11 +1052,11 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
	 * be acknowledged. (See below)
	 */
	if (!cmd->immediate_data) {
		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
			if (!cmd->sense_reason)
				return 0;

		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
					(unsigned char *)hdr, hdr->cmdsn);
		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
			return -1;
		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
			target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
			return 0;
		}
@@ -1083,6 +1083,9 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
	 * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below.
	 */
	if (cmd->sense_reason) {
		if (cmd->reject_reason)
			return 0;

		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
		return 1;
	}
@@ -1091,10 +1094,8 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
	 * the backend memory allocation.
	 */
	cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
	if (cmd->sense_reason) {
		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
	if (cmd->sense_reason)
		return 1;
	}

	return 0;
}
@@ -1104,6 +1105,7 @@ static int
iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
			  bool dump_payload)
{
	struct iscsi_conn *conn = cmd->conn;
	int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
	/*
	 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
@@ -1120,12 +1122,22 @@ iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
		 * DataCRC, check against ExpCmdSN/MaxCmdSN if
		 * Immediate Bit is not set.
		 */
		cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, hdr->cmdsn);
		cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd,
					(unsigned char *)hdr, hdr->cmdsn);
		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
			return -1;
		} else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
			target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
			return 0;
		}

		if (cmd->sense_reason) {
			if (iscsit_dump_data_payload(cmd->conn,
					cmd->first_burst_len, 1) < 0)
				return -1;
			int rc;

			rc = iscsit_dump_data_payload(cmd->conn,
						      cmd->first_burst_len, 1);
			target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
			return rc;
		} else if (cmd->unsolicited_data)
			iscsit_set_unsoliticed_dataout(cmd);

@@ -1159,7 +1171,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,

	rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
	if (rc < 0)
		return rc;
		return 0;
	/*
	 * Allocation iovecs needed for struct socket operations for
	 * traditional iSCSI block I/O.
@@ -1494,7 +1506,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)

	rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
	if (rc < 0)
		return rc;
		return 0;
	else if (!cmd)
		return 0;

@@ -1579,10 +1591,10 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
			return 0;
		}

		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
				(unsigned char *)hdr, hdr->cmdsn);
                if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
			return 0;

		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
			return -1;

@@ -1623,7 +1635,7 @@ static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,

	ret = iscsit_setup_nop_out(conn, cmd, hdr);
	if (ret < 0)
		return ret;
		return 0;
	/*
	 * Handle NOP-OUT payload for traditional iSCSI sockets
	 */
@@ -1893,7 +1905,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
	spin_unlock_bh(&conn->cmd_lock);

	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
		int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
		int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
		if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)
			out_of_order_cmdsn = 1;
		else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
@@ -1996,7 +2008,8 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
	iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));

	if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
		cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
				(unsigned char *)hdr, hdr->cmdsn);
		if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
			return -1;

@@ -2022,7 +2035,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,

	rc = iscsit_setup_text_cmd(conn, cmd, hdr);
	if (rc < 0)
		return rc;
		return 0;

	rx_size = payload_length;
	if (payload_length) {
@@ -2284,7 +2297,7 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
		if (ret < 0)
			return ret;
	} else {
		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
		cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
		if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
			logout_remove = 0;
		else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+3 −3
Original line number Diff line number Diff line
@@ -1088,7 +1088,7 @@ int iscsit_handle_ooo_cmdsn(

	ooo_cmdsn = iscsit_allocate_ooo_cmdsn();
	if (!ooo_cmdsn)
		return CMDSN_ERROR_CANNOT_RECOVER;
		return -ENOMEM;

	ooo_cmdsn->cmd			= cmd;
	ooo_cmdsn->batch_count		= (batch) ?
@@ -1099,10 +1099,10 @@ int iscsit_handle_ooo_cmdsn(

	if (iscsit_attach_ooo_cmdsn(sess, ooo_cmdsn) < 0) {
		kmem_cache_free(lio_ooo_cache, ooo_cmdsn);
		return CMDSN_ERROR_CANNOT_RECOVER;
		return -ENOMEM;
	}

	return CMDSN_HIGHER_THAN_EXP;
	return 0;
}

static int iscsit_set_dataout_timeout_values(
+20 −6
Original line number Diff line number Diff line
@@ -283,13 +283,12 @@ static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cm
 * 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,
	__be32 cmdsn)
int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
			unsigned char *buf, __be32 cmdsn)
{
	int ret;
	int cmdsn_ret;
	int ret, cmdsn_ret;
	bool reject = false;
	u8 reason = ISCSI_REASON_BOOKMARK_NO_RESOURCES;

	mutex_lock(&conn->sess->cmdsn_mutex);

@@ -299,9 +298,19 @@ int iscsit_sequence_cmd(
		ret = iscsit_execute_cmd(cmd, 0);
		if ((ret >= 0) && !list_empty(&conn->sess->sess_ooo_cmdsn_list))
			iscsit_execute_ooo_cmdsns(conn->sess);
		else if (ret < 0) {
			reject = true;
			ret = CMDSN_ERROR_CANNOT_RECOVER;
		}
		break;
	case CMDSN_HIGHER_THAN_EXP:
		ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, be32_to_cpu(cmdsn));
		if (ret < 0) {
			reject = true;
			ret = CMDSN_ERROR_CANNOT_RECOVER;
			break;
		}
		ret = CMDSN_HIGHER_THAN_EXP;
		break;
	case CMDSN_LOWER_THAN_EXP:
		cmd->i_state = ISTATE_REMOVE;
@@ -309,11 +318,16 @@ int iscsit_sequence_cmd(
		ret = cmdsn_ret;
		break;
	default:
		reason = ISCSI_REASON_PROTOCOL_ERROR;
		reject = true;
		ret = cmdsn_ret;
		break;
	}
	mutex_unlock(&conn->sess->cmdsn_mutex);

	if (reject)
		iscsit_reject_cmd(cmd, reason, buf);

	return ret;
}
EXPORT_SYMBOL(iscsit_sequence_cmd);
+2 −1
Original line number Diff line number Diff line
@@ -13,7 +13,8 @@ extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
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);
int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, __be32 cmdsn);
extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
			       unsigned char * ,__be32 cmdsn);
extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *);
extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t);
extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
Loading