scsi: target: Report and detect unsupported PR commands
authorMike Christie <michael.christie@oracle.com>
Fri, 7 Apr 2023 20:05:50 +0000 (15:05 -0500)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 12 Apr 2023 01:55:36 +0000 (21:55 -0400)
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>
drivers/target/target_core_pr.c
drivers/target/target_core_spc.c

index e16ef7d676afccea4b102fd4b70699b3627d683a..7a3f07979a020af5bb0dbc622c511699e6d1da0a 100644 (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;
index caf8d1325007015eb0895c67e324216825032b43..053bd2eea0e6854ade86625fb9d4d35c459a8d7f 100644 (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]) {