]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/target/target_core_pr.c
[media] ad9389b: no monitor if EDID is wrong
[karo-tx-linux.git] / drivers / target / target_core_pr.c
index 3240f2cc81efe0b65d2369c5cdadd9d3d22d3df4..bd78faf67c6b366657d572b8e8d1461af77abfec 100644 (file)
@@ -53,18 +53,28 @@ struct pr_transport_id_holder {
        struct list_head dest_list;
 };
 
-int core_pr_dump_initiator_port(
+void core_pr_dump_initiator_port(
        struct t10_pr_registration *pr_reg,
        char *buf,
        u32 size)
 {
        if (!pr_reg->isid_present_at_reg)
-               return 0;
+               buf[0] = '\0';
 
-       snprintf(buf, size, ",i,0x%s", &pr_reg->pr_reg_isid[0]);
-       return 1;
+       snprintf(buf, size, ",i,0x%s", pr_reg->pr_reg_isid);
 }
 
+enum register_type {
+       REGISTER,
+       REGISTER_AND_IGNORE_EXISTING_KEY,
+       REGISTER_AND_MOVE,
+};
+
+enum preempt_type {
+       PREEMPT,
+       PREEMPT_AND_ABORT,
+};
+
 static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *,
                        struct t10_pr_registration *, int);
 
@@ -596,14 +606,6 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
                return NULL;
        }
 
-       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");
-               kmem_cache_free(t10_pr_reg_cache, pr_reg);
-               return NULL;
-       }
-
        INIT_LIST_HEAD(&pr_reg->pr_reg_list);
        INIT_LIST_HEAD(&pr_reg->pr_reg_abort_list);
        INIT_LIST_HEAD(&pr_reg->pr_reg_aptpl_list);
@@ -794,7 +796,6 @@ int core_scsi3_alloc_aptpl_registration(
                pr_err("Unable to allocate struct t10_pr_registration\n");
                return -ENOMEM;
        }
-       pr_reg->pr_aptpl_buf = kzalloc(pr_tmpl->pr_aptpl_buf_len, GFP_KERNEL);
 
        INIT_LIST_HEAD(&pr_reg->pr_reg_list);
        INIT_LIST_HEAD(&pr_reg->pr_reg_abort_list);
@@ -848,11 +849,9 @@ static void core_scsi3_aptpl_reserve(
        struct t10_pr_registration *pr_reg)
 {
        char i_buf[PR_REG_ISID_ID_LEN];
-       int prf_isid;
 
        memset(i_buf, 0, PR_REG_ISID_ID_LEN);
-       prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
-                               PR_REG_ISID_ID_LEN);
+       core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
 
        spin_lock(&dev->dev_reservation_lock);
        dev->dev_pr_res_holder = pr_reg;
@@ -865,11 +864,11 @@ static void core_scsi3_aptpl_reserve(
                (pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
        pr_debug("SPC-3 PR [%s] RESERVE Node: %s%s\n",
                tpg->se_tpg_tfo->get_fabric_name(), node_acl->initiatorname,
-               (prf_isid) ? &i_buf[0] : "");
+               i_buf);
 }
 
 static void __core_scsi3_add_registration(struct se_device *, struct se_node_acl *,
-                               struct t10_pr_registration *, int, int);
+                               struct t10_pr_registration *, enum register_type, int);
 
 static int __core_scsi3_check_aptpl_registration(
        struct se_device *dev,
@@ -962,21 +961,19 @@ static void __core_scsi3_dump_registration(
        struct se_device *dev,
        struct se_node_acl *nacl,
        struct t10_pr_registration *pr_reg,
-       int register_type)
+       enum register_type register_type)
 {
        struct se_portal_group *se_tpg = nacl->se_tpg;
        char i_buf[PR_REG_ISID_ID_LEN];
-       int prf_isid;
 
        memset(&i_buf[0], 0, PR_REG_ISID_ID_LEN);
-       prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
-                               PR_REG_ISID_ID_LEN);
+       core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
 
        pr_debug("SPC-3 PR [%s] Service Action: REGISTER%s Initiator"
-               " Node: %s%s\n", tfo->get_fabric_name(), (register_type == 2) ?
-               "_AND_MOVE" : (register_type == 1) ?
+               " Node: %s%s\n", tfo->get_fabric_name(), (register_type == REGISTER_AND_MOVE) ?
+               "_AND_MOVE" : (register_type == REGISTER_AND_IGNORE_EXISTING_KEY) ?
                "_AND_IGNORE_EXISTING_KEY" : "", nacl->initiatorname,
-               (prf_isid) ? i_buf : "");
+               i_buf);
        pr_debug("SPC-3 PR [%s] registration on Target Port: %s,0x%04x\n",
                 tfo->get_fabric_name(), tfo->tpg_get_wwn(se_tpg),
                tfo->tpg_get_tag(se_tpg));
@@ -998,7 +995,7 @@ static void __core_scsi3_add_registration(
        struct se_device *dev,
        struct se_node_acl *nacl,
        struct t10_pr_registration *pr_reg,
-       int register_type,
+       enum register_type register_type,
        int register_move)
 {
        struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
@@ -1064,7 +1061,7 @@ static int core_scsi3_alloc_registration(
        u64 sa_res_key,
        int all_tg_pt,
        int aptpl,
-       int register_type,
+       enum register_type register_type,
        int register_move)
 {
        struct t10_pr_registration *pr_reg;
@@ -1225,11 +1222,9 @@ static void __core_scsi3_free_registration(
                        pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo;
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
        char i_buf[PR_REG_ISID_ID_LEN];
-       int prf_isid;
 
        memset(i_buf, 0, PR_REG_ISID_ID_LEN);
-       prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
-                               PR_REG_ISID_ID_LEN);
+       core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
 
        pr_reg->pr_reg_deve->def_pr_registered = 0;
        pr_reg->pr_reg_deve->pr_res_key = 0;
@@ -1257,7 +1252,7 @@ static void __core_scsi3_free_registration(
        pr_debug("SPC-3 PR [%s] Service Action: UNREGISTER Initiator"
                " Node: %s%s\n", tfo->get_fabric_name(),
                pr_reg->pr_reg_nacl->initiatorname,
-               (prf_isid) ? &i_buf[0] : "");
+               i_buf);
        pr_debug("SPC-3 PR [%s] for %s TCM Subsystem %s Object Target"
                " Port(s)\n", tfo->get_fabric_name(),
                (pr_reg->pr_reg_all_tg_pt) ? "ALL" : "SINGLE",
@@ -1269,7 +1264,6 @@ static void __core_scsi3_free_registration(
        if (!preempt_and_abort_list) {
                pr_reg->pr_reg_deve = NULL;
                pr_reg->pr_reg_nacl = NULL;
-               kfree(pr_reg->pr_aptpl_buf);
                kmem_cache_free(t10_pr_reg_cache, pr_reg);
                return;
        }
@@ -1338,7 +1332,6 @@ void core_scsi3_free_all_registrations(
        list_for_each_entry_safe(pr_reg, pr_reg_tmp, &pr_tmpl->aptpl_reg_list,
                                pr_reg_aptpl_list) {
                list_del(&pr_reg->pr_reg_aptpl_list);
-               kfree(pr_reg->pr_aptpl_buf);
                kmem_cache_free(t10_pr_reg_cache, pr_reg);
        }
        spin_unlock(&pr_tmpl->aptpl_reg_lock);
@@ -1453,7 +1446,7 @@ core_scsi3_decode_spec_i_port(
        char *iport_ptr = NULL, dest_iport[64], i_buf[PR_REG_ISID_ID_LEN];
        sense_reason_t ret;
        u32 tpdl, tid_len = 0;
-       int dest_local_nexus, prf_isid;
+       int dest_local_nexus;
        u32 dest_rtpi = 0;
 
        memset(dest_iport, 0, 64);
@@ -1764,8 +1757,7 @@ core_scsi3_decode_spec_i_port(
                kfree(tidh);
 
                memset(i_buf, 0, PR_REG_ISID_ID_LEN);
-               prf_isid = core_pr_dump_initiator_port(dest_pr_reg, &i_buf[0],
-                                               PR_REG_ISID_ID_LEN);
+               core_pr_dump_initiator_port(dest_pr_reg, i_buf, PR_REG_ISID_ID_LEN);
 
                __core_scsi3_add_registration(cmd->se_dev, dest_node_acl,
                                        dest_pr_reg, 0, 0);
@@ -1773,8 +1765,7 @@ core_scsi3_decode_spec_i_port(
                pr_debug("SPC-3 PR [%s] SPEC_I_PT: Successfully"
                        " registered Transport ID for Node: %s%s Mapped LUN:"
                        " %u\n", dest_tpg->se_tpg_tfo->get_fabric_name(),
-                       dest_node_acl->initiatorname, (prf_isid) ?
-                       &i_buf[0] : "", dest_se_deve->mapped_lun);
+                       dest_node_acl->initiatorname, i_buf, dest_se_deve->mapped_lun);
 
                if (dest_local_nexus)
                        continue;
@@ -1813,7 +1804,6 @@ out:
                        kmem_cache_free(t10_pr_reg_cache, pr_reg_tmp);
                }
 
-               kfree(dest_pr_reg->pr_aptpl_buf);
                kmem_cache_free(t10_pr_reg_cache, dest_pr_reg);
 
                if (dest_local_nexus)
@@ -1826,14 +1816,10 @@ out:
        return ret;
 }
 
-/*
- * Called with struct se_device->dev_reservation_lock held
- */
-static int __core_scsi3_update_aptpl_buf(
+static int core_scsi3_update_aptpl_buf(
        struct se_device *dev,
        unsigned char *buf,
-       u32 pr_aptpl_buf_len,
-       int clear_aptpl_metadata)
+       u32 pr_aptpl_buf_len)
 {
        struct se_lun *lun;
        struct se_portal_group *tpg;
@@ -1841,20 +1827,13 @@ static int __core_scsi3_update_aptpl_buf(
        unsigned char tmp[512], isid_buf[32];
        ssize_t len = 0;
        int reg_count = 0;
+       int ret = 0;
 
-       memset(buf, 0, pr_aptpl_buf_len);
-       /*
-        * Called to clear metadata once APTPL has been deactivated.
-        */
-       if (clear_aptpl_metadata) {
-               snprintf(buf, pr_aptpl_buf_len,
-                               "No Registrations or Reservations\n");
-               return 0;
-       }
+       spin_lock(&dev->dev_reservation_lock);
+       spin_lock(&dev->t10_pr.registration_lock);
        /*
         * Walk the registration list..
         */
-       spin_lock(&dev->t10_pr.registration_lock);
        list_for_each_entry(pr_reg, &dev->t10_pr.registration_list,
                        pr_reg_list) {
 
@@ -1900,8 +1879,8 @@ 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(&dev->t10_pr.registration_lock);
-                       return -EMSGSIZE;
+                       ret = -EMSGSIZE;
+                       goto out;
                }
                len += sprintf(buf+len, "%s", tmp);
 
@@ -1918,48 +1897,32 @@ 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(&dev->t10_pr.registration_lock);
-                       return -EMSGSIZE;
+                       ret = -EMSGSIZE;
+                       goto out;
                }
                len += sprintf(buf+len, "%s", tmp);
                reg_count++;
        }
-       spin_unlock(&dev->t10_pr.registration_lock);
 
        if (!reg_count)
                len += sprintf(buf+len, "No Registrations or Reservations");
 
-       return 0;
-}
-
-static int core_scsi3_update_aptpl_buf(
-       struct se_device *dev,
-       unsigned char *buf,
-       u32 pr_aptpl_buf_len,
-       int clear_aptpl_metadata)
-{
-       int ret;
-
-       spin_lock(&dev->dev_reservation_lock);
-       ret = __core_scsi3_update_aptpl_buf(dev, buf, pr_aptpl_buf_len,
-                               clear_aptpl_metadata);
+out:
+       spin_unlock(&dev->t10_pr.registration_lock);
        spin_unlock(&dev->dev_reservation_lock);
 
        return ret;
 }
 
-/*
- * Called with struct se_device->aptpl_file_mutex held
- */
 static int __core_scsi3_write_aptpl_to_file(
        struct se_device *dev,
-       unsigned char *buf,
-       u32 pr_aptpl_buf_len)
+       unsigned char *buf)
 {
        struct t10_wwn *wwn = &dev->t10_wwn;
        struct file *file;
        int flags = O_RDWR | O_CREAT | O_TRUNC;
        char path[512];
+       u32 pr_aptpl_buf_len;
        int ret;
 
        memset(path, 0, 512);
@@ -1978,8 +1941,7 @@ static int __core_scsi3_write_aptpl_to_file(
                return PTR_ERR(file);
        }
 
-       if (!pr_aptpl_buf_len)
-               pr_aptpl_buf_len = (strlen(&buf[0]) + 1); /* Add extra for NULL */
+       pr_aptpl_buf_len = (strlen(buf) + 1); /* Add extra for NULL */
 
        ret = kernel_write(file, buf, pr_aptpl_buf_len, 0);
 
@@ -1990,60 +1952,64 @@ static int __core_scsi3_write_aptpl_to_file(
        return ret ? -EIO : 0;
 }
 
-static int
-core_scsi3_update_and_write_aptpl(struct se_device *dev, unsigned char *in_buf,
-               u32 in_pr_aptpl_buf_len)
+/*
+ * Clear the APTPL metadata if APTPL has been disabled, otherwise
+ * write out the updated metadata to struct file for this SCSI device.
+ */
+static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl)
 {
-       unsigned char null_buf[64], *buf;
-       u32 pr_aptpl_buf_len;
-       int clear_aptpl_metadata = 0;
-       int ret;
+       unsigned char *buf;
+       int rc;
 
-       /*
-        * Can be called with a NULL pointer from PROUT service action CLEAR
-        */
-       if (!in_buf) {
-               memset(null_buf, 0, 64);
-               buf = &null_buf[0];
-               /*
-                * This will clear the APTPL metadata to:
-                * "No Registrations or Reservations" status
-                */
-               pr_aptpl_buf_len = 64;
-               clear_aptpl_metadata = 1;
-       } else {
-               buf = in_buf;
-               pr_aptpl_buf_len = in_pr_aptpl_buf_len;
+       if (!aptpl) {
+               char *null_buf = "No Registrations or Reservations\n";
+
+               rc = __core_scsi3_write_aptpl_to_file(dev, null_buf);
+               dev->t10_pr.pr_aptpl_active = 0;
+               pr_debug("SPC-3 PR: Set APTPL Bit Deactivated\n");
+
+               if (rc)
+                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+               return 0;
        }
 
-       ret = core_scsi3_update_aptpl_buf(dev, buf, pr_aptpl_buf_len,
-                               clear_aptpl_metadata);
-       if (ret != 0)
-               return ret;
+       buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
+       if (!buf)
+               return TCM_OUT_OF_RESOURCES;
 
-       /*
-        * __core_scsi3_write_aptpl_to_file() will call strlen()
-        * on the passed buf to determine pr_aptpl_buf_len.
-        */
-       return __core_scsi3_write_aptpl_to_file(dev, buf, 0);
+       rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN);
+       if (rc < 0) {
+               kfree(buf);
+               return TCM_OUT_OF_RESOURCES;
+       }
+
+       rc = __core_scsi3_write_aptpl_to_file(dev, buf);
+       if (rc != 0) {
+               pr_err("SPC-3 PR: Could not update APTPL\n");
+               kfree(buf);
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       }
+       dev->t10_pr.pr_aptpl_active = 1;
+       kfree(buf);
+       pr_debug("SPC-3 PR: Set APTPL Bit Activated\n");
+       return 0;
 }
 
 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)
+               bool aptpl, bool all_tg_pt, bool spec_i_pt, enum register_type register_type)
 {
        struct se_session *se_sess = cmd->se_sess;
        struct se_device *dev = cmd->se_dev;
        struct se_dev_entry *se_deve;
        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_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp;
        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;
        sense_reason_t ret = TCM_NO_SENSE;
-       int pr_holder = 0, type;
+       int pr_holder = 0;
 
        if (!se_sess || !se_lun) {
                pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
@@ -2061,8 +2027,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
        /*
         * Follow logic from spc4r17 Section 5.7.7, Register Behaviors Table 47
         */
-       pr_reg_e = core_scsi3_locate_pr_reg(dev, se_sess->se_node_acl, se_sess);
-       if (!pr_reg_e) {
+       pr_reg = core_scsi3_locate_pr_reg(dev, se_sess->se_node_acl, se_sess);
+       if (!pr_reg) {
                if (res_key) {
                        pr_warn("SPC-3 PR: Reservation Key non-zero"
                                " for SA REGISTER, returning CONFLICT\n");
@@ -2083,7 +2049,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                        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)) {
+                                       register_type, 0)) {
                                pr_err("Unable to allocate"
                                        " struct t10_pr_registration\n");
                                return TCM_INVALID_PARAMETER_LIST;
@@ -2102,97 +2068,68 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                        if (ret != 0)
                                return ret;
                }
-               /*
-                * Nothing left to do for the APTPL=0 case.
-                */
-               if (!aptpl) {
-                       pr_tmpl->pr_aptpl_active = 0;
-                       core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0);
-                       pr_debug("SPC-3 PR: Set APTPL Bit Deactivated for"
-                                       " REGISTER\n");
-                       return 0;
-               }
-               /*
-                * Locate the newly allocated local I_T Nexus *pr_reg, and
-                * update the APTPL metadata information using its
-                * preallocated *pr_reg->pr_aptpl_buf.
-                */
-               pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev,
-                               se_sess->se_node_acl, se_sess);
-
-               if (core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                               &pr_reg->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");
-               }
 
-               goto out_put_pr_reg;
+               return core_scsi3_update_and_write_aptpl(dev, aptpl);
        }
 
-       /*
-        * 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;
-               }
+       /* ok, existing registration */
+
+       if ((register_type == REGISTER) && (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;
        }
 
        if (spec_i_pt) {
-               pr_err("SPC-3 PR UNREGISTER: SPEC_I_PT"
-                       " set while sa_res_key=0\n");
+               pr_err("SPC-3 PR REGISTER: SPEC_I_PT"
+                       " set on a registered nexus\n");
                ret = TCM_INVALID_PARAMETER_LIST;
-               goto out_put_pr_reg;
+               goto out;
        }
 
        /*
         * 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"
+       if (pr_reg->pr_reg_all_tg_pt && !all_tg_pt) {
+               pr_err("SPC-3 PR REGISTER: 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;
+               goto out;
        }
 
        /*
-        * Allocate APTPL metadata buffer used for UNREGISTER ops
+        * sa_res_key=1 Change Reservation Key for registered I_T Nexus.
         */
-       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;
-               }
-       }
+       if (sa_res_key) {
+               /*
+                * 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(),
+                        (register_type == REGISTER_AND_IGNORE_EXISTING_KEY) ? "_AND_IGNORE_EXISTING_KEY" : "",
+                        pr_reg->pr_reg_nacl->initiatorname,
+                        pr_reg->pr_res_key, pr_reg->pr_res_generation);
 
-       /*
-        * 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) {
+       } else {
+               /*
+                * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus.
+                */
                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;
+                       goto out;
                }
 
                spin_lock(&pr_tmpl->registration_lock);
@@ -2237,8 +2174,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                 * RESERVATIONS RELEASED.
                 */
                if (pr_holder &&
-                  (type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY ||
-                   type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) {
+                   (pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY ||
+                    pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY)) {
                        list_for_each_entry(pr_reg_p,
                                        &pr_tmpl->registration_list,
                                        pr_reg_list) {
@@ -2250,60 +2187,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
                                        ASCQ_2AH_RESERVATIONS_RELEASED);
                        }
                }
-               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 (!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");
-               }
-
-               goto out_free_aptpl_buf;
-       }
-
-       /*
-        * 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);
-               pr_debug("SPC-3 PR: Set APTPL Bit Deactivated"
-                               " for REGISTER\n");
-               ret = 0;
-               goto out_put_pr_reg;
+               spin_unlock(&pr_tmpl->registration_lock);
        }
 
-       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");
-       }
+       ret = core_scsi3_update_and_write_aptpl(dev, aptpl);
 
-out_free_aptpl_buf:
-       kfree(pr_aptpl_buf);
-       ret = 0;
-out_put_pr_reg:
+out:
        core_scsi3_put_pr_reg(pr_reg);
        return ret;
 }
@@ -2340,7 +2230,6 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
        struct t10_reservation *pr_tmpl = &dev->t10_pr;
        char i_buf[PR_REG_ISID_ID_LEN];
        sense_reason_t ret;
-       int prf_isid;
 
        memset(i_buf, 0, PR_REG_ISID_ID_LEN);
 
@@ -2466,8 +2355,7 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
        pr_reg->pr_res_type = type;
        pr_reg->pr_res_holder = 1;
        dev->dev_pr_res_holder = pr_reg;
-       prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
-                               PR_REG_ISID_ID_LEN);
+       core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
 
        pr_debug("SPC-3 PR [%s] Service Action: RESERVE created new"
                " reservation holder TYPE: %s ALL_TG_PT: %d\n",
@@ -2476,17 +2364,11 @@ core_scsi3_pro_reserve(struct se_cmd *cmd, int type, int scope, u64 res_key)
        pr_debug("SPC-3 PR [%s] RESERVE Node: %s%s\n",
                        cmd->se_tfo->get_fabric_name(),
                        se_sess->se_node_acl->initiatorname,
-                       (prf_isid) ? &i_buf[0] : "");
+                       i_buf);
        spin_unlock(&dev->dev_reservation_lock);
 
-       if (pr_tmpl->pr_aptpl_active) {
-               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 RESERVE\n");
-               }
-       }
+       if (pr_tmpl->pr_aptpl_active)
+               core_scsi3_update_and_write_aptpl(cmd->se_dev, true);
 
        ret = 0;
 out_put_pr_reg:
@@ -2524,11 +2406,9 @@ static void __core_scsi3_complete_pro_release(
 {
        struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo;
        char i_buf[PR_REG_ISID_ID_LEN];
-       int prf_isid;
 
        memset(i_buf, 0, PR_REG_ISID_ID_LEN);
-       prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
-                               PR_REG_ISID_ID_LEN);
+       core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
        /*
         * Go ahead and release the current PR reservation holder.
         */
@@ -2541,7 +2421,7 @@ static void __core_scsi3_complete_pro_release(
                (pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
        pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n",
                tfo->get_fabric_name(), se_nacl->initiatorname,
-               (prf_isid) ? &i_buf[0] : "");
+               i_buf);
        /*
         * Clear TYPE and SCOPE for the next PROUT Service Action: RESERVE
         */
@@ -2702,12 +2582,9 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
        spin_unlock(&pr_tmpl->registration_lock);
 
 write_aptpl:
-       if (pr_tmpl->pr_aptpl_active) {
-               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");
-               }
-       }
+       if (pr_tmpl->pr_aptpl_active)
+               core_scsi3_update_and_write_aptpl(cmd->se_dev, true);
+
 out_put_pr_reg:
        core_scsi3_put_pr_reg(pr_reg);
        return ret;
@@ -2791,11 +2668,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
        pr_debug("SPC-3 PR [%s] Service Action: CLEAR complete\n",
                cmd->se_tfo->get_fabric_name());
 
-       if (pr_tmpl->pr_aptpl_active) {
-               core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0);
-               pr_debug("SPC-3 PR: Updated APTPL metadata"
-                               " for CLEAR\n");
-       }
+       core_scsi3_update_and_write_aptpl(cmd->se_dev, false);
 
        core_scsi3_pr_generation(dev);
        return 0;
@@ -2810,16 +2683,14 @@ static void __core_scsi3_complete_pro_preempt(
        struct list_head *preempt_and_abort_list,
        int type,
        int scope,
-       int abort)
+       enum preempt_type preempt_type)
 {
        struct se_node_acl *nacl = pr_reg->pr_reg_nacl;
        struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
        char i_buf[PR_REG_ISID_ID_LEN];
-       int prf_isid;
 
        memset(i_buf, 0, PR_REG_ISID_ID_LEN);
-       prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
-                               PR_REG_ISID_ID_LEN);
+       core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
        /*
         * Do an implict RELEASE of the existing reservation.
         */
@@ -2834,12 +2705,12 @@ static void __core_scsi3_complete_pro_preempt(
 
        pr_debug("SPC-3 PR [%s] Service Action: PREEMPT%s created new"
                " reservation holder TYPE: %s ALL_TG_PT: %d\n",
-               tfo->get_fabric_name(), (abort) ? "_AND_ABORT" : "",
+               tfo->get_fabric_name(), (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : "",
                core_scsi3_pr_dump_type(type),
                (pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
        pr_debug("SPC-3 PR [%s] PREEMPT%s from Node: %s%s\n",
-               tfo->get_fabric_name(), (abort) ? "_AND_ABORT" : "",
-               nacl->initiatorname, (prf_isid) ? &i_buf[0] : "");
+               tfo->get_fabric_name(), (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : "",
+               nacl->initiatorname, i_buf);
        /*
         * For PREEMPT_AND_ABORT, add the preempting reservation's
         * struct t10_pr_registration to the list that will be compared
@@ -2869,14 +2740,13 @@ static void core_scsi3_release_preempt_and_abort(
 
                pr_reg->pr_reg_deve = NULL;
                pr_reg->pr_reg_nacl = NULL;
-               kfree(pr_reg->pr_aptpl_buf);
                kmem_cache_free(t10_pr_reg_cache, pr_reg);
        }
 }
 
 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)
+               u64 sa_res_key, enum preempt_type preempt_type)
 {
        struct se_device *dev = cmd->se_dev;
        struct se_node_acl *pr_reg_nacl;
@@ -2896,7 +2766,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
        if (!pr_reg_n) {
                pr_err("SPC-3 PR: Unable to locate"
                        " PR_REGISTERED *pr_reg for PREEMPT%s\n",
-                       (abort) ? "_AND_ABORT" : "");
+                       (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : "");
                return TCM_RESERVATION_CONFLICT;
        }
        if (pr_reg_n->pr_res_key != res_key) {
@@ -2965,7 +2835,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                                pr_reg_nacl = pr_reg->pr_reg_nacl;
                                pr_res_mapped_lun = pr_reg->pr_res_mapped_lun;
                                __core_scsi3_free_registration(dev, pr_reg,
-                                       (abort) ? &preempt_and_abort_list :
+                                       (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list :
                                                NULL, calling_it_nexus);
                                released_regs++;
                        } else {
@@ -2993,7 +2863,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                                pr_reg_nacl = pr_reg->pr_reg_nacl;
                                pr_res_mapped_lun = pr_reg->pr_res_mapped_lun;
                                __core_scsi3_free_registration(dev, pr_reg,
-                                       (abort) ? &preempt_and_abort_list :
+                                       (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list :
                                                NULL, 0);
                                released_regs++;
                        }
@@ -3022,24 +2892,17 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                 */
                if (pr_res_holder && all_reg && !(sa_res_key)) {
                        __core_scsi3_complete_pro_preempt(dev, pr_reg_n,
-                               (abort) ? &preempt_and_abort_list : NULL,
-                               type, scope, abort);
+                               (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL,
+                               type, scope, preempt_type);
 
-                       if (abort)
+                       if (preempt_type == PREEMPT_AND_ABORT)
                                core_scsi3_release_preempt_and_abort(
                                        &preempt_and_abort_list, pr_reg_n);
                }
                spin_unlock(&dev->dev_reservation_lock);
 
-               if (pr_tmpl->pr_aptpl_active) {
-                       if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                                       &pr_reg_n->pr_aptpl_buf[0],
-                                       pr_tmpl->pr_aptpl_buf_len)) {
-                               pr_debug("SPC-3 PR: Updated APTPL"
-                                       " metadata for  PREEMPT%s\n", (abort) ?
-                                       "_AND_ABORT" : "");
-                       }
-               }
+               if (pr_tmpl->pr_aptpl_active)
+                       core_scsi3_update_and_write_aptpl(cmd->se_dev, true);
 
                core_scsi3_put_pr_reg(pr_reg_n);
                core_scsi3_pr_generation(cmd->se_dev);
@@ -3103,7 +2966,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
                pr_reg_nacl = pr_reg->pr_reg_nacl;
                pr_res_mapped_lun = pr_reg->pr_res_mapped_lun;
                __core_scsi3_free_registration(dev, pr_reg,
-                               (abort) ? &preempt_and_abort_list : NULL,
+                               (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL,
                                calling_it_nexus);
                /*
                 * e) Establish a unit attention condition for the initiator
@@ -3120,8 +2983,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
         *    I_T nexus using the contents of the SCOPE and TYPE fields;
         */
        __core_scsi3_complete_pro_preempt(dev, pr_reg_n,
-                       (abort) ? &preempt_and_abort_list : NULL,
-                       type, scope, abort);
+                       (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : NULL,
+                       type, scope, preempt_type);
        /*
         * d) Process tasks as defined in 5.7.1;
         * e) See above..
@@ -3161,20 +3024,14 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
         * been removed from the primary pr_reg list), except the
         * new persistent reservation holder, the calling Initiator Port.
         */
-       if (abort) {
+       if (preempt_type == PREEMPT_AND_ABORT) {
                core_tmr_lun_reset(dev, NULL, &preempt_and_abort_list, cmd);
                core_scsi3_release_preempt_and_abort(&preempt_and_abort_list,
                                                pr_reg_n);
        }
 
-       if (pr_tmpl->pr_aptpl_active) {
-               if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                               &pr_reg_n->pr_aptpl_buf[0],
-                               pr_tmpl->pr_aptpl_buf_len)) {
-                       pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT"
-                               "%s\n", abort ? "_AND_ABORT" : "");
-               }
-       }
+       if (pr_tmpl->pr_aptpl_active)
+               core_scsi3_update_and_write_aptpl(cmd->se_dev, true);
 
        core_scsi3_put_pr_reg(pr_reg_n);
        core_scsi3_pr_generation(cmd->se_dev);
@@ -3183,7 +3040,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
 
 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)
+               u64 res_key, u64 sa_res_key, enum preempt_type preempt_type)
 {
        switch (type) {
        case PR_TYPE_WRITE_EXCLUSIVE:
@@ -3193,10 +3050,10 @@ core_scsi3_emulate_pro_preempt(struct se_cmd *cmd, int type, int scope,
        case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
        case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG:
                return core_scsi3_pro_preempt(cmd, type, scope, res_key,
-                                             sa_res_key, abort);
+                                             sa_res_key, preempt_type);
        default:
                pr_err("SPC-3 PR: Unknown Service Action PREEMPT%s"
-                       " Type: 0x%02x\n", (abort) ? "_AND_ABORT" : "", type);
+                       " Type: 0x%02x\n", (preempt_type == PREEMPT_AND_ABORT) ? "_AND_ABORT" : "", type);
                return TCM_INVALID_CDB_FIELD;
        }
 }
@@ -3220,7 +3077,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
        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, matching_iname, prf_isid;
+       int new_reg = 0, type, scope, matching_iname;
        sense_reason_t ret;
        unsigned short rtpi;
        unsigned char proto_ident;
@@ -3564,8 +3421,7 @@ after_iport_check:
        dest_pr_reg->pr_res_holder = 1;
        dest_pr_reg->pr_res_type = type;
        pr_reg->pr_res_scope = scope;
-       prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
-                               PR_REG_ISID_ID_LEN);
+       core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
        /*
         * Increment PRGeneration for existing registrations..
         */
@@ -3581,7 +3437,7 @@ after_iport_check:
        pr_debug("SPC-3 PR Successfully moved reservation from"
                " %s Fabric Node: %s%s -> %s Fabric Node: %s %s\n",
                tf_ops->get_fabric_name(), pr_reg_nacl->initiatorname,
-               (prf_isid) ? &i_buf[0] : "", dest_tf_ops->get_fabric_name(),
+               i_buf, dest_tf_ops->get_fabric_name(),
                dest_node_acl->initiatorname, (iport_ptr != NULL) ?
                iport_ptr : "");
        /*
@@ -3602,24 +3458,7 @@ after_iport_check:
        } else
                core_scsi3_put_pr_reg(pr_reg);
 
-       /*
-        * Clear the APTPL metadata if APTPL has been disabled, otherwise
-        * write out the updated metadata to struct file for this SCSI device.
-        */
-       if (!aptpl) {
-               pr_tmpl->pr_aptpl_active = 0;
-               core_scsi3_update_and_write_aptpl(cmd->se_dev, NULL, 0);
-               pr_debug("SPC-3 PR: Set APTPL Bit Deactivated for"
-                               " REGISTER_AND_MOVE\n");
-       } else {
-               pr_tmpl->pr_aptpl_active = 1;
-               if (!core_scsi3_update_and_write_aptpl(cmd->se_dev,
-                               &dest_pr_reg->pr_aptpl_buf[0],
-                               pr_tmpl->pr_aptpl_buf_len)) {
-                       pr_debug("SPC-3 PR: Set APTPL Bit Activated for"
-                                       " REGISTER_AND_MOVE\n");
-               }
-       }
+       core_scsi3_update_and_write_aptpl(cmd->se_dev, aptpl);
 
        transport_kunmap_data_sg(cmd);
 
@@ -3752,7 +3591,7 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd)
        switch (sa) {
        case PRO_REGISTER:
                ret = core_scsi3_emulate_pro_register(cmd,
-                       res_key, sa_res_key, aptpl, all_tg_pt, spec_i_pt, 0);
+                       res_key, sa_res_key, aptpl, all_tg_pt, spec_i_pt, REGISTER);
                break;
        case PRO_RESERVE:
                ret = core_scsi3_emulate_pro_reserve(cmd, type, scope, res_key);
@@ -3765,15 +3604,15 @@ target_scsi3_emulate_pr_out(struct se_cmd *cmd)
                break;
        case PRO_PREEMPT:
                ret = core_scsi3_emulate_pro_preempt(cmd, type, scope,
-                                       res_key, sa_res_key, 0);
+                                       res_key, sa_res_key, PREEMPT);
                break;
        case PRO_PREEMPT_AND_ABORT:
                ret = core_scsi3_emulate_pro_preempt(cmd, type, scope,
-                                       res_key, sa_res_key, 1);
+                                       res_key, sa_res_key, PREEMPT_AND_ABORT);
                break;
        case PRO_REGISTER_AND_IGNORE_EXISTING_KEY:
                ret = core_scsi3_emulate_pro_register(cmd,
-                       0, sa_res_key, aptpl, all_tg_pt, spec_i_pt, 1);
+                       0, sa_res_key, aptpl, all_tg_pt, spec_i_pt, REGISTER_AND_IGNORE_EXISTING_KEY);
                break;
        case PRO_REGISTER_AND_MOVE:
                ret = core_scsi3_emulate_pro_register_and_move(cmd, res_key,