diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-22 20:41:14 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-22 20:41:14 +0100 |
commit | 5266e5b12c8b73587130325f7074d2f49ef9e427 (patch) | |
tree | 79abfbf1b047de05860fa832f66fce5078cc6434 /drivers/scsi | |
parent | Merge tag 'pci-v4.6-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git... (diff) | |
parent | target: Fix target_release_cmd_kref shutdown comp leak (diff) | |
download | linux-5266e5b12c8b73587130325f7074d2f49ef9e427.tar.xz linux-5266e5b12c8b73587130325f7074d2f49ef9e427.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:
"The highlights this round include:
- Add target_alloc_session() w/ callback helper for doing se_session
allocation + tag + se_node_acl lookup. (HCH + nab)
- Tree-wide fabric driver conversion to use target_alloc_session()
- Convert sbp-target to use percpu_ida tag pre-allocation, and
TARGET_SCF_ACK_KREF I/O krefs (Chris Boot + nab)
- Convert usb-gadget to use percpu_ida tag pre-allocation, and
TARGET_SCF_ACK_KREF I/O krefs (Andrzej Pietrasiewicz + nab)
- Convert xen-scsiback to use percpu_ida tag pre-allocation, and
TARGET_SCF_ACK_KREF I/O krefs (Juergen Gross + nab)
- Convert tcm_fc to use TARGET_SCF_ACK_KREF I/O + TMR krefs
- Convert ib_srpt to use percpu_ida tag pre-allocation
- Add DebugFS node for qla2xxx target sess list (Quinn)
- Rework iser-target connection termination (Jenny + Sagi)
- Convert iser-target to new CQ API (HCH)
- Add pass-through WRITE_SAME support for IBLOCK (Mike Christie)
- Introduce data_bitmap for asynchronous access of data area (Sheng
Yang + Andy)
- Fix target_release_cmd_kref shutdown comp leak (Himanshu Madhani)
Also, there is a separate PULL request coming for cxgb4 NIC driver
prerequisites for supporting hw iscsi segmentation offload (ISO), that
will be the base for a number of v4.7 developments involving
iscsi-target hw offloads"
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (36 commits)
target: Fix target_release_cmd_kref shutdown comp leak
target: Avoid DataIN transfers for non-GOOD SAM status
target/user: Report capability of handling out-of-order completions to userspace
target/user: Fix size_t format-spec build warning
target/user: Don't free expired command when time out
target/user: Introduce data_bitmap, replace data_length/data_head/data_tail
target/user: Free data ring in unified function
target/user: Use iovec[] to describe continuous area
target: Remove enum transport_lunflags_table
target/iblock: pass WRITE_SAME to device if possible
iser-target: Kill the ->isert_cmd back pointer in struct iser_tx_desc
iser-target: Kill struct isert_rdma_wr
iser-target: Convert to new CQ API
iser-target: Split and properly type the login buffer
iser-target: Remove ISER_RECV_DATA_SEG_LEN
iser-target: Remove impossible condition from isert_wait_conn
iser-target: Remove redundant wait in release_conn
iser-target: Rework connection termination
iser-target: Separate flows for np listeners and connections cma events
iser-target: Add new state ISER_CONN_BOUND to isert_conn
...
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dfs.c | 55 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 57 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.c | 79 |
5 files changed, 130 insertions, 64 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ceb452dd143c..47f8b9b49bac 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2963,6 +2963,7 @@ struct qlt_hw_data { uint8_t tgt_node_name[WWN_SIZE]; + struct dentry *dfs_tgt_sess; struct list_head q_full_list; uint32_t num_pend_cmds; uint32_t num_qfull_cmds_alloc; diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c index cd8b96a4b0dd..34272fde8a5b 100644 --- a/drivers/scsi/qla2xxx/qla_dfs.c +++ b/drivers/scsi/qla2xxx/qla_dfs.c @@ -13,6 +13,47 @@ static struct dentry *qla2x00_dfs_root; static atomic_t qla2x00_dfs_root_count; static int +qla2x00_dfs_tgt_sess_show(struct seq_file *s, void *unused) +{ + scsi_qla_host_t *vha = s->private; + struct qla_hw_data *ha = vha->hw; + unsigned long flags; + struct qla_tgt_sess *sess = NULL; + struct qla_tgt *tgt= vha->vha_tgt.qla_tgt; + + seq_printf(s, "%s\n",vha->host_str); + if (tgt) { + seq_printf(s, "Port ID Port Name Handle\n"); + + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + list_for_each_entry(sess, &tgt->sess_list, sess_list_entry) { + seq_printf(s, "%02x:%02x:%02x %8phC %d\n", + sess->s_id.b.domain,sess->s_id.b.area, + sess->s_id.b.al_pa, sess->port_name, + sess->loop_id); + } + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + } + + return 0; +} + +static int +qla2x00_dfs_tgt_sess_open(struct inode *inode, struct file *file) +{ + scsi_qla_host_t *vha = inode->i_private; + return single_open(file, qla2x00_dfs_tgt_sess_show, vha); +} + + +static const struct file_operations dfs_tgt_sess_ops = { + .open = qla2x00_dfs_tgt_sess_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) { struct scsi_qla_host *vha = s->private; @@ -248,6 +289,15 @@ create_nodes: "Unable to create debugfs fce node.\n"); goto out; } + + ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess", + S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_sess_ops); + if (!ha->tgt.dfs_tgt_sess) { + ql_log(ql_log_warn, vha, 0xffff, + "Unable to create debugFS tgt_sess node.\n"); + goto out; + } + out: return 0; } @@ -257,6 +307,11 @@ qla2x00_dfs_remove(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; + if (ha->tgt.dfs_tgt_sess) { + debugfs_remove(ha->tgt.dfs_tgt_sess); + ha->tgt.dfs_tgt_sess = NULL; + } + if (ha->dfs_fw_resource_cnt) { debugfs_remove(ha->dfs_fw_resource_cnt); ha->dfs_fw_resource_cnt = NULL; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index ee967becd257..985231900aca 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -641,7 +641,8 @@ void qlt_unreg_sess(struct qla_tgt_sess *sess) { struct scsi_qla_host *vha = sess->vha; - vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); + if (sess->se_sess) + vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); if (!list_empty(&sess->del_list_entry)) list_del_init(&sess->del_list_entry); @@ -856,8 +857,12 @@ static void qlt_del_sess_work_fn(struct delayed_work *work) ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, "Timeout: sess %p about to be deleted\n", sess); - ha->tgt.tgt_ops->shutdown_sess(sess); - ha->tgt.tgt_ops->put_sess(sess); + if (sess->se_sess) { + ha->tgt.tgt_ops->shutdown_sess(sess); + ha->tgt.tgt_ops->put_sess(sess); + } else { + qlt_unreg_sess(sess); + } } else { schedule_delayed_work(&tgt->sess_del_work, sess->expires - elapsed); @@ -879,7 +884,6 @@ static struct qla_tgt_sess *qlt_create_sess( struct qla_hw_data *ha = vha->hw; struct qla_tgt_sess *sess; unsigned long flags; - unsigned char be_sid[3]; /* Check to avoid double sessions */ spin_lock_irqsave(&ha->tgt.sess_lock, flags); @@ -905,6 +909,14 @@ static struct qla_tgt_sess *qlt_create_sess( if (sess->deleted) qlt_undelete_sess(sess); + if (!sess->se_sess) { + if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, + &sess->port_name[0], sess) < 0) { + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + return NULL; + } + } + kref_get(&sess->se_sess->sess_kref); ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, (fcport->flags & FCF_CONF_COMP_SUPPORTED)); @@ -948,26 +960,6 @@ static struct qla_tgt_sess *qlt_create_sess( "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n", sess, vha->vha_tgt.qla_tgt); - be_sid[0] = sess->s_id.b.domain; - be_sid[1] = sess->s_id.b.area; - be_sid[2] = sess->s_id.b.al_pa; - /* - * Determine if this fc_port->port_name is allowed to access - * target mode using explict NodeACLs+MappedLUNs, or using - * TPG demo mode. If this is successful a target mode FC nexus - * is created. - */ - if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, - &fcport->port_name[0], sess, &be_sid[0], fcport->loop_id) < 0) { - kfree(sess); - return NULL; - } - /* - * Take an extra reference to ->sess_kref here to handle qla_tgt_sess - * access across ->tgt.sess_lock reaquire. - */ - kref_get(&sess->se_sess->sess_kref); - sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED); BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name)); memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); @@ -985,6 +977,23 @@ static struct qla_tgt_sess *qlt_create_sess( fcport->loop_id, sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, sess->conf_compl_supported ? "" : "not "); + /* + * Determine if this fc_port->port_name is allowed to access + * target mode using explict NodeACLs+MappedLUNs, or using + * TPG demo mode. If this is successful a target mode FC nexus + * is created. + */ + if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, + &fcport->port_name[0], sess) < 0) { + return NULL; + } else { + /* + * Take an extra reference to ->sess_kref here to handle qla_tgt_sess + * access across ->tgt.sess_lock reaquire. + */ + kref_get(&sess->se_sess->sess_kref); + } + return sess; } diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 22a6a767fe07..d857feeb6514 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -731,7 +731,7 @@ struct qla_tgt_func_tmpl { void (*free_session)(struct qla_tgt_sess *); int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *, - void *, uint8_t *, uint16_t); + struct qla_tgt_sess *); void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool); struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *, const uint16_t); diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 1808a01cfb7e..c1461d225f08 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -1406,6 +1406,39 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) transport_deregister_session(sess->se_sess); } +static int tcm_qla2xxx_session_cb(struct se_portal_group *se_tpg, + struct se_session *se_sess, void *p) +{ + struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, + struct tcm_qla2xxx_tpg, se_tpg); + struct tcm_qla2xxx_lport *lport = tpg->lport; + struct qla_hw_data *ha = lport->qla_vha->hw; + struct se_node_acl *se_nacl = se_sess->se_node_acl; + struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, + struct tcm_qla2xxx_nacl, se_node_acl); + struct qla_tgt_sess *qlat_sess = p; + uint16_t loop_id = qlat_sess->loop_id; + unsigned long flags; + unsigned char be_sid[3]; + + be_sid[0] = qlat_sess->s_id.b.domain; + be_sid[1] = qlat_sess->s_id.b.area; + be_sid[2] = qlat_sess->s_id.b.al_pa; + + /* + * And now setup se_nacl and session pointers into HW lport internal + * mappings for fabric S_ID and LOOP_ID. + */ + spin_lock_irqsave(&ha->tgt.sess_lock, flags); + tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, + se_sess, qlat_sess, be_sid); + tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, + se_sess, qlat_sess, loop_id); + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + return 0; +} + /* * Called via qlt_create_sess():ha->qla2x_tmpl->check_initiator_node_acl() * to locate struct se_node_acl @@ -1413,20 +1446,13 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) static int tcm_qla2xxx_check_initiator_node_acl( scsi_qla_host_t *vha, unsigned char *fc_wwpn, - void *qla_tgt_sess, - uint8_t *s_id, - uint16_t loop_id) + struct qla_tgt_sess *qlat_sess) { struct qla_hw_data *ha = vha->hw; struct tcm_qla2xxx_lport *lport; struct tcm_qla2xxx_tpg *tpg; - struct tcm_qla2xxx_nacl *nacl; - struct se_portal_group *se_tpg; - struct se_node_acl *se_nacl; struct se_session *se_sess; - struct qla_tgt_sess *sess = qla_tgt_sess; unsigned char port_name[36]; - unsigned long flags; int num_tags = (ha->cur_fw_xcb_count) ? ha->cur_fw_xcb_count : TCM_QLA2XXX_DEFAULT_TAGS; @@ -1444,15 +1470,6 @@ static int tcm_qla2xxx_check_initiator_node_acl( pr_err("Unable to lcoate struct tcm_qla2xxx_lport->tpg_1\n"); return -EINVAL; } - se_tpg = &tpg->se_tpg; - - se_sess = transport_init_session_tags(num_tags, - sizeof(struct qla_tgt_cmd), - TARGET_PROT_ALL); - if (IS_ERR(se_sess)) { - pr_err("Unable to initialize struct se_session\n"); - return PTR_ERR(se_sess); - } /* * Format the FCP Initiator port_name into colon seperated values to * match the format by tcm_qla2xxx explict ConfigFS NodeACLs. @@ -1463,28 +1480,12 @@ static int tcm_qla2xxx_check_initiator_node_acl( * Locate our struct se_node_acl either from an explict NodeACL created * via ConfigFS, or via running in TPG demo mode. */ - se_sess->se_node_acl = core_tpg_check_initiator_node_acl(se_tpg, - port_name); - if (!se_sess->se_node_acl) { - transport_free_session(se_sess); - return -EINVAL; - } - se_nacl = se_sess->se_node_acl; - nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); - /* - * And now setup the new se_nacl and session pointers into our HW lport - * mappings for fabric S_ID and LOOP_ID. - */ - spin_lock_irqsave(&ha->tgt.sess_lock, flags); - tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl, se_sess, - qla_tgt_sess, s_id); - tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl, se_sess, - qla_tgt_sess, loop_id); - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); - /* - * Finally register the new FC Nexus with TCM - */ - transport_register_session(se_nacl->se_tpg, se_nacl, se_sess, sess); + se_sess = target_alloc_session(&tpg->se_tpg, num_tags, + sizeof(struct qla_tgt_cmd), + TARGET_PROT_ALL, port_name, + qlat_sess, tcm_qla2xxx_session_cb); + if (IS_ERR(se_sess)) + return PTR_ERR(se_sess); return 0; } |