diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-11 12:57:19 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-11 12:57:19 -0700 |
| commit | 6d2fa9e141ea56a571ec842fd4f3a86bea44a203 (patch) | |
| tree | e419f95b7d080046f0f4d4d5041b42a0889f2f0a /drivers/target/target_core_pr.c | |
| parent | 0fb3767b0a5601dd0d528bc8dbefc0567a34b7ec (diff) | |
| parent | ca40d24eb8fc3c194b4439493ecf6b2d703812b8 (diff) | |
| download | linux-next-6d2fa9e141ea56a571ec842fd4f3a86bea44a203.tar.gz linux-next-6d2fa9e141ea56a571ec842fd4f3a86bea44a203.zip | |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger:
"Lots of activity this round on performance improvements in target-core
while benchmarking the prototype scsi-mq initiator code with
vhost-scsi fabric ports, along with a number of iscsi/iser-target
improvements and hardening fixes for exception path cases post v3.10
merge.
The highlights include:
- Make persistent reservations APTPL buffer allocated on-demand, and
drop per t10_reservation buffer. (grover)
- Make virtual LUN=0 a NULLIO device, and skip allocation of NULLIO
device pages (grover)
- Add transport_cmd_check_stop write_pending bit to avoid extra
access of ->t_state_lock is WRITE I/O submission fast-path. (nab)
- Drop unnecessary CMD_T_DEV_ACTIVE check from
transport_lun_remove_cmd to avoid extra access of ->t_state_lock in
release fast-path. (nab)
- Avoid extra t_state_lock access in __target_execute_cmd fast-path
(nab)
- Drop unnecessary vhost-scsi wait_for_tasks=true usage +
->t_state_lock access in release fast-path. (nab)
- Convert vhost-scsi to use modern se_cmd->cmd_kref
TARGET_SCF_ACK_KREF usage (nab)
- Add tracepoints for SCSI commands being processed (roland)
- Refactoring of iscsi-target handling of ISCSI_OP_NOOP +
ISCSI_OP_TEXT to be transport independent (nab)
- Add iscsi-target SendTargets=$IQN support for in-band discovery
(nab)
- Add iser-target support for in-band discovery (nab + Or)
- Add iscsi-target demo-mode TPG authentication context support (nab)
- Fix isert_put_reject payload buffer post (nab)
- Fix iscsit_add_reject* usage for iser (nab)
- Fix iscsit_sequence_cmd reject handling for iser (nab)
- Fix ISCSI_OP_SCSI_TMFUNC handling for iser (nab)
- Fix session reset bug with RDMA_CM_EVENT_DISCONNECTED (nab)
The last five iscsi/iser-target items are CC'ed to stable, as they do
address issues present in v3.10 code. They are certainly larger than
I'd like for stable patch set, but are important to ensure proper
REJECT exception handling in iser-target for 3.10.y"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (51 commits)
iser-target: Ignore non TEXT + LOGOUT opcodes for discovery
target: make queue_tm_rsp() return void
target: remove unused codes from enum tcm_tmrsp_table
iscsi-target: kstrtou* configfs attribute parameter cleanups
iscsi-target: Fix tfc_tpg_auth_cit configfs length overflow
iscsi-target: Fix tfc_tpg_nacl_auth_cit configfs length overflow
iser-target: Add support for ISCSI_OP_TEXT opcode + payload handling
iser-target: Rename sense_buf_[dma,len] to pdu_[dma,len]
iser-target: Add vendor_err debug output
target: Add (obsolete) checking for PMI/LBA fields in READ CAPACITY(10)
target: Return correct sense data for IO past the end of a device
target: Add tracepoints for SCSI commands being processed
iser-target: Fix session reset bug with RDMA_CM_EVENT_DISCONNECTED
iscsi-target: Fix ISCSI_OP_SCSI_TMFUNC handling for iser
iscsi-target: Fix iscsit_sequence_cmd reject handling for iser
iscsi-target: Fix iscsit_add_reject* usage for iser
iser-target: Fix isert_put_reject payload buffer post
iscsi-target: missing kfree() on error path
iscsi-target: Drop left-over iscsi_conn->bad_hdr
target: Make core_scsi3_update_and_write_aptpl return sense_reason_t
...
Diffstat (limited to 'drivers/target/target_core_pr.c')
| -rw-r--r-- | drivers/target/target_core_pr.c | 499 |
1 files changed, 169 insertions, 330 deletions
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 3240f2cc81ef..bd78faf67c6b 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -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, |
