diff options
Diffstat (limited to 'drivers/target/target_core_pr.c')
-rw-r--r-- | drivers/target/target_core_pr.c | 62 |
1 files changed, 35 insertions, 27 deletions
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 830953a743d6..34403e80b87c 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c | |||
@@ -3734,12 +3734,30 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb) | |||
3734 | /* | 3734 | /* |
3735 | * See spc4r17 section 6.14 Table 170 | 3735 | * See spc4r17 section 6.14 Table 170 |
3736 | */ | 3736 | */ |
3737 | static int core_scsi3_emulate_pr_out(struct se_cmd *cmd, unsigned char *cdb) | 3737 | int target_scsi3_emulate_pr_out(struct se_cmd *cmd) |
3738 | { | 3738 | { |
3739 | unsigned char *cdb = &cmd->t_task_cdb[0]; | ||
3739 | unsigned char *buf; | 3740 | unsigned char *buf; |
3740 | u64 res_key, sa_res_key; | 3741 | u64 res_key, sa_res_key; |
3741 | int sa, scope, type, aptpl; | 3742 | int sa, scope, type, aptpl; |
3742 | int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; | 3743 | int spec_i_pt = 0, all_tg_pt = 0, unreg = 0; |
3744 | |||
3745 | /* | ||
3746 | * Following spc2r20 5.5.1 Reservations overview: | ||
3747 | * | ||
3748 | * If a logical unit has been reserved by any RESERVE command and is | ||
3749 | * still reserved by any initiator, all PERSISTENT RESERVE IN and all | ||
3750 | * PERSISTENT RESERVE OUT commands shall conflict regardless of | ||
3751 | * initiator or service action and shall terminate with a RESERVATION | ||
3752 | * CONFLICT status. | ||
3753 | */ | ||
3754 | if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) { | ||
3755 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" | ||
3756 | " SPC-2 reservation is held, returning" | ||
3757 | " RESERVATION_CONFLICT\n"); | ||
3758 | return PYX_TRANSPORT_RESERVATION_CONFLICT; | ||
3759 | } | ||
3760 | |||
3743 | /* | 3761 | /* |
3744 | * FIXME: A NULL struct se_session pointer means an this is not coming from | 3762 | * FIXME: A NULL struct se_session pointer means an this is not coming from |
3745 | * a $FABRIC_MOD's nexus, but from internal passthrough ops. | 3763 | * a $FABRIC_MOD's nexus, but from internal passthrough ops. |
@@ -4185,29 +4203,8 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) | |||
4185 | return 0; | 4203 | return 0; |
4186 | } | 4204 | } |
4187 | 4205 | ||
4188 | static int core_scsi3_emulate_pr_in(struct se_cmd *cmd, unsigned char *cdb) | 4206 | int target_scsi3_emulate_pr_in(struct se_cmd *cmd) |
4189 | { | ||
4190 | switch (cdb[1] & 0x1f) { | ||
4191 | case PRI_READ_KEYS: | ||
4192 | return core_scsi3_pri_read_keys(cmd); | ||
4193 | case PRI_READ_RESERVATION: | ||
4194 | return core_scsi3_pri_read_reservation(cmd); | ||
4195 | case PRI_REPORT_CAPABILITIES: | ||
4196 | return core_scsi3_pri_report_capabilities(cmd); | ||
4197 | case PRI_READ_FULL_STATUS: | ||
4198 | return core_scsi3_pri_read_full_status(cmd); | ||
4199 | default: | ||
4200 | pr_err("Unknown PERSISTENT_RESERVE_IN service" | ||
4201 | " action: 0x%02x\n", cdb[1] & 0x1f); | ||
4202 | return PYX_TRANSPORT_INVALID_CDB_FIELD; | ||
4203 | } | ||
4204 | |||
4205 | } | ||
4206 | |||
4207 | int core_scsi3_emulate_pr(struct se_cmd *cmd) | ||
4208 | { | 4207 | { |
4209 | unsigned char *cdb = &cmd->t_task_cdb[0]; | ||
4210 | struct se_device *dev = cmd->se_dev; | ||
4211 | /* | 4208 | /* |
4212 | * Following spc2r20 5.5.1 Reservations overview: | 4209 | * Following spc2r20 5.5.1 Reservations overview: |
4213 | * | 4210 | * |
@@ -4217,16 +4214,27 @@ int core_scsi3_emulate_pr(struct se_cmd *cmd) | |||
4217 | * initiator or service action and shall terminate with a RESERVATION | 4214 | * initiator or service action and shall terminate with a RESERVATION |
4218 | * CONFLICT status. | 4215 | * CONFLICT status. |
4219 | */ | 4216 | */ |
4220 | if (dev->dev_flags & DF_SPC2_RESERVATIONS) { | 4217 | if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) { |
4221 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" | 4218 | pr_err("Received PERSISTENT_RESERVE CDB while legacy" |
4222 | " SPC-2 reservation is held, returning" | 4219 | " SPC-2 reservation is held, returning" |
4223 | " RESERVATION_CONFLICT\n"); | 4220 | " RESERVATION_CONFLICT\n"); |
4224 | return PYX_TRANSPORT_RESERVATION_CONFLICT; | 4221 | return PYX_TRANSPORT_RESERVATION_CONFLICT; |
4225 | } | 4222 | } |
4226 | 4223 | ||
4227 | return (cdb[0] == PERSISTENT_RESERVE_OUT) ? | 4224 | switch (cmd->t_task_cdb[1] & 0x1f) { |
4228 | core_scsi3_emulate_pr_out(cmd, cdb) : | 4225 | case PRI_READ_KEYS: |
4229 | core_scsi3_emulate_pr_in(cmd, cdb); | 4226 | return core_scsi3_pri_read_keys(cmd); |
4227 | case PRI_READ_RESERVATION: | ||
4228 | return core_scsi3_pri_read_reservation(cmd); | ||
4229 | case PRI_REPORT_CAPABILITIES: | ||
4230 | return core_scsi3_pri_report_capabilities(cmd); | ||
4231 | case PRI_READ_FULL_STATUS: | ||
4232 | return core_scsi3_pri_read_full_status(cmd); | ||
4233 | default: | ||
4234 | pr_err("Unknown PERSISTENT_RESERVE_IN service" | ||
4235 | " action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f); | ||
4236 | return PYX_TRANSPORT_INVALID_CDB_FIELD; | ||
4237 | } | ||
4230 | } | 4238 | } |
4231 | 4239 | ||
4232 | static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type) | 4240 | static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type) |