return NULL;
}
- pr_reg->pr_aptpl_buf = kzalloc(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);
pr_err("Unable to allocate struct t10_pr_registration\n");
return -ENOMEM;
}
- pr_reg->pr_aptpl_buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
INIT_LIST_HEAD(&pr_reg->pr_reg_list);
INIT_LIST_HEAD(&pr_reg->pr_reg_abort_list);
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;
}
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);
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)
int reg_count = 0;
int ret = 0;
- memset(buf, 0, pr_aptpl_buf_len);
-
spin_lock(&dev->dev_reservation_lock);
spin_lock(&dev->t10_pr.registration_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)
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;
- int ret;
+ unsigned char *buf;
+ int rc;
- /*
- * Can be called with a NULL pointer from PROUT service action CLEAR
- */
- if (!in_buf) {
- snprintf(null_buf, 64, "No Registrations or Reservations\n");
- buf = null_buf;
- } else {
- ret = core_scsi3_update_aptpl_buf(dev, in_buf, in_pr_aptpl_buf_len);
- if (ret != 0)
- return ret;
- buf = in_buf;
+ 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;
}
- /*
- * __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);
+ buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
+ if (!buf)
+ return TCM_OUT_OF_RESOURCES;
+
+ 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, enum register_type register_type)
+ 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");
/*
* 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");
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, 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 (register_type == REGISTER) {
- 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 REGISTER: SPEC_I_PT"
" set on a registered nexus\n");
ret = TCM_INVALID_PARAMETER_LIST;
- goto out_put_pr_reg;
+ goto out;
}
/*
" 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_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);
* 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) {
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, 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(),
- (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);
- 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, 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;
}
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, 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:
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, 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;
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;
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);
}
}
}
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, PR_APTPL_BUF_LEN)) {
- pr_debug("SPC-3 PR: Updated APTPL"
- " metadata for PREEMPT%s\n", (preempt_type == PREEMPT_AND_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);
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, PR_APTPL_BUF_LEN)) {
- pr_debug("SPC-3 PR: Updated APTPL metadata for PREEMPT"
- "%s\n", (preempt_type == PREEMPT_AND_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);
} 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, 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);