Commit 8455799d authored by Mike Christie's avatar Mike Christie Committed by Martin K. Petersen
Browse files

scsi: target: Report and detect unsupported PR commands



The backend modules don't know about ports and I_T nexuses and the pr_ops
callouts the modules will use don't support the old RESERVE/RELEASE
commands. This patch has us report we don't support those types of
commands and fail them.

Signed-off-by: default avatarMike Christie <michael.christie@oracle.com>
Link: https://lore.kernel.org/r/20230407200551.12660-18-michael.christie@oracle.com


Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent d9b3275b
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -3554,6 +3554,18 @@ target_try_pr_out_pt(struct se_cmd *cmd, u8 sa, u64 res_key, u64 sa_res_key,
		return TCM_UNSUPPORTED_SCSI_OPCODE;
	}

	switch (sa) {
	case PRO_REGISTER_AND_MOVE:
	case PRO_REPLACE_LOST_RESERVATION:
		pr_err("SPC-3 PR: PRO_REGISTER_AND_MOVE and PRO_REPLACE_LOST_RESERVATION are not supported by PR passthrough.\n");
		return TCM_UNSUPPORTED_SCSI_OPCODE;
	}

	if (spec_i_pt || all_tg_pt) {
		pr_err("SPC-3 PR: SPEC_I_PT and ALL_TG_PT are not supported by PR passthrough.\n");
		return TCM_UNSUPPORTED_SCSI_OPCODE;
	}

	return ops->execute_pr_out(cmd, sa, res_key, sa_res_key, type, aptpl);
}

@@ -4082,6 +4094,11 @@ static sense_reason_t target_try_pr_in_pt(struct se_cmd *cmd, u8 sa)
		return TCM_UNSUPPORTED_SCSI_OPCODE;
	}

	if (sa == PRI_READ_FULL_STATUS) {
		pr_err("SPC-3 PR: PRI_READ_FULL_STATUS is not supported by PR passthrough.\n");
		return TCM_UNSUPPORTED_SCSI_OPCODE;
	}

	buf = transport_kmap_data_sg(cmd);
	if (!buf)
		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+55 −20
Original line number Diff line number Diff line
@@ -1672,7 +1672,41 @@ static bool tcm_is_pr_enabled(struct target_opcode_descriptor *descr,
{
	struct se_device *dev = cmd->se_dev;

	return dev->dev_attrib.emulate_pr;
	if (!dev->dev_attrib.emulate_pr)
		return false;

	if (!(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR))
		return true;

	switch (descr->opcode) {
	case RESERVE:
	case RESERVE_10:
	case RELEASE:
	case RELEASE_10:
		/*
		 * The pr_ops which are used by the backend modules don't
		 * support these commands.
		 */
		return false;
	case PERSISTENT_RESERVE_OUT:
		switch (descr->service_action) {
		case PRO_REGISTER_AND_MOVE:
		case PRO_REPLACE_LOST_RESERVATION:
			/*
			 * The backend modules don't have access to ports and
			 * I_T nexuses so they can't handle these type of
			 * requests.
			 */
			return false;
		}
		break;
	case PERSISTENT_RESERVE_IN:
		if (descr->service_action == PRI_READ_FULL_STATUS)
			return false;
		break;
	}

	return true;
}

static struct target_opcode_descriptor tcm_opcode_pri_read_caps = {
@@ -1797,22 +1831,13 @@ static struct target_opcode_descriptor tcm_opcode_pro_register_move = {
	.enabled = tcm_is_pr_enabled,
};

static bool
tcm_is_scsi2_reservations_enabled(struct target_opcode_descriptor *descr,
				  struct se_cmd *cmd)
{
	struct se_device *dev = cmd->se_dev;

	return dev->dev_attrib.emulate_pr;
}

static struct target_opcode_descriptor tcm_opcode_release = {
	.support = SCSI_SUPPORT_FULL,
	.opcode = RELEASE,
	.cdb_size = 6,
	.usage_bits = {RELEASE, 0x00, 0x00, 0x00,
		       0x00, SCSI_CONTROL_MASK},
	.enabled = tcm_is_scsi2_reservations_enabled,
	.enabled = tcm_is_pr_enabled,
};

static struct target_opcode_descriptor tcm_opcode_release10 = {
@@ -1822,7 +1847,7 @@ static struct target_opcode_descriptor tcm_opcode_release10 = {
	.usage_bits = {RELEASE_10, 0x00, 0x00, 0x00,
		       0x00, 0x00, 0x00, 0xff,
		       0xff, SCSI_CONTROL_MASK},
	.enabled = tcm_is_scsi2_reservations_enabled,
	.enabled = tcm_is_pr_enabled,
};

static struct target_opcode_descriptor tcm_opcode_reserve = {
@@ -1831,7 +1856,7 @@ static struct target_opcode_descriptor tcm_opcode_reserve = {
	.cdb_size = 6,
	.usage_bits = {RESERVE, 0x00, 0x00, 0x00,
		       0x00, SCSI_CONTROL_MASK},
	.enabled = tcm_is_scsi2_reservations_enabled,
	.enabled = tcm_is_pr_enabled,
};

static struct target_opcode_descriptor tcm_opcode_reserve10 = {
@@ -1841,7 +1866,7 @@ static struct target_opcode_descriptor tcm_opcode_reserve10 = {
	.usage_bits = {RESERVE_10, 0x00, 0x00, 0x00,
		       0x00, 0x00, 0x00, 0xff,
		       0xff, SCSI_CONTROL_MASK},
	.enabled = tcm_is_scsi2_reservations_enabled,
	.enabled = tcm_is_pr_enabled,
};

static struct target_opcode_descriptor tcm_opcode_request_sense = {
@@ -2246,12 +2271,22 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
	struct se_device *dev = cmd->se_dev;
	unsigned char *cdb = cmd->t_task_cdb;

	if (!dev->dev_attrib.emulate_pr &&
	    ((cdb[0] == PERSISTENT_RESERVE_IN) ||
	     (cdb[0] == PERSISTENT_RESERVE_OUT) ||
	     (cdb[0] == RELEASE || cdb[0] == RELEASE_10) ||
	     (cdb[0] == RESERVE || cdb[0] == RESERVE_10))) {
	switch (cdb[0]) {
	case RESERVE:
	case RESERVE_10:
	case RELEASE:
	case RELEASE_10:
		if (!dev->dev_attrib.emulate_pr)
			return TCM_UNSUPPORTED_SCSI_OPCODE;

		if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
			return TCM_UNSUPPORTED_SCSI_OPCODE;
		break;
	case PERSISTENT_RESERVE_IN:
	case PERSISTENT_RESERVE_OUT:
		if (!dev->dev_attrib.emulate_pr)
			return TCM_UNSUPPORTED_SCSI_OPCODE;
		break;
	}

	switch (cdb[0]) {