target/pr: Change alloc_registration to avoid pr_reg_tg_pt_lun

This patch changes __core_scsi3_do_alloc_registration() code to
drop pr_reg->pr_reg_tg_pt_lun pointer usage in favor of a new
pr_reg RPTI + existing pr_reg->pr_aptpl_target_lun used by
APTPL metadata logic.

It also includes changes to REGISTER, REGISTER_AND_MOVE and APTPL
feature bit codepaths to use rcu_dereference_check() with the
expected non-zero se_dev_entry->pr_kref reference held.

Reviewed-by: Hannes Reinecke <hare@suse.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Nicholas Bellinger 2015-03-27 04:51:03 +00:00
parent 80bfdfa924
commit 79dc9c9e86
3 changed files with 72 additions and 69 deletions

View file

@ -817,7 +817,6 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
struct se_device *dev, char *page) struct se_device *dev, char *page)
{ {
struct se_node_acl *se_nacl; struct se_node_acl *se_nacl;
struct se_lun *lun;
struct se_portal_group *se_tpg; struct se_portal_group *se_tpg;
struct t10_pr_registration *pr_reg; struct t10_pr_registration *pr_reg;
const struct target_core_fabric_ops *tfo; const struct target_core_fabric_ops *tfo;
@ -832,7 +831,6 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
se_nacl = pr_reg->pr_reg_nacl; se_nacl = pr_reg->pr_reg_nacl;
se_tpg = se_nacl->se_tpg; se_tpg = se_nacl->se_tpg;
lun = pr_reg->pr_reg_tg_pt_lun;
tfo = se_tpg->se_tpg_tfo; tfo = se_tpg->se_tpg_tfo;
len += sprintf(page+len, "SPC-3 Reservation: %s" len += sprintf(page+len, "SPC-3 Reservation: %s"
@ -840,9 +838,9 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
tfo->tpg_get_wwn(se_tpg)); tfo->tpg_get_wwn(se_tpg));
len += sprintf(page+len, "SPC-3 Reservation: Relative Port" len += sprintf(page+len, "SPC-3 Reservation: Relative Port"
" Identifier Tag: %hu %s Portal Group Tag: %hu" " Identifier Tag: %hu %s Portal Group Tag: %hu"
" %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi, " %s Logical Unit: %u\n", pr_reg->tg_pt_sep_rtpi,
tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg), tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg),
tfo->get_fabric_name(), lun->unpacked_lun); tfo->get_fabric_name(), pr_reg->pr_aptpl_target_lun);
out_unlock: out_unlock:
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);

View file

@ -44,11 +44,10 @@
* Used for Specify Initiator Ports Capable Bit (SPEC_I_PT) * Used for Specify Initiator Ports Capable Bit (SPEC_I_PT)
*/ */
struct pr_transport_id_holder { struct pr_transport_id_holder {
int dest_local_nexus;
struct t10_pr_registration *dest_pr_reg; struct t10_pr_registration *dest_pr_reg;
struct se_portal_group *dest_tpg; struct se_portal_group *dest_tpg;
struct se_node_acl *dest_node_acl; struct se_node_acl *dest_node_acl;
struct se_dev_entry __rcu *dest_se_deve; struct se_dev_entry *dest_se_deve;
struct list_head dest_list; struct list_head dest_list;
}; };
@ -625,7 +624,9 @@ static u32 core_scsi3_pr_generation(struct se_device *dev)
static struct t10_pr_registration *__core_scsi3_do_alloc_registration( static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
struct se_device *dev, struct se_device *dev,
struct se_node_acl *nacl, struct se_node_acl *nacl,
struct se_lun *lun,
struct se_dev_entry *deve, struct se_dev_entry *deve,
u32 mapped_lun,
unsigned char *isid, unsigned char *isid,
u64 sa_res_key, u64 sa_res_key,
int all_tg_pt, int all_tg_pt,
@ -647,12 +648,12 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
atomic_set(&pr_reg->pr_res_holders, 0); atomic_set(&pr_reg->pr_res_holders, 0);
pr_reg->pr_reg_nacl = nacl; pr_reg->pr_reg_nacl = nacl;
pr_reg->pr_reg_deve = deve; pr_reg->pr_reg_deve = deve;
pr_reg->pr_res_mapped_lun = deve->mapped_lun; pr_reg->pr_res_mapped_lun = mapped_lun;
pr_reg->pr_aptpl_target_lun = deve->se_lun->unpacked_lun; pr_reg->pr_aptpl_target_lun = lun->unpacked_lun;
pr_reg->tg_pt_sep_rtpi = lun->lun_sep->sep_rtpi;
pr_reg->pr_res_key = sa_res_key; pr_reg->pr_res_key = sa_res_key;
pr_reg->pr_reg_all_tg_pt = all_tg_pt; pr_reg->pr_reg_all_tg_pt = all_tg_pt;
pr_reg->pr_reg_aptpl = aptpl; pr_reg->pr_reg_aptpl = aptpl;
pr_reg->pr_reg_tg_pt_lun = deve->se_lun;
/* /*
* If an ISID value for this SCSI Initiator Port exists, * If an ISID value for this SCSI Initiator Port exists,
* save it to the registration now. * save it to the registration now.
@ -676,7 +677,9 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *);
static struct t10_pr_registration *__core_scsi3_alloc_registration( static struct t10_pr_registration *__core_scsi3_alloc_registration(
struct se_device *dev, struct se_device *dev,
struct se_node_acl *nacl, struct se_node_acl *nacl,
struct se_lun *lun,
struct se_dev_entry *deve, struct se_dev_entry *deve,
u32 mapped_lun,
unsigned char *isid, unsigned char *isid,
u64 sa_res_key, u64 sa_res_key,
int all_tg_pt, int all_tg_pt,
@ -684,6 +687,8 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
{ {
struct se_dev_entry *deve_tmp; struct se_dev_entry *deve_tmp;
struct se_node_acl *nacl_tmp; struct se_node_acl *nacl_tmp;
struct se_lun_acl *lacl_tmp;
struct se_lun *lun_tmp;
struct se_port *port, *port_tmp; struct se_port *port, *port_tmp;
const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo; const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
struct t10_pr_registration *pr_reg, *pr_reg_atp, *pr_reg_tmp, *pr_reg_tmp_safe; struct t10_pr_registration *pr_reg, *pr_reg_atp, *pr_reg_tmp, *pr_reg_tmp_safe;
@ -692,8 +697,9 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
* Create a registration for the I_T Nexus upon which the * Create a registration for the I_T Nexus upon which the
* PROUT REGISTER was received. * PROUT REGISTER was received.
*/ */
pr_reg = __core_scsi3_do_alloc_registration(dev, nacl, deve, isid, pr_reg = __core_scsi3_do_alloc_registration(dev, nacl, lun, deve, mapped_lun,
sa_res_key, all_tg_pt, aptpl); isid, sa_res_key, all_tg_pt,
aptpl);
if (!pr_reg) if (!pr_reg)
return NULL; return NULL;
/* /*
@ -721,7 +727,9 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
if (!deve_tmp->se_lun_acl) if (!deve_tmp->se_lun_acl)
continue; continue;
nacl_tmp = deve_tmp->se_lun_acl->se_lun_nacl; lacl_tmp = rcu_dereference_check(deve_tmp->se_lun_acl,
lockdep_is_held(&port->sep_alua_lock));
nacl_tmp = lacl_tmp->se_lun_nacl;
/* /*
* Skip the matching struct se_node_acl that is allocated * Skip the matching struct se_node_acl that is allocated
* above.. * above..
@ -764,8 +772,12 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
* the original *pr_reg is processed in * the original *pr_reg is processed in
* __core_scsi3_add_registration() * __core_scsi3_add_registration()
*/ */
lun_tmp = rcu_dereference_check(deve_tmp->se_lun,
atomic_read(&deve_tmp->pr_kref.refcount) != 0);
pr_reg_atp = __core_scsi3_do_alloc_registration(dev, pr_reg_atp = __core_scsi3_do_alloc_registration(dev,
nacl_tmp, deve_tmp, NULL, nacl_tmp, lun_tmp, deve_tmp,
deve_tmp->mapped_lun, NULL,
sa_res_key, all_tg_pt, aptpl); sa_res_key, all_tg_pt, aptpl);
if (!pr_reg_atp) { if (!pr_reg_atp) {
atomic_dec_mb(&port->sep_tg_pt_ref_cnt); atomic_dec_mb(&port->sep_tg_pt_ref_cnt);
@ -835,7 +847,6 @@ int core_scsi3_alloc_aptpl_registration(
pr_reg->pr_res_key = sa_res_key; pr_reg->pr_res_key = sa_res_key;
pr_reg->pr_reg_all_tg_pt = all_tg_pt; pr_reg->pr_reg_all_tg_pt = all_tg_pt;
pr_reg->pr_reg_aptpl = 1; pr_reg->pr_reg_aptpl = 1;
pr_reg->pr_reg_tg_pt_lun = NULL;
pr_reg->pr_res_scope = 0; /* Always LUN_SCOPE */ pr_reg->pr_res_scope = 0; /* Always LUN_SCOPE */
pr_reg->pr_res_type = type; pr_reg->pr_res_type = type;
/* /*
@ -935,7 +946,7 @@ static int __core_scsi3_check_aptpl_registration(
(pr_reg->pr_aptpl_target_lun == target_lun)) { (pr_reg->pr_aptpl_target_lun == target_lun)) {
pr_reg->pr_reg_nacl = nacl; pr_reg->pr_reg_nacl = nacl;
pr_reg->pr_reg_tg_pt_lun = lun; pr_reg->tg_pt_sep_rtpi = lun->lun_sep->sep_rtpi;
list_del(&pr_reg->pr_reg_aptpl_list); list_del(&pr_reg->pr_reg_aptpl_list);
spin_unlock(&pr_tmpl->aptpl_reg_lock); spin_unlock(&pr_tmpl->aptpl_reg_lock);
@ -1090,7 +1101,9 @@ static void __core_scsi3_add_registration(
static int core_scsi3_alloc_registration( static int core_scsi3_alloc_registration(
struct se_device *dev, struct se_device *dev,
struct se_node_acl *nacl, struct se_node_acl *nacl,
struct se_lun *lun,
struct se_dev_entry *deve, struct se_dev_entry *deve,
u32 mapped_lun,
unsigned char *isid, unsigned char *isid,
u64 sa_res_key, u64 sa_res_key,
int all_tg_pt, int all_tg_pt,
@ -1100,8 +1113,9 @@ static int core_scsi3_alloc_registration(
{ {
struct t10_pr_registration *pr_reg; struct t10_pr_registration *pr_reg;
pr_reg = __core_scsi3_alloc_registration(dev, nacl, deve, isid, pr_reg = __core_scsi3_alloc_registration(dev, nacl, lun, deve, mapped_lun,
sa_res_key, all_tg_pt, aptpl); isid, sa_res_key, all_tg_pt,
aptpl);
if (!pr_reg) if (!pr_reg)
return -EPERM; return -EPERM;
@ -1411,12 +1425,14 @@ static void core_scsi3_nodeacl_undepend_item(struct se_node_acl *nacl)
static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve) static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
{ {
struct se_lun_acl *lun_acl = se_deve->se_lun_acl; struct se_lun_acl *lun_acl;
struct se_node_acl *nacl; struct se_node_acl *nacl;
struct se_portal_group *tpg; struct se_portal_group *tpg;
/* /*
* For nacl->dynamic_node_acl=1 * For nacl->dynamic_node_acl=1
*/ */
lun_acl = rcu_dereference_check(se_deve->se_lun_acl,
atomic_read(&se_deve->pr_kref.refcount) != 0);
if (!lun_acl) if (!lun_acl)
return 0; return 0;
@ -1434,7 +1450,8 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
/* /*
* For nacl->dynamic_node_acl=1 * For nacl->dynamic_node_acl=1
*/ */
lun_acl = se_deve->se_lun_acl; lun_acl = rcu_dereference_check(se_deve->se_lun_acl,
atomic_read(&se_deve->pr_kref.refcount) != 0);
if (!lun_acl) { if (!lun_acl) {
kref_put(&se_deve->pr_kref, target_pr_kref_release); kref_put(&se_deve->pr_kref, target_pr_kref_release);
return; return;
@ -1450,7 +1467,6 @@ static sense_reason_t
core_scsi3_decode_spec_i_port( core_scsi3_decode_spec_i_port(
struct se_cmd *cmd, struct se_cmd *cmd,
struct se_portal_group *tpg, struct se_portal_group *tpg,
struct se_dev_entry *local_se_deve,
unsigned char *l_isid, unsigned char *l_isid,
u64 sa_res_key, u64 sa_res_key,
int all_tg_pt, int all_tg_pt,
@ -1461,7 +1477,7 @@ core_scsi3_decode_spec_i_port(
struct se_portal_group *dest_tpg = NULL, *tmp_tpg; struct se_portal_group *dest_tpg = NULL, *tmp_tpg;
struct se_session *se_sess = cmd->se_sess; struct se_session *se_sess = cmd->se_sess;
struct se_node_acl *dest_node_acl = NULL; struct se_node_acl *dest_node_acl = NULL;
struct se_dev_entry __rcu *dest_se_deve = NULL; struct se_dev_entry *dest_se_deve = NULL;
struct t10_pr_registration *dest_pr_reg, *local_pr_reg, *pr_reg_e; struct t10_pr_registration *dest_pr_reg, *local_pr_reg, *pr_reg_e;
struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe; struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
LIST_HEAD(tid_dest_list); LIST_HEAD(tid_dest_list);
@ -1471,14 +1487,12 @@ core_scsi3_decode_spec_i_port(
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN]; char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
sense_reason_t ret; sense_reason_t ret;
u32 tpdl, tid_len = 0; u32 tpdl, tid_len = 0;
int dest_local_nexus;
u32 dest_rtpi = 0; u32 dest_rtpi = 0;
/* /*
* Allocate a struct pr_transport_id_holder and setup the * Allocate a struct pr_transport_id_holder and setup the
* local_node_acl and local_se_deve pointers and add to * local_node_acl pointer and add to struct list_head tid_dest_list
* struct list_head tid_dest_list for add registration * for add registration processing in the loop of tid_dest_list below.
* processing in the loop of tid_dest_list below.
*/ */
tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL); tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL);
if (!tidh_new) { if (!tidh_new) {
@ -1490,20 +1504,20 @@ core_scsi3_decode_spec_i_port(
tidh_new->dest_node_acl = se_sess->se_node_acl; tidh_new->dest_node_acl = se_sess->se_node_acl;
local_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev, local_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
se_sess->se_node_acl, local_se_deve, l_isid, se_sess->se_node_acl, cmd->se_lun,
NULL, cmd->orig_fe_lun, l_isid,
sa_res_key, all_tg_pt, aptpl); sa_res_key, all_tg_pt, aptpl);
if (!local_pr_reg) { if (!local_pr_reg) {
kfree(tidh_new); kfree(tidh_new);
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
rcu_assign_pointer(tidh_new->dest_se_deve, local_se_deve);
tidh_new->dest_pr_reg = local_pr_reg; tidh_new->dest_pr_reg = local_pr_reg;
/* /*
* The local I_T nexus does not hold any configfs dependances, * The local I_T nexus does not hold any configfs dependances,
* so we set tid_h->dest_local_nexus=1 to prevent the * so we set tidh_new->dest_se_deve to NULL to prevent the
* configfs_undepend_item() calls in the tid_dest_list loops below. * configfs_undepend_item() calls in the tid_dest_list loops below.
*/ */
tidh_new->dest_local_nexus = 1; tidh_new->dest_se_deve = NULL;
list_add_tail(&tidh_new->dest_list, &tid_dest_list); list_add_tail(&tidh_new->dest_list, &tid_dest_list);
if (cmd->data_length < 28) { if (cmd->data_length < 28) {
@ -1544,6 +1558,8 @@ core_scsi3_decode_spec_i_port(
ptr = &buf[28]; ptr = &buf[28];
while (tpdl > 0) { while (tpdl > 0) {
struct se_lun *dest_lun;
proto_ident = (ptr[0] & 0x0f); proto_ident = (ptr[0] & 0x0f);
dest_tpg = NULL; dest_tpg = NULL;
@ -1720,9 +1736,13 @@ core_scsi3_decode_spec_i_port(
* and then call __core_scsi3_add_registration() in the * and then call __core_scsi3_add_registration() in the
* 2nd loop which will never fail. * 2nd loop which will never fail.
*/ */
dest_lun = rcu_dereference_check(dest_se_deve->se_lun,
atomic_read(&dest_se_deve->pr_kref.refcount) != 0);
dest_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev, dest_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
dest_node_acl, dest_se_deve, iport_ptr, dest_node_acl, dest_lun, dest_se_deve,
sa_res_key, all_tg_pt, aptpl); dest_se_deve->mapped_lun, iport_ptr,
sa_res_key, all_tg_pt, aptpl);
if (!dest_pr_reg) { if (!dest_pr_reg) {
core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_lunacl_undepend_item(dest_se_deve);
core_scsi3_nodeacl_undepend_item(dest_node_acl); core_scsi3_nodeacl_undepend_item(dest_node_acl);
@ -1760,7 +1780,6 @@ core_scsi3_decode_spec_i_port(
dest_node_acl = tidh->dest_node_acl; dest_node_acl = tidh->dest_node_acl;
dest_se_deve = tidh->dest_se_deve; dest_se_deve = tidh->dest_se_deve;
dest_pr_reg = tidh->dest_pr_reg; dest_pr_reg = tidh->dest_pr_reg;
dest_local_nexus = tidh->dest_local_nexus;
list_del(&tidh->dest_list); list_del(&tidh->dest_list);
kfree(tidh); kfree(tidh);
@ -1774,9 +1793,10 @@ core_scsi3_decode_spec_i_port(
pr_debug("SPC-3 PR [%s] SPEC_I_PT: Successfully" pr_debug("SPC-3 PR [%s] SPEC_I_PT: Successfully"
" registered Transport ID for Node: %s%s Mapped LUN:" " registered Transport ID for Node: %s%s Mapped LUN:"
" %u\n", dest_tpg->se_tpg_tfo->get_fabric_name(), " %u\n", dest_tpg->se_tpg_tfo->get_fabric_name(),
dest_node_acl->initiatorname, i_buf, dest_se_deve->mapped_lun); dest_node_acl->initiatorname, i_buf, (dest_se_deve) ?
dest_se_deve->mapped_lun : 0);
if (dest_local_nexus) if (!dest_se_deve)
continue; continue;
core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_lunacl_undepend_item(dest_se_deve);
@ -1797,7 +1817,6 @@ core_scsi3_decode_spec_i_port(
dest_node_acl = tidh->dest_node_acl; dest_node_acl = tidh->dest_node_acl;
dest_se_deve = tidh->dest_se_deve; dest_se_deve = tidh->dest_se_deve;
dest_pr_reg = tidh->dest_pr_reg; dest_pr_reg = tidh->dest_pr_reg;
dest_local_nexus = tidh->dest_local_nexus;
list_del(&tidh->dest_list); list_del(&tidh->dest_list);
kfree(tidh); kfree(tidh);
@ -1815,7 +1834,7 @@ core_scsi3_decode_spec_i_port(
kmem_cache_free(t10_pr_reg_cache, dest_pr_reg); kmem_cache_free(t10_pr_reg_cache, dest_pr_reg);
if (dest_local_nexus) if (!dest_se_deve)
continue; continue;
core_scsi3_lunacl_undepend_item(dest_se_deve); core_scsi3_lunacl_undepend_item(dest_se_deve);
@ -1830,7 +1849,6 @@ static int core_scsi3_update_aptpl_buf(
unsigned char *buf, unsigned char *buf,
u32 pr_aptpl_buf_len) u32 pr_aptpl_buf_len)
{ {
struct se_lun *lun;
struct se_portal_group *tpg; struct se_portal_group *tpg;
struct t10_pr_registration *pr_reg; struct t10_pr_registration *pr_reg;
unsigned char tmp[512], isid_buf[32]; unsigned char tmp[512], isid_buf[32];
@ -1849,7 +1867,6 @@ static int core_scsi3_update_aptpl_buf(
tmp[0] = '\0'; tmp[0] = '\0';
isid_buf[0] = '\0'; isid_buf[0] = '\0';
tpg = pr_reg->pr_reg_nacl->se_tpg; tpg = pr_reg->pr_reg_nacl->se_tpg;
lun = pr_reg->pr_reg_tg_pt_lun;
/* /*
* Write out any ISID value to APTPL metadata that was included * Write out any ISID value to APTPL metadata that was included
* in the original registration. * in the original registration.
@ -1901,7 +1918,8 @@ static int core_scsi3_update_aptpl_buf(
" %d\n", tpg->se_tpg_tfo->get_fabric_name(), " %d\n", tpg->se_tpg_tfo->get_fabric_name(),
tpg->se_tpg_tfo->tpg_get_wwn(tpg), tpg->se_tpg_tfo->tpg_get_wwn(tpg),
tpg->se_tpg_tfo->tpg_get_tag(tpg), tpg->se_tpg_tfo->tpg_get_tag(tpg),
lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count); pr_reg->tg_pt_sep_rtpi, pr_reg->pr_aptpl_target_lun,
reg_count);
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
pr_err("Unable to update renaming APTPL metadata," pr_err("Unable to update renaming APTPL metadata,"
@ -2011,9 +2029,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
bool aptpl, bool all_tg_pt, bool 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_session *se_sess = cmd->se_sess;
struct se_node_acl *nacl = se_sess->se_node_acl;
struct se_device *dev = cmd->se_dev; struct se_device *dev = cmd->se_dev;
struct se_dev_entry *se_deve;
struct se_lun *se_lun = cmd->se_lun; struct se_lun *se_lun = cmd->se_lun;
struct se_portal_group *se_tpg; struct se_portal_group *se_tpg;
struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp; struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp;
@ -2028,14 +2044,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
} }
se_tpg = se_sess->se_tpg; se_tpg = se_sess->se_tpg;
rcu_read_lock();
se_deve = target_nacl_find_deve(nacl, cmd->orig_fe_lun);
if (!se_deve) {
pr_err("Unable to locate se_deve for PRO-REGISTER\n");
rcu_read_unlock();
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
if (se_tpg->se_tpg_tfo->sess_get_initiator_sid) { if (se_tpg->se_tpg_tfo->sess_get_initiator_sid) {
memset(&isid_buf[0], 0, PR_REG_ISID_LEN); memset(&isid_buf[0], 0, PR_REG_ISID_LEN);
se_tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess, &isid_buf[0], se_tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess, &isid_buf[0],
@ -2050,16 +2058,14 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
if (res_key) { if (res_key) {
pr_warn("SPC-3 PR: Reservation Key non-zero" pr_warn("SPC-3 PR: Reservation Key non-zero"
" for SA REGISTER, returning CONFLICT\n"); " for SA REGISTER, returning CONFLICT\n");
rcu_read_unlock();
return TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
} }
/* /*
* Do nothing but return GOOD status. * Do nothing but return GOOD status.
*/ */
if (!sa_res_key) { if (!sa_res_key)
rcu_read_unlock();
return 0; return 0;
}
if (!spec_i_pt) { if (!spec_i_pt) {
/* /*
* Perform the Service Action REGISTER on the Initiator * Perform the Service Action REGISTER on the Initiator
@ -2067,12 +2073,12 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
* Logical Unit of the SCSI device server. * Logical Unit of the SCSI device server.
*/ */
if (core_scsi3_alloc_registration(cmd->se_dev, if (core_scsi3_alloc_registration(cmd->se_dev,
se_sess->se_node_acl, se_deve, isid_ptr, se_sess->se_node_acl, cmd->se_lun,
NULL, cmd->orig_fe_lun, isid_ptr,
sa_res_key, all_tg_pt, aptpl, sa_res_key, all_tg_pt, aptpl,
register_type, 0)) { register_type, 0)) {
pr_err("Unable to allocate" pr_err("Unable to allocate"
" struct t10_pr_registration\n"); " struct t10_pr_registration\n");
rcu_read_unlock();
return TCM_INVALID_PARAMETER_LIST; return TCM_INVALID_PARAMETER_LIST;
} }
} else { } else {
@ -2084,17 +2090,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
* logic from of core_scsi3_alloc_registration() for * logic from of core_scsi3_alloc_registration() for
* each TransportID provided SCSI Initiator Port/Device * each TransportID provided SCSI Initiator Port/Device
*/ */
ret = core_scsi3_decode_spec_i_port(cmd, se_tpg, se_deve, ret = core_scsi3_decode_spec_i_port(cmd, se_tpg,
isid_ptr, sa_res_key, all_tg_pt, aptpl); isid_ptr, sa_res_key, all_tg_pt, aptpl);
if (ret != 0) { if (ret != 0)
rcu_read_unlock();
return ret; return ret;
}
} }
rcu_read_unlock();
return core_scsi3_update_and_write_aptpl(dev, aptpl); return core_scsi3_update_and_write_aptpl(dev, aptpl);
} }
rcu_read_unlock();
/* ok, existing registration */ /* ok, existing registration */
@ -3440,10 +3442,13 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl, dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
iport_ptr); iport_ptr);
if (!dest_pr_reg) { if (!dest_pr_reg) {
struct se_lun *dest_lun = rcu_dereference_check(dest_se_deve->se_lun,
atomic_read(&dest_se_deve->pr_kref.refcount) != 0);
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
if (core_scsi3_alloc_registration(cmd->se_dev, if (core_scsi3_alloc_registration(cmd->se_dev, dest_node_acl,
dest_node_acl, dest_se_deve, iport_ptr, dest_lun, dest_se_deve, dest_se_deve->mapped_lun,
sa_res_key, 0, aptpl, 2, 1)) { iport_ptr, sa_res_key, 0, aptpl, 2, 1)) {
ret = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;
goto out; goto out;
} }
@ -4011,10 +4016,10 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
* IDENTIFIER field are not defined by this standard. * IDENTIFIER field are not defined by this standard.
*/ */
if (!pr_reg->pr_reg_all_tg_pt) { if (!pr_reg->pr_reg_all_tg_pt) {
struct se_port *port = pr_reg->pr_reg_tg_pt_lun->lun_sep; u16 sep_rtpi = pr_reg->tg_pt_sep_rtpi;
buf[off++] = ((port->sep_rtpi >> 8) & 0xff); buf[off++] = ((sep_rtpi >> 8) & 0xff);
buf[off++] = (port->sep_rtpi & 0xff); buf[off++] = (sep_rtpi & 0xff);
} else } else
off += 2; /* Skip over RELATIVE TARGET PORT IDENTIFIER */ off += 2; /* Skip over RELATIVE TARGET PORT IDENTIFIER */

View file

@ -372,13 +372,14 @@ struct t10_pr_registration {
bool isid_present_at_reg; bool isid_present_at_reg;
u32 pr_res_mapped_lun; u32 pr_res_mapped_lun;
u32 pr_aptpl_target_lun; u32 pr_aptpl_target_lun;
u16 tg_pt_sep_rtpi;
u32 pr_res_generation; u32 pr_res_generation;
u64 pr_reg_bin_isid; u64 pr_reg_bin_isid;
u64 pr_res_key; u64 pr_res_key;
atomic_t pr_res_holders; atomic_t pr_res_holders;
struct se_node_acl *pr_reg_nacl; struct se_node_acl *pr_reg_nacl;
/* Used by ALL_TG_PT=1 registration with deve->pr_ref taken */
struct se_dev_entry *pr_reg_deve; struct se_dev_entry *pr_reg_deve;
struct se_lun *pr_reg_tg_pt_lun;
struct list_head pr_reg_list; struct list_head pr_reg_list;
struct list_head pr_reg_abort_list; struct list_head pr_reg_abort_list;
struct list_head pr_reg_aptpl_list; struct list_head pr_reg_aptpl_list;
@ -498,7 +499,6 @@ struct se_cmd {
struct list_head se_delayed_node; struct list_head se_delayed_node;
struct list_head se_qf_node; struct list_head se_qf_node;
struct se_device *se_dev; struct se_device *se_dev;
struct se_dev_entry *se_deve;
struct se_lun *se_lun; struct se_lun *se_lun;
/* Only used for internal passthrough and legacy TCM fabric modules */ /* Only used for internal passthrough and legacy TCM fabric modules */
struct se_session *se_sess; struct se_session *se_sess;