diff options
Diffstat (limited to 'drivers/target/target_core_spc.c')
-rw-r--r-- | drivers/target/target_core_spc.c | 113 |
1 files changed, 79 insertions, 34 deletions
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 89c0d56294cc..50290abc07bc 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -1424,9 +1424,10 @@ static struct target_opcode_descriptor tcm_opcode_write_verify16 = { .update_usage_bits = set_dpofua_usage_bits, }; -static bool tcm_is_ws_enabled(struct se_cmd *cmd) +static bool tcm_is_ws_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; return (dev->dev_attrib.emulate_tpws && !!ops->execute_unmap) || @@ -1451,7 +1452,8 @@ static struct target_opcode_descriptor tcm_opcode_write_same32 = { .update_usage_bits = set_dpofua_usage_bits32, }; -static bool tcm_is_caw_enabled(struct se_cmd *cmd) +static bool tcm_is_caw_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1491,7 +1493,8 @@ static struct target_opcode_descriptor tcm_opcode_read_capacity16 = { 0xff, 0xff, 0x00, SCSI_CONTROL_MASK}, }; -static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd) +static bool tcm_is_rep_ref_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1502,7 +1505,6 @@ static bool tcm_is_rep_ref_enabled(struct se_cmd *cmd) } spin_unlock(&dev->t10_alua.lba_map_lock); return true; - } static struct target_opcode_descriptor tcm_opcode_read_report_refferals = { @@ -1537,9 +1539,10 @@ static struct target_opcode_descriptor tcm_opcode_sync_cache16 = { 0xff, 0xff, SCSI_GROUP_NUMBER_MASK, SCSI_CONTROL_MASK}, }; -static bool tcm_is_unmap_enabled(struct se_cmd *cmd) +static bool tcm_is_unmap_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { - struct sbc_ops *ops = cmd->protocol_data; + struct exec_cmd_ops *ops = cmd->protocol_data; struct se_device *dev = cmd->se_dev; return ops->execute_unmap && dev->dev_attrib.emulate_tpu; @@ -1659,11 +1662,46 @@ static struct target_opcode_descriptor tcm_opcode_pri_read_resrv = { 0xff, SCSI_CONTROL_MASK}, }; -static bool tcm_is_pr_enabled(struct se_cmd *cmd) +static bool tcm_is_pr_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { 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 = { @@ -1788,20 +1826,13 @@ static struct target_opcode_descriptor tcm_opcode_pro_register_move = { .enabled = tcm_is_pr_enabled, }; -static bool tcm_is_scsi2_reservations_enabled(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 = { @@ -1811,7 +1842,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 = { @@ -1820,7 +1851,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 = { @@ -1830,7 +1861,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 = { @@ -1849,7 +1880,8 @@ static struct target_opcode_descriptor tcm_opcode_inquiry = { 0xff, SCSI_CONTROL_MASK}, }; -static bool tcm_is_3pc_enabled(struct se_cmd *cmd) +static bool tcm_is_3pc_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1910,8 +1942,8 @@ static struct target_opcode_descriptor tcm_opcode_report_target_pgs = { 0xff, 0xff, 0x00, SCSI_CONTROL_MASK}, }; - -static bool spc_rsoc_enabled(struct se_cmd *cmd) +static bool spc_rsoc_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; @@ -1931,7 +1963,8 @@ static struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = { .enabled = spc_rsoc_enabled, }; -static bool tcm_is_set_tpg_enabled(struct se_cmd *cmd) +static bool tcm_is_set_tpg_enabled(struct target_opcode_descriptor *descr, + struct se_cmd *cmd) { struct t10_alua_tg_pt_gp *l_tg_pt_gp; struct se_lun *l_lun = cmd->se_lun; @@ -2118,7 +2151,7 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) if (descr->serv_action_valid) return TCM_INVALID_CDB_FIELD; - if (!descr->enabled || descr->enabled(cmd)) + if (!descr->enabled || descr->enabled(descr, cmd)) *opcode = descr; break; case 0x2: @@ -2132,7 +2165,8 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) */ if (descr->serv_action_valid && descr->service_action == requested_sa) { - if (!descr->enabled || descr->enabled(cmd)) + if (!descr->enabled || descr->enabled(descr, + cmd)) *opcode = descr; } else if (!descr->serv_action_valid) return TCM_INVALID_CDB_FIELD; @@ -2145,7 +2179,8 @@ spc_rsoc_get_descr(struct se_cmd *cmd, struct target_opcode_descriptor **opcode) * be returned in the one_command parameter data format. */ if (descr->service_action == requested_sa) - if (!descr->enabled || descr->enabled(cmd)) + if (!descr->enabled || descr->enabled(descr, + cmd)) *opcode = descr; break; } @@ -2202,7 +2237,7 @@ spc_emulate_report_supp_op_codes(struct se_cmd *cmd) for (i = 0; i < ARRAY_SIZE(tcm_supported_opcodes); i++) { descr = tcm_supported_opcodes[i]; - if (descr->enabled && !descr->enabled(cmd)) + if (descr->enabled && !descr->enabled(descr, cmd)) continue; response_length += spc_rsoc_encode_command_descriptor( @@ -2231,12 +2266,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]) { |