]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/target/target_core_pr.c
Merge branch 'kbuild' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
[karo-tx-linux.git] / drivers / target / target_core_pr.c
index 8c323a98c4a02bbf7773384f87b885b737d1124a..e35dbf85841fa6067094a336ef23d9edbb3427e6 100644 (file)
@@ -4,8 +4,7 @@
  * This file contains SPC-3 compliant persistent reservations and
  * legacy SPC-2 reservations with compatible reservation handling (CRH=1)
  *
- * Copyright (c) 2009, 2010 Rising Tide Systems
- * Copyright (c) 2009, 2010 Linux-iSCSI.org
+ * (c) Copyright 2009-2012 RisingTide Systems LLC.
  *
  * Nicholas A. Bellinger <nab@kernel.org>
  *
@@ -68,49 +67,33 @@ 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 core_scsi2_reservation_seq_non_holder(
-       struct se_cmd *cmd,
-       unsigned char *cdb,
-       u32 pr_reg_type)
+static sense_reason_t
+target_scsi2_reservation_check(struct se_cmd *cmd)
 {
-       switch (cdb[0]) {
+       struct se_device *dev = cmd->se_dev;
+       struct se_session *sess = cmd->se_sess;
+
+       switch (cmd->t_task_cdb[0]) {
        case INQUIRY:
        case RELEASE:
        case RELEASE_10:
                return 0;
        default:
-               return 1;
+               break;
        }
 
-       return 1;
-}
-
-static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type)
-{
-       struct se_device *dev = cmd->se_dev;
-       struct se_session *sess = cmd->se_sess;
-       int ret;
-
-       if (!sess)
+       if (!dev->dev_reserved_node_acl || !sess)
                return 0;
 
-       spin_lock(&dev->dev_reservation_lock);
-       if (!dev->dev_reserved_node_acl || !sess) {
-               spin_unlock(&dev->dev_reservation_lock);
-               return 0;
-       }
-       if (dev->dev_reserved_node_acl != sess->se_node_acl) {
-               spin_unlock(&dev->dev_reservation_lock);
-               return -EINVAL;
-       }
-       if (!(dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID)) {
-               spin_unlock(&dev->dev_reservation_lock);
-               return 0;
+       if (dev->dev_reserved_node_acl != sess->se_node_acl)
+               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 TCM_RESERVATION_CONFLICT;
        }
-       ret = (dev->dev_res_bin_isid == sess->sess_bin_isid) ? 0 : -EINVAL;
-       spin_unlock(&dev->dev_reservation_lock);
 
-       return ret;
+       return 0;
 }
 
 static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *,
@@ -120,15 +103,11 @@ static void core_scsi3_put_pr_reg(struct t10_pr_registration *);
 static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd)
 {
        struct se_session *se_sess = cmd->se_sess;
-       struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
+       struct se_device *dev = cmd->se_dev;
        struct t10_pr_registration *pr_reg;
-       struct t10_reservation *pr_tmpl = &su_dev->t10_pr;
-       int crh = (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS);
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        int conflict = 0;
 
-       if (!crh)
-               return -EINVAL;
-
        pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
                        se_sess);
        if (pr_reg) {
@@ -186,32 +165,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;
@@ -223,10 +198,10 @@ int target_scsi2_reservation_release(struct se_cmd *cmd)
                goto out_unlock;
 
        dev->dev_reserved_node_acl = NULL;
-       dev->dev_flags &= ~DF_SPC2_RESERVATIONS;
-       if (dev->dev_flags & DF_SPC2_RESERVATIONS_WITH_ISID) {
+       dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS;
+       if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) {
                dev->dev_res_bin_isid = 0;
-               dev->dev_flags &= ~DF_SPC2_RESERVATIONS_WITH_ISID;
+               dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS_WITH_ISID;
        }
        tpg = sess->se_tpg;
        pr_debug("SCSI-2 Released reservation for %s LUN: %u ->"
@@ -237,25 +212,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
@@ -266,13 +240,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 &&
@@ -286,16 +257,15 @@ 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;
        }
 
        dev->dev_reserved_node_acl = sess->se_node_acl;
-       dev->dev_flags |= DF_SPC2_RESERVATIONS;
+       dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS;
        if (sess->sess_bin_isid != 0) {
                dev->dev_res_bin_isid = sess->sess_bin_isid;
-               dev->dev_flags |= DF_SPC2_RESERVATIONS_WITH_ISID;
+               dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS_WITH_ISID;
        }
        pr_debug("SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u"
                " for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
@@ -319,9 +289,9 @@ out:
  */
 static int core_scsi3_pr_seq_non_holder(
        struct se_cmd *cmd,
-       unsigned char *cdb,
        u32 pr_reg_type)
 {
+       unsigned char *cdb = cmd->t_task_cdb;
        struct se_dev_entry *se_deve;
        struct se_session *se_sess = cmd->se_sess;
        int other_cdb = 0, ignore_reg;
@@ -330,17 +300,11 @@ static int core_scsi3_pr_seq_non_holder(
        int we = 0; /* Write Exclusive */
        int legacy = 0; /* Act like a legacy device and return
                         * RESERVATION CONFLICT on some CDBs */
-       /*
-        * A legacy SPC-2 reservation is being held.
-        */
-       if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS)
-               return core_scsi2_reservation_seq_non_holder(cmd,
-                                       cdb, pr_reg_type);
 
        se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
        /*
         * Determine if the registration should be ignored due to
-        * non-matching ISIDs in core_scsi3_pr_reservation_check().
+        * non-matching ISIDs in target_scsi3_pr_reservation_check().
         */
        ignore_reg = (pr_reg_type & 0x80000000);
        if (ignore_reg)
@@ -563,10 +527,41 @@ static int core_scsi3_pr_seq_non_holder(
        return 1; /* Conflict by default */
 }
 
+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;
+       u32 pr_reg_type;
+
+       if (!dev->dev_pr_res_holder)
+               return 0;
+
+       pr_reg_type = dev->dev_pr_res_holder->pr_res_type;
+       cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key;
+       if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl)
+               goto check_nonholder;
+
+       if (dev->dev_pr_res_holder->isid_present_at_reg) {
+               if (dev->dev_pr_res_holder->pr_reg_bin_isid !=
+                   sess->sess_bin_isid) {
+                       pr_reg_type |= 0x80000000;
+                       goto check_nonholder;
+               }
+       }
+
+       return 0;
+
+check_nonholder:
+       if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type))
+               return TCM_RESERVATION_CONFLICT;
+       return 0;
+}
+
 static u32 core_scsi3_pr_generation(struct se_device *dev)
 {
-       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
        u32 prg;
+
        /*
         * PRGeneration field shall contain the value of a 32-bit wrapping
         * counter mainted by the device server.
@@ -577,56 +572,12 @@ static u32 core_scsi3_pr_generation(struct se_device *dev)
         * See spc4r17 section 6.3.12 READ_KEYS service action
         */
        spin_lock(&dev->dev_reservation_lock);
-       prg = su_dev->t10_pr.pr_generation++;
+       prg = dev->t10_pr.pr_generation++;
        spin_unlock(&dev->dev_reservation_lock);
 
        return prg;
 }
 
-static int core_scsi3_pr_reservation_check(
-       struct se_cmd *cmd,
-       u32 *pr_reg_type)
-{
-       struct se_device *dev = cmd->se_dev;
-       struct se_session *sess = cmd->se_sess;
-       int ret;
-
-       if (!sess)
-               return 0;
-       /*
-        * A legacy SPC-2 reservation is being held.
-        */
-       if (dev->dev_flags & DF_SPC2_RESERVATIONS)
-               return core_scsi2_reservation_check(cmd, pr_reg_type);
-
-       spin_lock(&dev->dev_reservation_lock);
-       if (!dev->dev_pr_res_holder) {
-               spin_unlock(&dev->dev_reservation_lock);
-               return 0;
-       }
-       *pr_reg_type = dev->dev_pr_res_holder->pr_res_type;
-       cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key;
-       if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) {
-               spin_unlock(&dev->dev_reservation_lock);
-               return -EINVAL;
-       }
-       if (!dev->dev_pr_res_holder->isid_present_at_reg) {
-               spin_unlock(&dev->dev_reservation_lock);
-               return 0;
-       }
-       ret = (dev->dev_pr_res_holder->pr_reg_bin_isid ==
-              sess->sess_bin_isid) ? 0 : -EINVAL;
-       /*
-        * Use bit in *pr_reg_type to notify ISID mismatch in
-        * core_scsi3_pr_seq_non_holder().
-        */
-       if (ret != 0)
-               *pr_reg_type |= 0x80000000;
-       spin_unlock(&dev->dev_reservation_lock);
-
-       return ret;
-}
-
 static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
        struct se_device *dev,
        struct se_node_acl *nacl,
@@ -636,7 +587,6 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
        int all_tg_pt,
        int aptpl)
 {
-       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
        struct t10_pr_registration *pr_reg;
 
        pr_reg = kmem_cache_zalloc(t10_pr_reg_cache, GFP_ATOMIC);
@@ -645,7 +595,7 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
                return NULL;
        }
 
-       pr_reg->pr_aptpl_buf = kzalloc(su_dev->t10_pr.pr_aptpl_buf_len,
+       pr_reg->pr_aptpl_buf = kzalloc(dev->t10_pr.pr_aptpl_buf_len,
                                        GFP_ATOMIC);
        if (!pr_reg->pr_aptpl_buf) {
                pr_err("Unable to allocate pr_reg->pr_aptpl_buf\n");
@@ -929,7 +879,7 @@ static int __core_scsi3_check_aptpl_registration(
        struct se_dev_entry *deve)
 {
        struct t10_pr_registration *pr_reg, *pr_reg_tmp;
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        unsigned char i_port[PR_APTPL_MAX_IPORT_LEN];
        unsigned char t_port[PR_APTPL_MAX_TPORT_LEN];
        u16 tpgt;
@@ -996,11 +946,10 @@ int core_scsi3_check_aptpl_registration(
        struct se_lun *lun,
        struct se_lun_acl *lun_acl)
 {
-       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
        struct se_node_acl *nacl = lun_acl->se_lun_nacl;
        struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun];
 
-       if (su_dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
+       if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
                return 0;
 
        return __core_scsi3_check_aptpl_registration(dev, tpg, lun,
@@ -1051,10 +1000,9 @@ static void __core_scsi3_add_registration(
        int register_type,
        int register_move)
 {
-       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
        struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
        struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
 
        /*
         * Increment PRgeneration counter for struct se_device upon a successful
@@ -1066,7 +1014,7 @@ static void __core_scsi3_add_registration(
         * for the REGISTER.
         */
        pr_reg->pr_res_generation = (register_move) ?
-                       su_dev->t10_pr.pr_generation++ :
+                       dev->t10_pr.pr_generation++ :
                        core_scsi3_pr_generation(dev);
 
        spin_lock(&pr_tmpl->registration_lock);
@@ -1135,7 +1083,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg(
        struct se_node_acl *nacl,
        unsigned char *isid)
 {
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        struct t10_pr_registration *pr_reg, *pr_reg_tmp;
        struct se_portal_group *tpg;
 
@@ -1160,7 +1108,7 @@ static struct t10_pr_registration *__core_scsi3_locate_pr_reg(
                         * for fabric modules (iSCSI) requiring them.
                         */
                        if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) {
-                               if (dev->se_sub_dev->se_dev_attrib.enforce_pr_isids)
+                               if (dev->dev_attrib.enforce_pr_isids)
                                        continue;
                        }
                        atomic_inc(&pr_reg->pr_res_holders);
@@ -1274,7 +1222,7 @@ static void __core_scsi3_free_registration(
 {
        struct target_core_fabric_ops *tfo =
                        pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo;
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        char i_buf[PR_REG_ISID_ID_LEN];
        int prf_isid;
 
@@ -1335,7 +1283,7 @@ void core_scsi3_free_pr_reg_from_nacl(
        struct se_device *dev,
        struct se_node_acl *nacl)
 {
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder;
        /*
         * If the passed se_node_acl matches the reservation holder,
@@ -1365,7 +1313,7 @@ void core_scsi3_free_pr_reg_from_nacl(
 void core_scsi3_free_all_registrations(
        struct se_device *dev)
 {
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder;
 
        spin_lock(&dev->dev_reservation_lock);
@@ -1479,7 +1427,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,
@@ -1501,8 +1450,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);
@@ -1517,8 +1467,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;
@@ -1530,8 +1479,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;
        /*
@@ -1545,12 +1493,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
@@ -1565,9 +1517,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
@@ -1610,16 +1561,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
@@ -1641,17 +1589,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;
@@ -1668,9 +1613,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"
@@ -1683,9 +1627,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
@@ -1702,23 +1645,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"
@@ -1754,10 +1693,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;
@@ -1788,9 +1725,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);
@@ -1848,8 +1784,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..
@@ -1899,7 +1836,6 @@ static int __core_scsi3_update_aptpl_buf(
 {
        struct se_lun *lun;
        struct se_portal_group *tpg;
-       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
        struct t10_pr_registration *pr_reg;
        unsigned char tmp[512], isid_buf[32];
        ssize_t len = 0;
@@ -1917,8 +1853,8 @@ static int __core_scsi3_update_aptpl_buf(
        /*
         * Walk the registration list..
         */
-       spin_lock(&su_dev->t10_pr.registration_lock);
-       list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list,
+       spin_lock(&dev->t10_pr.registration_lock);
+       list_for_each_entry(pr_reg, &dev->t10_pr.registration_list,
                        pr_reg_list) {
 
                tmp[0] = '\0';
@@ -1963,7 +1899,7 @@ static int __core_scsi3_update_aptpl_buf(
                if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
                        pr_err("Unable to update renaming"
                                " APTPL metadata\n");
-                       spin_unlock(&su_dev->t10_pr.registration_lock);
+                       spin_unlock(&dev->t10_pr.registration_lock);
                        return -EMSGSIZE;
                }
                len += sprintf(buf+len, "%s", tmp);
@@ -1981,13 +1917,13 @@ static int __core_scsi3_update_aptpl_buf(
                if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
                        pr_err("Unable to update renaming"
                                " APTPL metadata\n");
-                       spin_unlock(&su_dev->t10_pr.registration_lock);
+                       spin_unlock(&dev->t10_pr.registration_lock);
                        return -EMSGSIZE;
                }
                len += sprintf(buf+len, "%s", tmp);
                reg_count++;
        }
-       spin_unlock(&su_dev->t10_pr.registration_lock);
+       spin_unlock(&dev->t10_pr.registration_lock);
 
        if (!reg_count)
                len += sprintf(buf+len, "No Registrations or Reservations");
@@ -2019,7 +1955,7 @@ static int __core_scsi3_write_aptpl_to_file(
        unsigned char *buf,
        u32 pr_aptpl_buf_len)
 {
-       struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn;
+       struct t10_wwn *wwn = &dev->t10_wwn;
        struct file *file;
        struct iovec iov[1];
        mm_segment_t old_fs;
@@ -2065,14 +2001,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
         */
@@ -2094,25 +2031,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;
@@ -2120,16 +2049,16 @@ static int core_scsi3_emulate_pro_register(
        struct se_lun *se_lun = cmd->se_lun;
        struct se_portal_group *se_tpg;
        struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp, *pr_reg_e;
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        /* 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];
@@ -2148,8 +2077,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.
@@ -2163,15 +2091,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 {
                        /*
@@ -2205,201 +2131,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)
@@ -2424,26 +2341,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->se_sub_dev->t10_pr;
+       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
@@ -2453,8 +2367,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:
@@ -2469,9 +2382,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:
@@ -2485,9 +2397,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
@@ -2518,9 +2429,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:
@@ -2542,9 +2452,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:
@@ -2557,8 +2466,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
@@ -2582,27 +2491,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:
@@ -2610,16 +2516,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;
 }
 
 /*
@@ -2657,23 +2559,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->se_sub_dev->t10_pr;
-       int ret, all_reg = 0;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
+       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
@@ -2682,8 +2582,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:
@@ -2704,8 +2603,7 @@ 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;
+               goto out_put_pr_reg;
        }
        if ((pr_res_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
            (pr_res_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG))
@@ -2718,9 +2616,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:
         *
@@ -2740,9 +2638,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:
@@ -2763,9 +2660,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
@@ -2818,25 +2714,23 @@ 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;
        struct se_session *se_sess = cmd->se_sess;
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
        u32 pr_res_mapped_lun = 0;
        int calling_it_nexus = 0;
@@ -2848,8 +2742,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:
@@ -2868,8 +2761,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;
@@ -2993,28 +2885,22 @@ 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;
        struct se_session *se_sess = cmd->se_sess;
        LIST_HEAD(preempt_and_abort_list);
        struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       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);
@@ -3022,19 +2908,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);
@@ -3047,8 +2930,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:
@@ -3142,8 +3024,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
@@ -3162,13 +3043,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);
@@ -3298,12 +3179,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);
@@ -3311,16 +3192,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:
@@ -3328,26 +3203,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;
@@ -3358,20 +3226,21 @@ static int core_scsi3_emulate_pro_register_and_move(
        struct se_portal_group *se_tpg, *dest_se_tpg = NULL;
        struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
        struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
-       struct t10_reservation *pr_tmpl = &dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        unsigned char *buf;
        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;
@@ -3387,8 +3256,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
@@ -3398,9 +3266,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
@@ -3408,9 +3275,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;
        }
 
        /*
@@ -3419,6 +3285,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;
@@ -3432,9 +3303,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);
@@ -3452,15 +3322,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);
@@ -3472,12 +3340,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:"
@@ -3489,16 +3360,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,
@@ -3506,8 +3375,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;
        }
 
@@ -3536,8 +3404,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)) {
@@ -3545,8 +3412,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:
@@ -3566,19 +3432,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;
        }
 
@@ -3594,19 +3458,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;
        }
 
@@ -3625,8 +3486,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;
        }
        /*
@@ -3639,8 +3499,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;
        }
        /*
@@ -3658,8 +3517,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;
@@ -3691,13 +3549,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,
@@ -3768,12 +3624,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);
@@ -3788,6 +3644,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;
 }
@@ -3805,14 +3663,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:
@@ -3823,32 +3682,26 @@ int target_scsi3_emulate_pr_out(struct se_cmd *cmd)
         * initiator or service action and shall terminate with a RESERVATION
         * CONFLICT status.
         */
-       if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) {
+       if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) {
                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)
         */
@@ -3857,6 +3710,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)
         */
@@ -3880,11 +3736,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:
@@ -3899,10 +3752,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:
@@ -3941,12 +3793,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;
@@ -3957,10 +3806,10 @@ 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 *se_dev = cmd->se_dev;
-       struct se_subsystem_dev *su_dev = se_dev->se_sub_dev;
+       struct se_device *dev = cmd->se_dev;
        struct t10_pr_registration *pr_reg;
        unsigned char *buf;
        u32 add_len = 0, off = 8;
@@ -3968,18 +3817,20 @@ 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);
-       buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
-       buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
-       buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
-       buf[3] = (su_dev->t10_pr.pr_generation & 0xff);
+       if (!buf)
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-       spin_lock(&su_dev->t10_pr.registration_lock);
-       list_for_each_entry(pr_reg, &su_dev->t10_pr.registration_list,
+       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);
+       buf[3] = (dev->t10_pr.pr_generation & 0xff);
+
+       spin_lock(&dev->t10_pr.registration_lock);
+       list_for_each_entry(pr_reg, &dev->t10_pr.registration_list,
                        pr_reg_list) {
                /*
                 * Check for overflow of 8byte PRI READ_KEYS payload and
@@ -3999,7 +3850,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
 
                add_len += 8;
        }
-       spin_unlock(&su_dev->t10_pr.registration_lock);
+       spin_unlock(&dev->t10_pr.registration_lock);
 
        buf[4] = ((add_len >> 24) & 0xff);
        buf[5] = ((add_len >> 16) & 0xff);
@@ -4016,10 +3867,10 @@ 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 *se_dev = cmd->se_dev;
-       struct se_subsystem_dev *su_dev = se_dev->se_sub_dev;
+       struct se_device *dev = cmd->se_dev;
        struct t10_pr_registration *pr_reg;
        unsigned char *buf;
        u64 pr_res_key;
@@ -4028,18 +3879,20 @@ 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);
-       buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
-       buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
-       buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
-       buf[3] = (su_dev->t10_pr.pr_generation & 0xff);
+       if (!buf)
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-       spin_lock(&se_dev->dev_reservation_lock);
-       pr_reg = se_dev->dev_pr_res_holder;
+       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);
+       buf[3] = (dev->t10_pr.pr_generation & 0xff);
+
+       spin_lock(&dev->dev_reservation_lock);
+       pr_reg = dev->dev_pr_res_holder;
        if (pr_reg) {
                /*
                 * Set the hardcoded Additional Length
@@ -4090,7 +3943,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
        }
 
 err:
-       spin_unlock(&se_dev->dev_reservation_lock);
+       spin_unlock(&dev->dev_reservation_lock);
        transport_kunmap_data_sg(cmd);
 
        return 0;
@@ -4101,21 +3954,23 @@ 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->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        unsigned char *buf;
        u16 add_len = 8; /* Hardcoded to 8. */
 
        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);
@@ -4157,14 +4012,14 @@ 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 *se_dev = cmd->se_dev;
+       struct se_device *dev = cmd->se_dev;
        struct se_node_acl *se_nacl;
-       struct se_subsystem_dev *su_dev = se_dev->se_sub_dev;
        struct se_portal_group *se_tpg;
        struct t10_pr_registration *pr_reg, *pr_reg_tmp;
-       struct t10_reservation *pr_tmpl = &se_dev->se_sub_dev->t10_pr;
+       struct t10_reservation *pr_tmpl = &dev->t10_pr;
        unsigned char *buf;
        u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len;
        u32 off = 8; /* off into first Full Status descriptor */
@@ -4173,16 +4028,17 @@ 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] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
-       buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
-       buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
-       buf[3] = (su_dev->t10_pr.pr_generation & 0xff);
+       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);
+       buf[3] = (dev->t10_pr.pr_generation & 0xff);
 
        spin_lock(&pr_tmpl->registration_lock);
        list_for_each_entry_safe(pr_reg, pr_reg_tmp,
@@ -4303,9 +4159,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:
@@ -4316,12 +4173,11 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
         * initiator or service action and shall terminate with a RESERVATION
         * CONFLICT status.
         */
-       if (cmd->se_dev->dev_flags & DF_SPC2_RESERVATIONS) {
+       if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) {
                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) {
@@ -4340,9 +4196,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)
@@ -4350,56 +4204,25 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
        return ret;
 }
 
-static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type)
-{
-       return 0;
-}
-
-static int core_pt_seq_non_holder(
-       struct se_cmd *cmd,
-       unsigned char *cdb,
-       u32 pr_reg_type)
+sense_reason_t
+target_check_reservation(struct se_cmd *cmd)
 {
-       return 0;
-}
+       struct se_device *dev = cmd->se_dev;
+       sense_reason_t ret;
 
-int core_setup_reservations(struct se_device *dev, int force_pt)
-{
-       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
-       struct t10_reservation *rest = &su_dev->t10_pr;
-       /*
-        * If this device is from Target_Core_Mod/pSCSI, use the reservations
-        * of the Underlying SCSI hardware.  In Linux/SCSI terms, this can
-        * cause a problem because libata and some SATA RAID HBAs appear
-        * under Linux/SCSI, but to emulate reservations themselves.
-        */
-       if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) &&
-           !(dev->se_sub_dev->se_dev_attrib.emulate_reservations)) || force_pt) {
-               rest->res_type = SPC_PASSTHROUGH;
-               rest->pr_ops.t10_reservation_check = &core_pt_reservation_check;
-               rest->pr_ops.t10_seq_non_holder = &core_pt_seq_non_holder;
-               pr_debug("%s: Using SPC_PASSTHROUGH, no reservation"
-                       " emulation\n", dev->transport->name);
+       if (!cmd->se_sess)
+               return 0;
+       if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
+               return 0;
+       if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
                return 0;
-       }
-       /*
-        * If SPC-3 or above is reported by real or emulated struct se_device,
-        * use emulated Persistent Reservations.
-        */
-       if (dev->transport->get_device_rev(dev) >= SCSI_3) {
-               rest->res_type = SPC3_PERSISTENT_RESERVATIONS;
-               rest->pr_ops.t10_reservation_check = &core_scsi3_pr_reservation_check;
-               rest->pr_ops.t10_seq_non_holder = &core_scsi3_pr_seq_non_holder;
-               pr_debug("%s: Using SPC3_PERSISTENT_RESERVATIONS"
-                       " emulation\n", dev->transport->name);
-       } else {
-               rest->res_type = SPC2_RESERVATIONS;
-               rest->pr_ops.t10_reservation_check = &core_scsi2_reservation_check;
-               rest->pr_ops.t10_seq_non_holder =
-                               &core_scsi2_reservation_seq_non_holder;
-               pr_debug("%s: Using SPC2_RESERVATIONS emulation\n",
-                       dev->transport->name);
-       }
 
-       return 0;
+       spin_lock(&dev->dev_reservation_lock);
+       if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
+               ret = target_scsi2_reservation_check(cmd);
+       else
+               ret = target_scsi3_pr_reservation_check(cmd);
+       spin_unlock(&dev->dev_reservation_lock);
+
+       return ret;
 }