|
@@ -68,7 +68,8 @@ int core_pr_dump_initiator_port(
|
|
|
static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *,
|
|
|
struct t10_pr_registration *, int);
|
|
|
|
|
|
-static int target_scsi2_reservation_check(struct se_cmd *cmd)
|
|
|
+static sense_reason_t
|
|
|
+target_scsi2_reservation_check(struct se_cmd *cmd)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_session *sess = cmd->se_sess;
|
|
@@ -86,11 +87,11 @@ static int target_scsi2_reservation_check(struct se_cmd *cmd)
|
|
|
return 0;
|
|
|
|
|
|
if (dev->dev_reserved_node_acl != sess->se_node_acl)
|
|
|
- return -EBUSY;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
|
|
|
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) {
|
|
|
if (dev->dev_res_bin_isid != sess->sess_bin_isid)
|
|
|
- return -EBUSY;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -165,32 +166,28 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd)
|
|
|
pr_err("Received legacy SPC-2 RESERVE/RELEASE"
|
|
|
" while active SPC-3 registrations exist,"
|
|
|
" returning RESERVATION_CONFLICT\n");
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
return -EBUSY;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int target_scsi2_reservation_release(struct se_cmd *cmd)
|
|
|
+sense_reason_t
|
|
|
+target_scsi2_reservation_release(struct se_cmd *cmd)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_session *sess = cmd->se_sess;
|
|
|
struct se_portal_group *tpg;
|
|
|
- int ret = 0, rc;
|
|
|
+ int rc;
|
|
|
|
|
|
if (!sess || !sess->se_tpg)
|
|
|
goto out;
|
|
|
rc = target_check_scsi2_reservation_conflict(cmd);
|
|
|
if (rc == 1)
|
|
|
goto out;
|
|
|
- else if (rc < 0) {
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ if (rc < 0)
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
|
|
|
- ret = 0;
|
|
|
spin_lock(&dev->dev_reservation_lock);
|
|
|
if (!dev->dev_reserved_node_acl || !sess)
|
|
|
goto out_unlock;
|
|
@@ -216,25 +213,24 @@ int target_scsi2_reservation_release(struct se_cmd *cmd)
|
|
|
out_unlock:
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
out:
|
|
|
- if (!ret)
|
|
|
- target_complete_cmd(cmd, GOOD);
|
|
|
- return ret;
|
|
|
+ target_complete_cmd(cmd, GOOD);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-int target_scsi2_reservation_reserve(struct se_cmd *cmd)
|
|
|
+sense_reason_t
|
|
|
+target_scsi2_reservation_reserve(struct se_cmd *cmd)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_session *sess = cmd->se_sess;
|
|
|
struct se_portal_group *tpg;
|
|
|
- int ret = 0, rc;
|
|
|
+ sense_reason_t ret = 0;
|
|
|
+ int rc;
|
|
|
|
|
|
if ((cmd->t_task_cdb[1] & 0x01) &&
|
|
|
(cmd->t_task_cdb[1] & 0x02)) {
|
|
|
pr_err("LongIO and Obselete Bits set, returning"
|
|
|
" ILLEGAL_REQUEST\n");
|
|
|
- cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ return TCM_UNSUPPORTED_SCSI_OPCODE;
|
|
|
}
|
|
|
/*
|
|
|
* This is currently the case for target_core_mod passthrough struct se_cmd
|
|
@@ -245,13 +241,10 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd)
|
|
|
rc = target_check_scsi2_reservation_conflict(cmd);
|
|
|
if (rc == 1)
|
|
|
goto out;
|
|
|
- else if (rc < 0) {
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
|
|
|
- ret = 0;
|
|
|
+ if (rc < 0)
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
+
|
|
|
tpg = sess->se_tpg;
|
|
|
spin_lock(&dev->dev_reservation_lock);
|
|
|
if (dev->dev_reserved_node_acl &&
|
|
@@ -265,8 +258,7 @@ int target_scsi2_reservation_reserve(struct se_cmd *cmd)
|
|
|
" from %s \n", cmd->se_lun->unpacked_lun,
|
|
|
cmd->se_deve->mapped_lun,
|
|
|
sess->se_node_acl->initiatorname);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
|
|
@@ -536,7 +528,8 @@ static int core_scsi3_pr_seq_non_holder(
|
|
|
return 1; /* Conflict by default */
|
|
|
}
|
|
|
|
|
|
-static int target_scsi3_pr_reservation_check(struct se_cmd *cmd)
|
|
|
+static sense_reason_t
|
|
|
+target_scsi3_pr_reservation_check(struct se_cmd *cmd)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_session *sess = cmd->se_sess;
|
|
@@ -562,7 +555,7 @@ static int target_scsi3_pr_reservation_check(struct se_cmd *cmd)
|
|
|
|
|
|
check_nonholder:
|
|
|
if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type))
|
|
|
- return -EBUSY;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1435,7 +1428,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
|
|
|
smp_mb__after_atomic_dec();
|
|
|
}
|
|
|
|
|
|
-static int core_scsi3_decode_spec_i_port(
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_decode_spec_i_port(
|
|
|
struct se_cmd *cmd,
|
|
|
struct se_portal_group *tpg,
|
|
|
unsigned char *l_isid,
|
|
@@ -1457,8 +1451,9 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
unsigned char *buf;
|
|
|
unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident;
|
|
|
char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN];
|
|
|
+ sense_reason_t ret;
|
|
|
u32 tpdl, tid_len = 0;
|
|
|
- int ret, dest_local_nexus, prf_isid;
|
|
|
+ int dest_local_nexus, prf_isid;
|
|
|
u32 dest_rtpi = 0;
|
|
|
|
|
|
memset(dest_iport, 0, 64);
|
|
@@ -1473,8 +1468,7 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL);
|
|
|
if (!tidh_new) {
|
|
|
pr_err("Unable to allocate tidh_new\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
INIT_LIST_HEAD(&tidh_new->dest_list);
|
|
|
tidh_new->dest_tpg = tpg;
|
|
@@ -1486,8 +1480,7 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
sa_res_key, all_tg_pt, aptpl);
|
|
|
if (!local_pr_reg) {
|
|
|
kfree(tidh_new);
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -ENOMEM;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
tidh_new->dest_pr_reg = local_pr_reg;
|
|
|
/*
|
|
@@ -1501,12 +1494,16 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
if (cmd->data_length < 28) {
|
|
|
pr_warn("SPC-PR: Received PR OUT parameter list"
|
|
|
" length too small: %u\n", cmd->data_length);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
buf = transport_kmap_data_sg(cmd);
|
|
|
+ if (!buf) {
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* For a PERSISTENT RESERVE OUT specify initiator ports payload,
|
|
|
* first extract TransportID Parameter Data Length, and make sure
|
|
@@ -1521,9 +1518,8 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
pr_err("SPC-3 PR: Illegal tpdl: %u + 28 byte header"
|
|
|
" does not equal CDB data_length: %u\n", tpdl,
|
|
|
cmd->data_length);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_unmap;
|
|
|
}
|
|
|
/*
|
|
|
* Start processing the received transport IDs using the
|
|
@@ -1566,16 +1562,13 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
smp_mb__after_atomic_inc();
|
|
|
spin_unlock(&dev->se_port_lock);
|
|
|
|
|
|
- ret = core_scsi3_tpg_depend_item(tmp_tpg);
|
|
|
- if (ret != 0) {
|
|
|
+ if (core_scsi3_tpg_depend_item(tmp_tpg)) {
|
|
|
pr_err(" core_scsi3_tpg_depend_item()"
|
|
|
" for tmp_tpg\n");
|
|
|
atomic_dec(&tmp_tpg->tpg_pr_ref_count);
|
|
|
smp_mb__after_atomic_dec();
|
|
|
- cmd->scsi_sense_reason =
|
|
|
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ goto out_unmap;
|
|
|
}
|
|
|
/*
|
|
|
* Locate the destination initiator ACL to be registered
|
|
@@ -1597,17 +1590,14 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- ret = core_scsi3_nodeacl_depend_item(dest_node_acl);
|
|
|
- if (ret != 0) {
|
|
|
+ if (core_scsi3_nodeacl_depend_item(dest_node_acl)) {
|
|
|
pr_err("configfs_depend_item() failed"
|
|
|
" for dest_node_acl->acl_group\n");
|
|
|
atomic_dec(&dest_node_acl->acl_pr_ref_count);
|
|
|
smp_mb__after_atomic_dec();
|
|
|
core_scsi3_tpg_undepend_item(tmp_tpg);
|
|
|
- cmd->scsi_sense_reason =
|
|
|
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ goto out_unmap;
|
|
|
}
|
|
|
|
|
|
dest_tpg = tmp_tpg;
|
|
@@ -1624,9 +1614,8 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
if (!dest_tpg) {
|
|
|
pr_err("SPC-3 PR SPEC_I_PT: Unable to locate"
|
|
|
" dest_tpg\n");
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_unmap;
|
|
|
}
|
|
|
|
|
|
pr_debug("SPC-3 PR SPEC_I_PT: Got %s data_length: %u tpdl: %u"
|
|
@@ -1639,9 +1628,8 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
" %u for Transport ID: %s\n", tid_len, ptr);
|
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
|
core_scsi3_tpg_undepend_item(dest_tpg);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_unmap;
|
|
|
}
|
|
|
/*
|
|
|
* Locate the desintation struct se_dev_entry pointer for matching
|
|
@@ -1658,23 +1646,19 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
|
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
|
core_scsi3_tpg_undepend_item(dest_tpg);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_unmap;
|
|
|
}
|
|
|
|
|
|
- ret = core_scsi3_lunacl_depend_item(dest_se_deve);
|
|
|
- if (ret < 0) {
|
|
|
+ if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
|
|
|
pr_err("core_scsi3_lunacl_depend_item()"
|
|
|
" failed\n");
|
|
|
atomic_dec(&dest_se_deve->pr_ref_count);
|
|
|
smp_mb__after_atomic_dec();
|
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
|
core_scsi3_tpg_undepend_item(dest_tpg);
|
|
|
- cmd->scsi_sense_reason =
|
|
|
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ goto out_unmap;
|
|
|
}
|
|
|
|
|
|
pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s"
|
|
@@ -1710,10 +1694,8 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
core_scsi3_lunacl_undepend_item(dest_se_deve);
|
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
|
core_scsi3_tpg_undepend_item(dest_tpg);
|
|
|
- cmd->scsi_sense_reason =
|
|
|
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- ret = -ENOMEM;
|
|
|
- goto out;
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ goto out_unmap;
|
|
|
}
|
|
|
INIT_LIST_HEAD(&tidh_new->dest_list);
|
|
|
tidh_new->dest_tpg = dest_tpg;
|
|
@@ -1744,9 +1726,8 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
|
core_scsi3_tpg_undepend_item(dest_tpg);
|
|
|
kfree(tidh_new);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_unmap;
|
|
|
}
|
|
|
tidh_new->dest_pr_reg = dest_pr_reg;
|
|
|
list_add_tail(&tidh_new->dest_list, &tid_dest_list);
|
|
@@ -1804,8 +1785,9 @@ static int core_scsi3_decode_spec_i_port(
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
-out:
|
|
|
+out_unmap:
|
|
|
transport_kunmap_data_sg(cmd);
|
|
|
+out:
|
|
|
/*
|
|
|
* For the failure case, release everything from tid_dest_list
|
|
|
* including *dest_pr_reg and the configfs dependances..
|
|
@@ -2020,14 +2002,15 @@ static int __core_scsi3_write_aptpl_to_file(
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int core_scsi3_update_and_write_aptpl(
|
|
|
- struct se_device *dev,
|
|
|
- unsigned char *in_buf,
|
|
|
- u32 in_pr_aptpl_buf_len)
|
|
|
+static int
|
|
|
+core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf,
|
|
|
+ u32 in_pr_aptpl_buf_len)
|
|
|
{
|
|
|
unsigned char null_buf[64], *buf;
|
|
|
u32 pr_aptpl_buf_len;
|
|
|
- int ret, clear_aptpl_metadata = 0;
|
|
|
+ int clear_aptpl_metadata = 0;
|
|
|
+ int ret;
|
|
|
+
|
|
|
/*
|
|
|
* Can be called with a NULL pointer from PROUT service action CLEAR
|
|
|
*/
|
|
@@ -2049,25 +2032,17 @@ static int core_scsi3_update_and_write_aptpl(
|
|
|
clear_aptpl_metadata);
|
|
|
if (ret != 0)
|
|
|
return ret;
|
|
|
+
|
|
|
/*
|
|
|
* __core_scsi3_write_aptpl_to_file() will call strlen()
|
|
|
* on the passed buf to determine pr_aptpl_buf_len.
|
|
|
*/
|
|
|
- ret = __core_scsi3_write_aptpl_to_file(dev, buf, 0);
|
|
|
- if (ret != 0)
|
|
|
- return ret;
|
|
|
-
|
|
|
- return ret;
|
|
|
+ return __core_scsi3_write_aptpl_to_file(dev, buf, 0);
|
|
|
}
|
|
|
|
|
|
-static int core_scsi3_emulate_pro_register(
|
|
|
- struct se_cmd *cmd,
|
|
|
- u64 res_key,
|
|
|
- u64 sa_res_key,
|
|
|
- int aptpl,
|
|
|
- int all_tg_pt,
|
|
|
- int spec_i_pt,
|
|
|
- int ignore_key)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
|
|
|
+ int aptpl, int all_tg_pt, int spec_i_pt, int ignore_key)
|
|
|
{
|
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
@@ -2079,12 +2054,12 @@ static int core_scsi3_emulate_pro_register(
|
|
|
/* Used for APTPL metadata w/ UNREGISTER */
|
|
|
unsigned char *pr_aptpl_buf = NULL;
|
|
|
unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
|
|
|
- int pr_holder = 0, ret = 0, type;
|
|
|
+ sense_reason_t ret;
|
|
|
+ int pr_holder = 0, type;
|
|
|
|
|
|
if (!se_sess || !se_lun) {
|
|
|
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
se_tpg = se_sess->se_tpg;
|
|
|
se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
|
|
@@ -2103,8 +2078,7 @@ static int core_scsi3_emulate_pro_register(
|
|
|
if (res_key) {
|
|
|
pr_warn("SPC-3 PR: Reservation Key non-zero"
|
|
|
" for SA REGISTER, returning CONFLICT\n");
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
}
|
|
|
/*
|
|
|
* Do nothing but return GOOD status.
|
|
@@ -2118,15 +2092,13 @@ static int core_scsi3_emulate_pro_register(
|
|
|
* Port Endpoint that the PRO was received from on the
|
|
|
* Logical Unit of the SCSI device server.
|
|
|
*/
|
|
|
- ret = core_scsi3_alloc_registration(cmd->se_dev,
|
|
|
+ if (core_scsi3_alloc_registration(cmd->se_dev,
|
|
|
se_sess->se_node_acl, se_deve, isid_ptr,
|
|
|
sa_res_key, all_tg_pt, aptpl,
|
|
|
- ignore_key, 0);
|
|
|
- if (ret != 0) {
|
|
|
+ ignore_key, 0)) {
|
|
|
pr_err("Unable to allocate"
|
|
|
" struct t10_pr_registration\n");
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_INVALID_PARAMETER_LIST;
|
|
|
}
|
|
|
} else {
|
|
|
/*
|
|
@@ -2160,201 +2132,192 @@ static int core_scsi3_emulate_pro_register(
|
|
|
pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev,
|
|
|
se_sess->se_node_acl, se_sess);
|
|
|
|
|
|
- ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
+ if (core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
&pr_reg->pr_aptpl_buf[0],
|
|
|
- pr_tmpl->pr_aptpl_buf_len);
|
|
|
- if (!ret) {
|
|
|
+ pr_tmpl->pr_aptpl_buf_len)) {
|
|
|
pr_tmpl->pr_aptpl_active = 1;
|
|
|
pr_debug("SPC-3 PR: Set APTPL Bit Activated for REGISTER\n");
|
|
|
}
|
|
|
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- return ret;
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * Locate the existing *pr_reg via struct se_node_acl pointers
|
|
|
- */
|
|
|
- pr_reg = pr_reg_e;
|
|
|
- type = pr_reg->pr_res_type;
|
|
|
-
|
|
|
- if (!ignore_key) {
|
|
|
- if (res_key != pr_reg->pr_res_key) {
|
|
|
- pr_err("SPC-3 PR REGISTER: Received"
|
|
|
- " res_key: 0x%016Lx does not match"
|
|
|
- " existing SA REGISTER res_key:"
|
|
|
- " 0x%016Lx\n", res_key,
|
|
|
- pr_reg->pr_res_key);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
+ goto out_put_pr_reg;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Locate the existing *pr_reg via struct se_node_acl pointers
|
|
|
+ */
|
|
|
+ pr_reg = pr_reg_e;
|
|
|
+ type = pr_reg->pr_res_type;
|
|
|
+
|
|
|
+ if (!ignore_key) {
|
|
|
+ if (res_key != pr_reg->pr_res_key) {
|
|
|
+ pr_err("SPC-3 PR REGISTER: Received"
|
|
|
+ " res_key: 0x%016Lx does not match"
|
|
|
+ " existing SA REGISTER res_key:"
|
|
|
+ " 0x%016Lx\n", res_key,
|
|
|
+ pr_reg->pr_res_key);
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
- if (spec_i_pt) {
|
|
|
- pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT"
|
|
|
- " set while sa_res_key=0\n");
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (spec_i_pt) {
|
|
|
+ pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT"
|
|
|
+ " set while sa_res_key=0\n");
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_put_pr_reg;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * An existing ALL_TG_PT=1 registration being released
|
|
|
+ * must also set ALL_TG_PT=1 in the incoming PROUT.
|
|
|
+ */
|
|
|
+ if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) {
|
|
|
+ pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1"
|
|
|
+ " registration exists, but ALL_TG_PT=1 bit not"
|
|
|
+ " present in received PROUT\n");
|
|
|
+ ret = TCM_INVALID_CDB_FIELD;
|
|
|
+ goto out_put_pr_reg;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Allocate APTPL metadata buffer used for UNREGISTER ops
|
|
|
+ */
|
|
|
+ if (aptpl) {
|
|
|
+ pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len,
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!pr_aptpl_buf) {
|
|
|
+ pr_err("Unable to allocate"
|
|
|
+ " pr_aptpl_buf\n");
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
- /*
|
|
|
- * An existing ALL_TG_PT=1 registration being released
|
|
|
- * must also set ALL_TG_PT=1 in the incoming PROUT.
|
|
|
- */
|
|
|
- if (pr_reg->pr_reg_all_tg_pt && !(all_tg_pt)) {
|
|
|
- pr_err("SPC-3 PR UNREGISTER: ALL_TG_PT=1"
|
|
|
- " registration exists, but ALL_TG_PT=1 bit not"
|
|
|
- " present in received PROUT\n");
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * sa_res_key=0 Unregister Reservation Key for registered I_T
|
|
|
+ * Nexus sa_res_key=1 Change Reservation Key for registered I_T
|
|
|
+ * Nexus.
|
|
|
+ */
|
|
|
+ if (!sa_res_key) {
|
|
|
+ pr_holder = core_scsi3_check_implict_release(
|
|
|
+ cmd->se_dev, pr_reg);
|
|
|
+ if (pr_holder < 0) {
|
|
|
+ kfree(pr_aptpl_buf);
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
+
|
|
|
+ spin_lock(&pr_tmpl->registration_lock);
|
|
|
/*
|
|
|
- * Allocate APTPL metadata buffer used for UNREGISTER ops
|
|
|
+ * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port
|
|
|
+ * and matching pr_res_key.
|
|
|
*/
|
|
|
- if (aptpl) {
|
|
|
- pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len,
|
|
|
- GFP_KERNEL);
|
|
|
- if (!pr_aptpl_buf) {
|
|
|
- pr_err("Unable to allocate"
|
|
|
- " pr_aptpl_buf\n");
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason =
|
|
|
- TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ if (pr_reg->pr_reg_all_tg_pt) {
|
|
|
+ list_for_each_entry_safe(pr_reg_p, pr_reg_tmp,
|
|
|
+ &pr_tmpl->registration_list,
|
|
|
+ pr_reg_list) {
|
|
|
+
|
|
|
+ if (!pr_reg_p->pr_reg_all_tg_pt)
|
|
|
+ continue;
|
|
|
+ if (pr_reg_p->pr_res_key != res_key)
|
|
|
+ continue;
|
|
|
+ if (pr_reg == pr_reg_p)
|
|
|
+ continue;
|
|
|
+ if (strcmp(pr_reg->pr_reg_nacl->initiatorname,
|
|
|
+ pr_reg_p->pr_reg_nacl->initiatorname))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ __core_scsi3_free_registration(dev,
|
|
|
+ pr_reg_p, NULL, 0);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
/*
|
|
|
- * sa_res_key=0 Unregister Reservation Key for registered I_T
|
|
|
- * Nexus sa_res_key=1 Change Reservation Key for registered I_T
|
|
|
- * Nexus.
|
|
|
+ * Release the calling I_T Nexus registration now..
|
|
|
*/
|
|
|
- if (!sa_res_key) {
|
|
|
- pr_holder = core_scsi3_check_implict_release(
|
|
|
- cmd->se_dev, pr_reg);
|
|
|
- if (pr_holder < 0) {
|
|
|
- kfree(pr_aptpl_buf);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
-
|
|
|
- spin_lock(&pr_tmpl->registration_lock);
|
|
|
- /*
|
|
|
- * Release all ALL_TG_PT=1 for the matching SCSI Initiator Port
|
|
|
- * and matching pr_res_key.
|
|
|
- */
|
|
|
- if (pr_reg->pr_reg_all_tg_pt) {
|
|
|
- list_for_each_entry_safe(pr_reg_p, pr_reg_tmp,
|
|
|
- &pr_tmpl->registration_list,
|
|
|
- pr_reg_list) {
|
|
|
-
|
|
|
- if (!pr_reg_p->pr_reg_all_tg_pt)
|
|
|
- continue;
|
|
|
+ __core_scsi3_free_registration(cmd->se_dev, pr_reg, NULL, 1);
|
|
|
|
|
|
- if (pr_reg_p->pr_res_key != res_key)
|
|
|
- continue;
|
|
|
-
|
|
|
- if (pr_reg == pr_reg_p)
|
|
|
- continue;
|
|
|
-
|
|
|
- if (strcmp(pr_reg->pr_reg_nacl->initiatorname,
|
|
|
- pr_reg_p->pr_reg_nacl->initiatorname))
|
|
|
- continue;
|
|
|
-
|
|
|
- __core_scsi3_free_registration(dev,
|
|
|
- pr_reg_p, NULL, 0);
|
|
|
- }
|
|
|
- }
|
|
|
- /*
|
|
|
- * Release the calling I_T Nexus registration now..
|
|
|
- */
|
|
|
- __core_scsi3_free_registration(cmd->se_dev, pr_reg,
|
|
|
- NULL, 1);
|
|
|
- /*
|
|
|
- * From spc4r17, section 5.7.11.3 Unregistering
|
|
|
- *
|
|
|
- * If the persistent reservation is a registrants only
|
|
|
- * type, the device server shall establish a unit
|
|
|
- * attention condition for the initiator port associated
|
|
|
- * with every registered I_T nexus except for the I_T
|
|
|
- * nexus on which the PERSISTENT RESERVE OUT command was
|
|
|
- * received, with the additional sense code set to
|
|
|
- * RESERVATIONS RELEASED.
|
|
|
- */
|
|
|
- if (pr_holder &&
|
|
|
- ((type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) ||
|
|
|
- (type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY))) {
|
|
|
- list_for_each_entry(pr_reg_p,
|
|
|
- &pr_tmpl->registration_list,
|
|
|
- pr_reg_list) {
|
|
|
-
|
|
|
- core_scsi3_ua_allocate(
|
|
|
- pr_reg_p->pr_reg_nacl,
|
|
|
- pr_reg_p->pr_res_mapped_lun,
|
|
|
- 0x2A,
|
|
|
- ASCQ_2AH_RESERVATIONS_RELEASED);
|
|
|
- }
|
|
|
+ /*
|
|
|
+ * From spc4r17, section 5.7.11.3 Unregistering
|
|
|
+ *
|
|
|
+ * If the persistent reservation is a registrants only
|
|
|
+ * type, the device server shall establish a unit
|
|
|
+ * attention condition for the initiator port associated
|
|
|
+ * with every registered I_T nexus except for the I_T
|
|
|
+ * nexus on which the PERSISTENT RESERVE OUT command was
|
|
|
+ * received, with the additional sense code set to
|
|
|
+ * RESERVATIONS RELEASED.
|
|
|
+ */
|
|
|
+ if (pr_holder &&
|
|
|
+ (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY ||
|
|
|
+ type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) {
|
|
|
+ list_for_each_entry(pr_reg_p,
|
|
|
+ &pr_tmpl->registration_list,
|
|
|
+ pr_reg_list) {
|
|
|
+
|
|
|
+ core_scsi3_ua_allocate(
|
|
|
+ pr_reg_p->pr_reg_nacl,
|
|
|
+ pr_reg_p->pr_res_mapped_lun,
|
|
|
+ 0x2A,
|
|
|
+ ASCQ_2AH_RESERVATIONS_RELEASED);
|
|
|
}
|
|
|
- spin_unlock(&pr_tmpl->registration_lock);
|
|
|
+ }
|
|
|
+ spin_unlock(&pr_tmpl->registration_lock);
|
|
|
|
|
|
- if (!aptpl) {
|
|
|
- pr_tmpl->pr_aptpl_active = 0;
|
|
|
- core_scsi3_update_and_write_aptpl(dev, NULL, 0);
|
|
|
- pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
|
|
|
- " for UNREGISTER\n");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ if (!aptpl) {
|
|
|
+ pr_tmpl->pr_aptpl_active = 0;
|
|
|
+ core_scsi3_update_and_write_aptpl(dev, NULL, 0);
|
|
|
+ pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
|
|
|
+ " for UNREGISTER\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- ret = core_scsi3_update_and_write_aptpl(dev,
|
|
|
- &pr_aptpl_buf[0],
|
|
|
- pr_tmpl->pr_aptpl_buf_len);
|
|
|
- if (!ret) {
|
|
|
- pr_tmpl->pr_aptpl_active = 1;
|
|
|
- pr_debug("SPC-3 PR: Set APTPL Bit Activated"
|
|
|
- " for UNREGISTER\n");
|
|
|
- }
|
|
|
+ if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0],
|
|
|
+ pr_tmpl->pr_aptpl_buf_len)) {
|
|
|
+ pr_tmpl->pr_aptpl_active = 1;
|
|
|
+ pr_debug("SPC-3 PR: Set APTPL Bit Activated"
|
|
|
+ " for UNREGISTER\n");
|
|
|
+ }
|
|
|
|
|
|
- kfree(pr_aptpl_buf);
|
|
|
- return ret;
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * Increment PRgeneration counter for struct se_device"
|
|
|
- * upon a successful REGISTER, see spc4r17 section 6.3.2
|
|
|
- * READ_KEYS service action.
|
|
|
- */
|
|
|
- pr_reg->pr_res_generation = core_scsi3_pr_generation(
|
|
|
- cmd->se_dev);
|
|
|
- pr_reg->pr_res_key = sa_res_key;
|
|
|
- pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
|
|
|
- " Key for %s to: 0x%016Lx PRgeneration:"
|
|
|
- " 0x%08x\n", cmd->se_tfo->get_fabric_name(),
|
|
|
- (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "",
|
|
|
- pr_reg->pr_reg_nacl->initiatorname,
|
|
|
- pr_reg->pr_res_key, pr_reg->pr_res_generation);
|
|
|
-
|
|
|
- if (!aptpl) {
|
|
|
- pr_tmpl->pr_aptpl_active = 0;
|
|
|
- core_scsi3_update_and_write_aptpl(dev, NULL, 0);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
|
|
|
- " for REGISTER\n");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ goto out_free_aptpl_buf;
|
|
|
+ }
|
|
|
|
|
|
- ret = core_scsi3_update_and_write_aptpl(dev,
|
|
|
- &pr_aptpl_buf[0],
|
|
|
- pr_tmpl->pr_aptpl_buf_len);
|
|
|
- if (!ret) {
|
|
|
- pr_tmpl->pr_aptpl_active = 1;
|
|
|
- pr_debug("SPC-3 PR: Set APTPL Bit Activated"
|
|
|
- " for REGISTER\n");
|
|
|
- }
|
|
|
+ /*
|
|
|
+ * Increment PRgeneration counter for struct se_device"
|
|
|
+ * upon a successful REGISTER, see spc4r17 section 6.3.2
|
|
|
+ * READ_KEYS service action.
|
|
|
+ */
|
|
|
+ pr_reg->pr_res_generation = core_scsi3_pr_generation(cmd->se_dev);
|
|
|
+ pr_reg->pr_res_key = sa_res_key;
|
|
|
+ pr_debug("SPC-3 PR [%s] REGISTER%s: Changed Reservation"
|
|
|
+ " Key for %s to: 0x%016Lx PRgeneration:"
|
|
|
+ " 0x%08x\n", cmd->se_tfo->get_fabric_name(),
|
|
|
+ (ignore_key) ? "_AND_IGNORE_EXISTING_KEY" : "",
|
|
|
+ pr_reg->pr_reg_nacl->initiatorname,
|
|
|
+ pr_reg->pr_res_key, pr_reg->pr_res_generation);
|
|
|
|
|
|
- kfree(pr_aptpl_buf);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- }
|
|
|
+ if (!aptpl) {
|
|
|
+ pr_tmpl->pr_aptpl_active = 0;
|
|
|
+ core_scsi3_update_and_write_aptpl(dev, NULL, 0);
|
|
|
+ pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
|
|
|
+ " for REGISTER\n");
|
|
|
+ ret = 0;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
- return 0;
|
|
|
+
|
|
|
+ if (!core_scsi3_update_and_write_aptpl(dev, &pr_aptpl_buf[0],
|
|
|
+ pr_tmpl->pr_aptpl_buf_len)) {
|
|
|
+ pr_tmpl->pr_aptpl_active = 1;
|
|
|
+ pr_debug("SPC-3 PR: Set APTPL Bit Activated"
|
|
|
+ " for REGISTER\n");
|
|
|
+ }
|
|
|
+
|
|
|
+out_free_aptpl_buf:
|
|
|
+ kfree(pr_aptpl_buf);
|
|
|
+ ret = 0;
|
|
|
+out_put_pr_reg:
|
|
|
+ core_scsi3_put_pr_reg(pr_reg);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
unsigned char *core_scsi3_pr_dump_type(int type)
|
|
@@ -2379,26 +2342,23 @@ unsigned char *core_scsi3_pr_dump_type(int type)
|
|
|
return "Unknown SPC-3 PR Type";
|
|
|
}
|
|
|
|
|
|
-static int core_scsi3_pro_reserve(
|
|
|
- struct se_cmd *cmd,
|
|
|
- struct se_device *dev,
|
|
|
- int type,
|
|
|
- int scope,
|
|
|
- u64 res_key)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
|
|
|
{
|
|
|
+ struct se_device *dev = cmd->se_dev;
|
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
|
struct se_lun *se_lun = cmd->se_lun;
|
|
|
struct t10_pr_registration *pr_reg, *pr_res_holder;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
|
char i_buf[PR_REG_ISID_ID_LEN];
|
|
|
- int ret, prf_isid;
|
|
|
+ sense_reason_t ret;
|
|
|
+ int prf_isid;
|
|
|
|
|
|
memset(i_buf, 0, PR_REG_ISID_ID_LEN);
|
|
|
|
|
|
if (!se_sess || !se_lun) {
|
|
|
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
/*
|
|
|
* Locate the existing *pr_reg via struct se_node_acl pointers
|
|
@@ -2408,8 +2368,7 @@ static int core_scsi3_pro_reserve(
|
|
|
if (!pr_reg) {
|
|
|
pr_err("SPC-3 PR: Unable to locate"
|
|
|
" PR_REGISTERED *pr_reg for RESERVE\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
/*
|
|
|
* From spc4r17 Section 5.7.9: Reserving:
|
|
@@ -2424,9 +2383,8 @@ static int core_scsi3_pro_reserve(
|
|
|
pr_err("SPC-3 PR RESERVE: Received res_key: 0x%016Lx"
|
|
|
" does not match existing SA REGISTER res_key:"
|
|
|
" 0x%016Lx\n", res_key, pr_reg->pr_res_key);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
/*
|
|
|
* From spc4r17 Section 5.7.9: Reserving:
|
|
@@ -2440,9 +2398,8 @@ static int core_scsi3_pro_reserve(
|
|
|
*/
|
|
|
if (scope != PR_SCOPE_LU_SCOPE) {
|
|
|
pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
/*
|
|
|
* See if we have an existing PR reservation holder pointer at
|
|
@@ -2473,9 +2430,8 @@ static int core_scsi3_pro_reserve(
|
|
|
pr_res_holder->pr_reg_nacl->initiatorname);
|
|
|
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
/*
|
|
|
* From spc4r17 Section 5.7.9: Reserving:
|
|
@@ -2497,9 +2453,8 @@ static int core_scsi3_pro_reserve(
|
|
|
pr_res_holder->pr_reg_nacl->initiatorname);
|
|
|
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
/*
|
|
|
* From spc4r17 Section 5.7.9: Reserving:
|
|
@@ -2512,8 +2467,8 @@ static int core_scsi3_pro_reserve(
|
|
|
* shall completethe command with GOOD status.
|
|
|
*/
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- return 0;
|
|
|
+ ret = 0;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
/*
|
|
|
* Otherwise, our *pr_reg becomes the PR reservation holder for said
|
|
@@ -2537,27 +2492,24 @@ static int core_scsi3_pro_reserve(
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
|
|
|
if (pr_tmpl->pr_aptpl_active) {
|
|
|
- ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
+ if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
&pr_reg->pr_aptpl_buf[0],
|
|
|
- pr_tmpl->pr_aptpl_buf_len);
|
|
|
- if (!ret)
|
|
|
+ pr_tmpl->pr_aptpl_buf_len)) {
|
|
|
pr_debug("SPC-3 PR: Updated APTPL metadata"
|
|
|
" for RESERVE\n");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ ret = 0;
|
|
|
+out_put_pr_reg:
|
|
|
core_scsi3_put_pr_reg(pr_reg);
|
|
|
- return 0;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-static int core_scsi3_emulate_pro_reserve(
|
|
|
- struct se_cmd *cmd,
|
|
|
- int type,
|
|
|
- int scope,
|
|
|
- u64 res_key)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_emulate_pro_reserve(struct se_cmd *cmd, int type, int scope,
|
|
|
+ u64 res_key)
|
|
|
{
|
|
|
- struct se_device *dev = cmd->se_dev;
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
switch (type) {
|
|
|
case PR_TYPE_WRITE_EXCLUSIVE:
|
|
|
case PR_TYPE_EXCLUSIVE_ACCESS:
|
|
@@ -2565,16 +2517,12 @@ static int core_scsi3_emulate_pro_reserve(
|
|
|
case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY:
|
|
|
case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
|
|
|
case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG:
|
|
|
- ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key);
|
|
|
- break;
|
|
|
+ return core_scsi3_pro_reserve(cmd, type, scope, res_key);
|
|
|
default:
|
|
|
pr_err("SPC-3 PR: Unknown Service Action RESERVE Type:"
|
|
|
" 0x%02x\n", type);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
|
}
|
|
|
-
|
|
|
- return ret;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -2612,23 +2560,21 @@ static void __core_scsi3_complete_pro_release(
|
|
|
pr_reg->pr_res_holder = pr_reg->pr_res_type = pr_reg->pr_res_scope = 0;
|
|
|
}
|
|
|
|
|
|
-static int core_scsi3_emulate_pro_release(
|
|
|
- struct se_cmd *cmd,
|
|
|
- int type,
|
|
|
- int scope,
|
|
|
- u64 res_key)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
|
|
|
+ u64 res_key)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
|
struct se_lun *se_lun = cmd->se_lun;
|
|
|
struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_res_holder;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
|
- int ret, all_reg = 0;
|
|
|
+ int all_reg = 0;
|
|
|
+ sense_reason_t ret = 0;
|
|
|
|
|
|
if (!se_sess || !se_lun) {
|
|
|
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
/*
|
|
|
* Locate the existing *pr_reg via struct se_node_acl pointers
|
|
@@ -2637,8 +2583,7 @@ static int core_scsi3_emulate_pro_release(
|
|
|
if (!pr_reg) {
|
|
|
pr_err("SPC-3 PR: Unable to locate"
|
|
|
" PR_REGISTERED *pr_reg for RELEASE\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
/*
|
|
|
* From spc4r17 Section 5.7.11.2 Releasing:
|
|
@@ -2659,7 +2604,6 @@ static int core_scsi3_emulate_pro_release(
|
|
|
* No persistent reservation, return GOOD status.
|
|
|
*/
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
return 0;
|
|
|
}
|
|
|
if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
|
|
@@ -2673,9 +2617,9 @@ static int core_scsi3_emulate_pro_release(
|
|
|
* persistent reservation holder. return GOOD status.
|
|
|
*/
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- return 0;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
+
|
|
|
/*
|
|
|
* From spc4r17 Section 5.7.11.2 Releasing:
|
|
|
*
|
|
@@ -2695,9 +2639,8 @@ static int core_scsi3_emulate_pro_release(
|
|
|
" does not match existing SA REGISTER res_key:"
|
|
|
" 0x%016Lx\n", res_key, pr_reg->pr_res_key);
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
/*
|
|
|
* From spc4r17 Section 5.7.11.2 Releasing and above:
|
|
@@ -2718,9 +2661,8 @@ static int core_scsi3_emulate_pro_release(
|
|
|
pr_res_holder->pr_reg_nacl->initiatorname);
|
|
|
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
/*
|
|
|
* In response to a persistent reservation release request from the
|
|
@@ -2773,20 +2715,18 @@ static int core_scsi3_emulate_pro_release(
|
|
|
|
|
|
write_aptpl:
|
|
|
if (pr_tmpl->pr_aptpl_active) {
|
|
|
- ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
- &pr_reg->pr_aptpl_buf[0],
|
|
|
- pr_tmpl->pr_aptpl_buf_len);
|
|
|
- if (!ret)
|
|
|
+ if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
+ &pr_reg->pr_aptpl_buf[0], pr_tmpl->pr_aptpl_buf_len)) {
|
|
|
pr_debug("SPC-3 PR: Updated APTPL metadata for RELEASE\n");
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
+out_put_pr_reg:
|
|
|
core_scsi3_put_pr_reg(pr_reg);
|
|
|
- return 0;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-static int core_scsi3_emulate_pro_clear(
|
|
|
- struct se_cmd *cmd,
|
|
|
- u64 res_key)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_node_acl *pr_reg_nacl;
|
|
@@ -2803,8 +2743,7 @@ static int core_scsi3_emulate_pro_clear(
|
|
|
if (!pr_reg_n) {
|
|
|
pr_err("SPC-3 PR: Unable to locate"
|
|
|
" PR_REGISTERED *pr_reg for CLEAR\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
/*
|
|
|
* From spc4r17 section 5.7.11.6, Clearing:
|
|
@@ -2823,8 +2762,7 @@ static int core_scsi3_emulate_pro_clear(
|
|
|
" existing SA REGISTER res_key:"
|
|
|
" 0x%016Lx\n", res_key, pr_reg_n->pr_res_key);
|
|
|
core_scsi3_put_pr_reg(pr_reg_n);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
}
|
|
|
/*
|
|
|
* a) Release the persistent reservation, if any;
|
|
@@ -2948,13 +2886,9 @@ static void core_scsi3_release_preempt_and_abort(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int core_scsi3_pro_preempt(
|
|
|
- struct se_cmd *cmd,
|
|
|
- int type,
|
|
|
- int scope,
|
|
|
- u64 res_key,
|
|
|
- u64 sa_res_key,
|
|
|
- int abort)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
|
|
|
+ u64 sa_res_key, int abort)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_node_acl *pr_reg_nacl;
|
|
@@ -2964,12 +2898,10 @@ static int core_scsi3_pro_preempt(
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
|
u32 pr_res_mapped_lun = 0;
|
|
|
int all_reg = 0, calling_it_nexus = 0, released_regs = 0;
|
|
|
- int prh_type = 0, prh_scope = 0, ret;
|
|
|
+ int prh_type = 0, prh_scope = 0;
|
|
|
|
|
|
- if (!se_sess) {
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
+ if (!se_sess)
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
|
|
|
pr_reg_n = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
|
|
|
se_sess);
|
|
@@ -2977,19 +2909,16 @@ static int core_scsi3_pro_preempt(
|
|
|
pr_err("SPC-3 PR: Unable to locate"
|
|
|
" PR_REGISTERED *pr_reg for PREEMPT%s\n",
|
|
|
(abort) ? "_AND_ABORT" : "");
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
}
|
|
|
if (pr_reg_n->pr_res_key != res_key) {
|
|
|
core_scsi3_put_pr_reg(pr_reg_n);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
}
|
|
|
if (scope != PR_SCOPE_LU_SCOPE) {
|
|
|
pr_err("SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
|
|
|
core_scsi3_put_pr_reg(pr_reg_n);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_INVALID_PARAMETER_LIST;
|
|
|
}
|
|
|
|
|
|
spin_lock(&dev->dev_reservation_lock);
|
|
@@ -3002,8 +2931,7 @@ static int core_scsi3_pro_preempt(
|
|
|
if (!all_reg && !sa_res_key) {
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
core_scsi3_put_pr_reg(pr_reg_n);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_INVALID_PARAMETER_LIST;
|
|
|
}
|
|
|
/*
|
|
|
* From spc4r17, section 5.7.11.4.4 Removing Registrations:
|
|
@@ -3097,8 +3025,7 @@ static int core_scsi3_pro_preempt(
|
|
|
if (!released_regs) {
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
core_scsi3_put_pr_reg(pr_reg_n);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
}
|
|
|
/*
|
|
|
* For an existing all registrants type reservation
|
|
@@ -3117,13 +3044,13 @@ static int core_scsi3_pro_preempt(
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
|
|
|
if (pr_tmpl->pr_aptpl_active) {
|
|
|
- ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
+ if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
&pr_reg_n->pr_aptpl_buf[0],
|
|
|
- pr_tmpl->pr_aptpl_buf_len);
|
|
|
- if (!ret)
|
|
|
+ pr_tmpl->pr_aptpl_buf_len)) {
|
|
|
pr_debug("SPC-3 PR: Updated APTPL"
|
|
|
" metadata for PREEMPT%s\n", (abort) ?
|
|
|
"_AND_ABORT" : "");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
core_scsi3_put_pr_reg(pr_reg_n);
|
|
@@ -3253,12 +3180,12 @@ static int core_scsi3_pro_preempt(
|
|
|
}
|
|
|
|
|
|
if (pr_tmpl->pr_aptpl_active) {
|
|
|
- ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
+ if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
&pr_reg_n->pr_aptpl_buf[0],
|
|
|
- pr_tmpl->pr_aptpl_buf_len);
|
|
|
- if (!ret)
|
|
|
+ pr_tmpl->pr_aptpl_buf_len)) {
|
|
|
pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT"
|
|
|
- "%s\n", (abort) ? "_AND_ABORT" : "");
|
|
|
+ "%s\n", abort ? "_AND_ABORT" : "");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
core_scsi3_put_pr_reg(pr_reg_n);
|
|
@@ -3266,16 +3193,10 @@ static int core_scsi3_pro_preempt(
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int core_scsi3_emulate_pro_preempt(
|
|
|
- struct se_cmd *cmd,
|
|
|
- int type,
|
|
|
- int scope,
|
|
|
- u64 res_key,
|
|
|
- u64 sa_res_key,
|
|
|
- int abort)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope,
|
|
|
+ u64 res_key, u64 sa_res_key, int abort)
|
|
|
{
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
switch (type) {
|
|
|
case PR_TYPE_WRITE_EXCLUSIVE:
|
|
|
case PR_TYPE_EXCLUSIVE_ACCESS:
|
|
@@ -3283,26 +3204,19 @@ static int core_scsi3_emulate_pro_preempt(
|
|
|
case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY:
|
|
|
case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
|
|
|
case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG:
|
|
|
- ret = core_scsi3_pro_preempt(cmd, type, scope,
|
|
|
- res_key, sa_res_key, abort);
|
|
|
- break;
|
|
|
+ return core_scsi3_pro_preempt(cmd, type, scope, res_key,
|
|
|
+ sa_res_key, abort);
|
|
|
default:
|
|
|
pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s"
|
|
|
" Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
|
}
|
|
|
-
|
|
|
- return ret;
|
|
|
}
|
|
|
|
|
|
|
|
|
-static int core_scsi3_emulate_pro_register_and_move(
|
|
|
- struct se_cmd *cmd,
|
|
|
- u64 res_key,
|
|
|
- u64 sa_res_key,
|
|
|
- int aptpl,
|
|
|
- int unreg)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
|
|
|
+ u64 sa_res_key, int aptpl, int unreg)
|
|
|
{
|
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
@@ -3318,15 +3232,16 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
unsigned char *initiator_str;
|
|
|
char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN];
|
|
|
u32 tid_len, tmp_tid_len;
|
|
|
- int new_reg = 0, type, scope, ret, matching_iname, prf_isid;
|
|
|
+ int new_reg = 0, type, scope, matching_iname, prf_isid;
|
|
|
+ sense_reason_t ret;
|
|
|
unsigned short rtpi;
|
|
|
unsigned char proto_ident;
|
|
|
|
|
|
if (!se_sess || !se_lun) {
|
|
|
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
+
|
|
|
memset(dest_iport, 0, 64);
|
|
|
memset(i_buf, 0, PR_REG_ISID_ID_LEN);
|
|
|
se_tpg = se_sess->se_tpg;
|
|
@@ -3342,8 +3257,7 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
if (!pr_reg) {
|
|
|
pr_err("SPC-3 PR: Unable to locate PR_REGISTERED"
|
|
|
" *pr_reg for REGISTER_AND_MOVE\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
|
/*
|
|
|
* The provided reservation key much match the existing reservation key
|
|
@@ -3353,9 +3267,8 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received"
|
|
|
" res_key: 0x%016Lx does not match existing SA REGISTER"
|
|
|
" res_key: 0x%016Lx\n", res_key, pr_reg->pr_res_key);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
/*
|
|
|
* The service active reservation key needs to be non zero
|
|
@@ -3363,9 +3276,8 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
if (!sa_res_key) {
|
|
|
pr_warn("SPC-3 PR REGISTER_AND_MOVE: Received zero"
|
|
|
" sa_res_key\n");
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -3374,6 +3286,11 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
* information.
|
|
|
*/
|
|
|
buf = transport_kmap_data_sg(cmd);
|
|
|
+ if (!buf) {
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ goto out_put_pr_reg;
|
|
|
+ }
|
|
|
+
|
|
|
rtpi = (buf[18] & 0xff) << 8;
|
|
|
rtpi |= buf[19] & 0xff;
|
|
|
tid_len = (buf[20] & 0xff) << 24;
|
|
@@ -3387,9 +3304,8 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
pr_err("SPC-3 PR: Illegal tid_len: %u + 24 byte header"
|
|
|
" does not equal CDB data_length: %u\n", tid_len,
|
|
|
cmd->data_length);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
|
|
|
spin_lock(&dev->se_port_lock);
|
|
@@ -3407,15 +3323,13 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
smp_mb__after_atomic_inc();
|
|
|
spin_unlock(&dev->se_port_lock);
|
|
|
|
|
|
- ret = core_scsi3_tpg_depend_item(dest_se_tpg);
|
|
|
- if (ret != 0) {
|
|
|
+ if (core_scsi3_tpg_depend_item(dest_se_tpg)) {
|
|
|
pr_err("core_scsi3_tpg_depend_item() failed"
|
|
|
" for dest_se_tpg\n");
|
|
|
atomic_dec(&dest_se_tpg->tpg_pr_ref_count);
|
|
|
smp_mb__after_atomic_dec();
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
|
|
|
spin_lock(&dev->se_port_lock);
|
|
@@ -3427,12 +3341,15 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
|
|
|
" fabric ops from Relative Target Port Identifier:"
|
|
|
" %hu\n", rtpi);
|
|
|
- core_scsi3_put_pr_reg(pr_reg);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- return -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
+ goto out_put_pr_reg;
|
|
|
}
|
|
|
|
|
|
buf = transport_kmap_data_sg(cmd);
|
|
|
+ if (!buf) {
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+ goto out_put_pr_reg;
|
|
|
+ }
|
|
|
proto_ident = (buf[24] & 0x0f);
|
|
|
|
|
|
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
|
|
@@ -3444,16 +3361,14 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
" from fabric: %s\n", proto_ident,
|
|
|
dest_tf_ops->get_fabric_proto_ident(dest_se_tpg),
|
|
|
dest_tf_ops->get_fabric_name());
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
|
}
|
|
|
if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) {
|
|
|
pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not"
|
|
|
" containg a valid tpg_parse_pr_out_transport_id"
|
|
|
" function pointer\n");
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
goto out;
|
|
|
}
|
|
|
initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg,
|
|
@@ -3461,8 +3376,7 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
if (!initiator_str) {
|
|
|
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
|
|
|
" initiator_str from Transport ID\n");
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -3491,8 +3405,7 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
pr_err("SPC-3 PR REGISTER_AND_MOVE: TransportID: %s"
|
|
|
" matches: %s on received I_T Nexus\n", initiator_str,
|
|
|
pr_reg_nacl->initiatorname);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
|
}
|
|
|
if (!strcmp(iport_ptr, pr_reg->pr_reg_isid)) {
|
|
@@ -3500,8 +3413,7 @@ static int core_scsi3_emulate_pro_register_and_move(
|
|
|
" matches: %s %s on received I_T Nexus\n",
|
|
|
initiator_str, iport_ptr, pr_reg_nacl->initiatorname,
|
|
|
pr_reg->pr_reg_isid);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
|
}
|
|
|
after_iport_check:
|
|
@@ -3521,19 +3433,17 @@ after_iport_check:
|
|
|
pr_err("Unable to locate %s dest_node_acl for"
|
|
|
" TransportID%s\n", dest_tf_ops->get_fabric_name(),
|
|
|
initiator_str);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
|
}
|
|
|
- ret = core_scsi3_nodeacl_depend_item(dest_node_acl);
|
|
|
- if (ret != 0) {
|
|
|
+
|
|
|
+ if (core_scsi3_nodeacl_depend_item(dest_node_acl)) {
|
|
|
pr_err("core_scsi3_nodeacl_depend_item() for"
|
|
|
" dest_node_acl\n");
|
|
|
atomic_dec(&dest_node_acl->acl_pr_ref_count);
|
|
|
smp_mb__after_atomic_dec();
|
|
|
dest_node_acl = NULL;
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -3549,19 +3459,16 @@ after_iport_check:
|
|
|
if (!dest_se_deve) {
|
|
|
pr_err("Unable to locate %s dest_se_deve from RTPI:"
|
|
|
" %hu\n", dest_tf_ops->get_fabric_name(), rtpi);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- ret = core_scsi3_lunacl_depend_item(dest_se_deve);
|
|
|
- if (ret < 0) {
|
|
|
+ if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
|
|
|
pr_err("core_scsi3_lunacl_depend_item() failed\n");
|
|
|
atomic_dec(&dest_se_deve->pr_ref_count);
|
|
|
smp_mb__after_atomic_dec();
|
|
|
dest_se_deve = NULL;
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -3580,8 +3487,7 @@ after_iport_check:
|
|
|
pr_warn("SPC-3 PR REGISTER_AND_MOVE: No reservation"
|
|
|
" currently held\n");
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_CDB_FIELD;
|
|
|
goto out;
|
|
|
}
|
|
|
/*
|
|
@@ -3594,8 +3500,7 @@ after_iport_check:
|
|
|
pr_warn("SPC-3 PR REGISTER_AND_MOVE: Calling I_T"
|
|
|
" Nexus is not reservation holder\n");
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
goto out;
|
|
|
}
|
|
|
/*
|
|
@@ -3613,8 +3518,7 @@ after_iport_check:
|
|
|
" reservation for type: %s\n",
|
|
|
core_scsi3_pr_dump_type(pr_res_holder->pr_res_type));
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_RESERVATION_CONFLICT;
|
|
|
goto out;
|
|
|
}
|
|
|
pr_res_nacl = pr_res_holder->pr_reg_nacl;
|
|
@@ -3646,13 +3550,11 @@ after_iport_check:
|
|
|
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
|
|
|
iport_ptr);
|
|
|
if (!dest_pr_reg) {
|
|
|
- ret = core_scsi3_alloc_registration(cmd->se_dev,
|
|
|
+ if (core_scsi3_alloc_registration(cmd->se_dev,
|
|
|
dest_node_acl, dest_se_deve, iport_ptr,
|
|
|
- sa_res_key, 0, aptpl, 2, 1);
|
|
|
- if (ret != 0) {
|
|
|
+ sa_res_key, 0, aptpl, 2, 1)) {
|
|
|
spin_unlock(&dev->dev_reservation_lock);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
+ ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
|
}
|
|
|
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
|
|
@@ -3723,12 +3625,12 @@ after_iport_check:
|
|
|
" REGISTER_AND_MOVE\n");
|
|
|
} else {
|
|
|
pr_tmpl->pr_aptpl_active = 1;
|
|
|
- ret = core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
+ if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
|
|
|
&dest_pr_reg->pr_aptpl_buf[0],
|
|
|
- pr_tmpl->pr_aptpl_buf_len);
|
|
|
- if (!ret)
|
|
|
+ pr_tmpl->pr_aptpl_buf_len)) {
|
|
|
pr_debug("SPC-3 PR: Set APTPL Bit Activated for"
|
|
|
" REGISTER_AND_MOVE\n");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
transport_kunmap_data_sg(cmd);
|
|
@@ -3743,6 +3645,8 @@ out:
|
|
|
if (dest_node_acl)
|
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
|
core_scsi3_tpg_undepend_item(dest_se_tpg);
|
|
|
+
|
|
|
+out_put_pr_reg:
|
|
|
core_scsi3_put_pr_reg(pr_reg);
|
|
|
return ret;
|
|
|
}
|
|
@@ -3760,14 +3664,15 @@ static unsigned long long core_scsi3_extract_reservation_key(unsigned char *cdb)
|
|
|
/*
|
|
|
* See spc4r17 section 6.14 Table 170
|
|
|
*/
|
|
|
-int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
|
|
|
+sense_reason_t
|
|
|
+target_scsi3_emulate_pr_out(struct se_cmd *cmd)
|
|
|
{
|
|
|
unsigned char *cdb = &cmd->t_task_cdb[0];
|
|
|
unsigned char *buf;
|
|
|
u64 res_key, sa_res_key;
|
|
|
int sa, scope, type, aptpl;
|
|
|
int spec_i_pt = 0, all_tg_pt = 0, unreg = 0;
|
|
|
- int ret;
|
|
|
+ sense_reason_t ret;
|
|
|
|
|
|
/*
|
|
|
* Following spc2r20 5.5.1 Reservations overview:
|
|
@@ -3782,28 +3687,22 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
|
|
|
pr_err("Received PERSISTENT_RESERVE CDB while legacy"
|
|
|
" SPC-2 reservation is held, returning"
|
|
|
" RESERVATION_CONFLICT\n");
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* FIXME: A NULL struct se_session pointer means an this is not coming from
|
|
|
* a $FABRIC_MOD's nexus, but from internal passthrough ops.
|
|
|
*/
|
|
|
- if (!cmd->se_sess) {
|
|
|
- cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ if (!cmd->se_sess)
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
|
|
|
if (cmd->data_length < 24) {
|
|
|
pr_warn("SPC-PR: Received PR OUT parameter list"
|
|
|
" length too small: %u\n", cmd->data_length);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ return TCM_INVALID_PARAMETER_LIST;
|
|
|
}
|
|
|
+
|
|
|
/*
|
|
|
* From the PERSISTENT_RESERVE_OUT command descriptor block (CDB)
|
|
|
*/
|
|
@@ -3812,6 +3711,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
|
|
|
type = (cdb[2] & 0x0f);
|
|
|
|
|
|
buf = transport_kmap_data_sg(cmd);
|
|
|
+ if (!buf)
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+
|
|
|
/*
|
|
|
* From PERSISTENT_RESERVE_OUT parameter list (payload)
|
|
|
*/
|
|
@@ -3835,11 +3737,8 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
|
|
|
/*
|
|
|
* SPEC_I_PT=1 is only valid for Service action: REGISTER
|
|
|
*/
|
|
|
- if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER)) {
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
+ if (spec_i_pt && ((cdb[1] & 0x1f) != PRO_REGISTER))
|
|
|
+ return TCM_INVALID_PARAMETER_LIST;
|
|
|
|
|
|
/*
|
|
|
* From spc4r17 section 6.14:
|
|
@@ -3854,10 +3753,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
|
|
|
(cmd->data_length != 24)) {
|
|
|
pr_warn("SPC-PR: Received PR OUT illegal parameter"
|
|
|
" list length: %u\n", cmd->data_length);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
|
|
|
- ret = -EINVAL;
|
|
|
- goto out;
|
|
|
+ return TCM_INVALID_PARAMETER_LIST;
|
|
|
}
|
|
|
+
|
|
|
/*
|
|
|
* (core_scsi3_emulate_pro_* function parameters
|
|
|
* are defined by spc4r17 Table 174:
|
|
@@ -3896,12 +3794,9 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
|
|
|
default:
|
|
|
pr_err("Unknown PERSISTENT_RESERVE_OUT service"
|
|
|
" action: 0x%02x\n", cdb[1] & 0x1f);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- ret = -EINVAL;
|
|
|
- break;
|
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
|
}
|
|
|
|
|
|
-out:
|
|
|
if (!ret)
|
|
|
target_complete_cmd(cmd, GOOD);
|
|
|
return ret;
|
|
@@ -3912,7 +3807,8 @@ out:
|
|
|
*
|
|
|
* See spc4r17 section 5.7.6.2 and section 6.13.2, Table 160
|
|
|
*/
|
|
|
-static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_pri_read_keys(struct se_cmd *cmd)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct t10_pr_registration *pr_reg;
|
|
@@ -3922,11 +3818,13 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
|
|
|
if (cmd->data_length < 8) {
|
|
|
pr_err("PRIN SA READ_KEYS SCSI Data Length: %u"
|
|
|
" too small\n", cmd->data_length);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
|
}
|
|
|
|
|
|
buf = transport_kmap_data_sg(cmd);
|
|
|
+ if (!buf)
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+
|
|
|
buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff);
|
|
|
buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff);
|
|
|
buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
|
|
@@ -3970,7 +3868,8 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
|
|
|
*
|
|
|
* See spc4r17 section 5.7.6.3 and section 6.13.3.2 Table 161 and 162
|
|
|
*/
|
|
|
-static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_pri_read_reservation(struct se_cmd *cmd)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct t10_pr_registration *pr_reg;
|
|
@@ -3981,11 +3880,13 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
|
|
|
if (cmd->data_length < 8) {
|
|
|
pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u"
|
|
|
" too small\n", cmd->data_length);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
|
}
|
|
|
|
|
|
buf = transport_kmap_data_sg(cmd);
|
|
|
+ if (!buf)
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
+
|
|
|
buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff);
|
|
|
buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff);
|
|
|
buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
|
|
@@ -4054,7 +3955,8 @@ err:
|
|
|
*
|
|
|
* See spc4r17 section 6.13.4 Table 165
|
|
|
*/
|
|
|
-static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
@@ -4064,11 +3966,12 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
|
|
|
if (cmd->data_length < 6) {
|
|
|
pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:"
|
|
|
" %u too small\n", cmd->data_length);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
|
}
|
|
|
|
|
|
buf = transport_kmap_data_sg(cmd);
|
|
|
+ if (!buf)
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
|
|
|
buf[0] = ((add_len << 8) & 0xff);
|
|
|
buf[1] = (add_len & 0xff);
|
|
@@ -4110,7 +4013,8 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
|
|
|
*
|
|
|
* See spc4r17 section 6.13.5 Table 168 and 169
|
|
|
*/
|
|
|
-static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|
|
+static sense_reason_t
|
|
|
+core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_node_acl *se_nacl;
|
|
@@ -4125,11 +4029,12 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|
|
if (cmd->data_length < 8) {
|
|
|
pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u"
|
|
|
" too small\n", cmd->data_length);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
|
}
|
|
|
|
|
|
buf = transport_kmap_data_sg(cmd);
|
|
|
+ if (!buf)
|
|
|
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
|
|
|
buf[0] = ((dev->t10_pr.pr_generation >> 24) & 0xff);
|
|
|
buf[1] = ((dev->t10_pr.pr_generation >> 16) & 0xff);
|
|
@@ -4255,9 +4160,10 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
|
|
|
+sense_reason_t
|
|
|
+target_scsi3_emulate_pr_in(struct se_cmd *cmd)
|
|
|
{
|
|
|
- int ret;
|
|
|
+ sense_reason_t ret;
|
|
|
|
|
|
/*
|
|
|
* Following spc2r20 5.5.1 Reservations overview:
|
|
@@ -4272,8 +4178,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
|
|
|
pr_err("Received PERSISTENT_RESERVE CDB while legacy"
|
|
|
" SPC-2 reservation is held, returning"
|
|
|
" RESERVATION_CONFLICT\n");
|
|
|
- cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
|
|
- return -EINVAL;
|
|
|
+ return TCM_RESERVATION_CONFLICT;
|
|
|
}
|
|
|
|
|
|
switch (cmd->t_task_cdb[1] & 0x1f) {
|
|
@@ -4292,9 +4197,7 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
|
|
|
default:
|
|
|
pr_err("Unknown PERSISTENT_RESERVE_IN service"
|
|
|
" action: 0x%02x\n", cmd->t_task_cdb[1] & 0x1f);
|
|
|
- cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
|
|
- ret = -EINVAL;
|
|
|
- break;
|
|
|
+ return TCM_INVALID_CDB_FIELD;
|
|
|
}
|
|
|
|
|
|
if (!ret)
|
|
@@ -4302,10 +4205,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-int target_check_reservation(struct se_cmd *cmd)
|
|
|
+sense_reason_t
|
|
|
+target_check_reservation(struct se_cmd *cmd)
|
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
- int ret;
|
|
|
+ sense_reason_t ret;
|
|
|
|
|
|
if (!cmd->se_sess)
|
|
|
return 0;
|