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: Mike Christie <michael.christie@oracle.com>
Link: https://lore.kernel.org/r/20230407200551.12660-18-michael.christie@oracle.com
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Mike Christie 2023-04-07 15:05:50 -05:00 committed by Martin K. Petersen
parent d9b3275bdd
commit 8455799d2d
2 changed files with 72 additions and 20 deletions

View file

@ -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;

View file

@ -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))) {
return TCM_UNSUPPORTED_SCSI_OPCODE;
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]) {