linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion
@ 2016-01-25  8:10 Nicholas A. Bellinger
  2016-01-25  8:10 ` [PATCH-v2 01/12] target: Add target_alloc_session() helper function Nicholas A. Bellinger
                   ` (11 more replies)
  0 siblings, 12 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:10 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

Hi folks,

Here is -v2 series code for target_alloc_session() helper
support using existing percpu-ida tag pre-allocation, along
with a new (*callback)() for allowing fabric driver code
to complete ahead of transport_register_session() finishing
I_T nexus setup.

This includes a tree-wide fabric driver conversion to use
use target_alloc_session() + associated (*callback)() with
common code.

Also as per HCH, it contains sbp-target, usb-gadget/tcm
and xen-scsiback driver percpu_ida tag pre-allocation
conversions, along with initial TARGET_SCF_ACK_KREF
support for v4.6-rc code.

Please review.

--nab

Christoph Hellwig (1):
  target: Convert demo-mode only drivers to target_alloc_session

Nicholas Bellinger (11):
  target: Add target_alloc_session() helper function
  vhost/scsi: Convert to target_alloc_session usage
  tcm_qla2xxx: Convert to target_alloc_session usage
  tcm_fc: Convert to target_alloc_session usage
  ib_srpt: Convert to target_alloc_session usage
  sbp-target: Conversion to percpu_ida tag pre-allocation
  sbp-target: Convert to TARGET_SCF_ACK_KREF I/O krefs
  usb-gadget/tcm: Conversion to percpu_ida tag pre-allocation
  usb-gadget/tcm: Convert to TARGET_SCF_ACK_KREF I/O krefs
  xen-scsiback: Convert to percpu_ida tag allocation
  xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs

 drivers/infiniband/ulp/srpt/ib_srpt.c  |  23 +--
 drivers/scsi/qla2xxx/qla_target.c      |   8 +-
 drivers/scsi/qla2xxx/qla_target.h      |   2 +-
 drivers/scsi/qla2xxx/tcm_qla2xxx.c     |  79 +++++-----
 drivers/target/loopback/tcm_loop.c     |  35 +----
 drivers/target/sbp/sbp_target.c        |  97 ++++++------
 drivers/target/target_core_transport.c |  56 +++++++
 drivers/target/tcm_fc/tfc_sess.c       |  44 +++---
 drivers/usb/gadget/function/f_tcm.c    | 181 ++++++++++------------
 drivers/vhost/scsi.c                   |  99 +++++-------
 drivers/xen/xen-scsiback.c             | 265 ++++++++++++++++-----------------
 include/target/target_core_fabric.h    |   6 +
 12 files changed, 437 insertions(+), 458 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH-v2 01/12] target: Add target_alloc_session() helper function
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
@ 2016-01-25  8:10 ` Nicholas A. Bellinger
  2016-01-25  8:10 ` [PATCH-v2 02/12] target: Convert demo-mode only drivers to target_alloc_session Nicholas A. Bellinger
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:10 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

Based on HCH's original patch, this adds a full version to
support percpu-ida tag pre-allocation and callback function
pointer into fabric driver code to complete session setup.

Reported-by: Christoph Hellwig <hch@lst.de>
Cc: Sagi Grimberg <sagig@mellanox.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Andy Grover <agrover@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/target/target_core_transport.c | 56 ++++++++++++++++++++++++++++++++++
 include/target/target_core_fabric.h    |  6 ++++
 2 files changed, 62 insertions(+)

diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 6235067..5609f91 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -281,6 +281,17 @@ struct se_session *transport_init_session_tags(unsigned int tag_num,
 	struct se_session *se_sess;
 	int rc;
 
+	if (tag_num != 0 && !tag_size) {
+		pr_err("init_session_tags called with percpu-ida tag_num:"
+		       " %u, but zero tag_size\n", tag_num);
+		return ERR_PTR(-EINVAL);
+	}
+	if (!tag_num && tag_size) {
+		pr_err("init_session_tags called with percpu-ida tag_size:"
+		       " %u, but zero tag_num\n", tag_size);
+		return ERR_PTR(-EINVAL);
+	}
+
 	se_sess = transport_init_session(sup_prot_ops);
 	if (IS_ERR(se_sess))
 		return se_sess;
@@ -374,6 +385,51 @@ void transport_register_session(
 }
 EXPORT_SYMBOL(transport_register_session);
 
+struct se_session *
+target_alloc_session(struct se_portal_group *tpg,
+		     unsigned int tag_num, unsigned int tag_size,
+		     enum target_prot_op prot_op,
+		     const char *initiatorname, void *private,
+		     int (*callback)(struct se_portal_group *,
+				     struct se_session *, void *))
+{
+	struct se_session *sess;
+
+	/*
+	 * If the fabric driver is using percpu-ida based pre allocation
+	 * of I/O descriptor tags, go ahead and perform that setup now..
+	 */
+	if (tag_num != 0)
+		sess = transport_init_session_tags(tag_num, tag_size, prot_op);
+	else
+		sess = transport_init_session(prot_op);
+
+	if (IS_ERR(sess))
+		return sess;
+
+	sess->se_node_acl = core_tpg_check_initiator_node_acl(tpg,
+					(unsigned char *)initiatorname);
+	if (!sess->se_node_acl) {
+		transport_free_session(sess);
+		return ERR_PTR(-EACCES);
+	}
+	/*
+	 * Go ahead and perform any remaining fabric setup that is
+	 * required before transport_register_session().
+	 */
+	if (callback != NULL) {
+		int rc = callback(tpg, sess, private);
+		if (rc) {
+			transport_free_session(sess);
+			return ERR_PTR(rc);
+		}
+	}
+
+	transport_register_session(tpg, sess->se_node_acl, sess, private);
+	return sess;
+}
+EXPORT_SYMBOL(target_alloc_session);
+
 static void target_release_session(struct kref *kref)
 {
 	struct se_session *se_sess = container_of(kref,
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index 5665340..685a51a 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -108,6 +108,12 @@ void target_unregister_template(const struct target_core_fabric_ops *fo);
 int target_depend_item(struct config_item *item);
 void target_undepend_item(struct config_item *item);
 
+struct se_session *target_alloc_session(struct se_portal_group *,
+		unsigned int, unsigned int, enum target_prot_op prot_op,
+		const char *, void *,
+		int (*callback)(struct se_portal_group *,
+				struct se_session *, void *));
+
 struct se_session *transport_init_session(enum target_prot_op);
 int transport_alloc_session_tags(struct se_session *, unsigned int,
 		unsigned int);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 02/12] target: Convert demo-mode only drivers to target_alloc_session
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
  2016-01-25  8:10 ` [PATCH-v2 01/12] target: Add target_alloc_session() helper function Nicholas A. Bellinger
@ 2016-01-25  8:10 ` Nicholas A. Bellinger
  2016-01-26  9:45   ` Juergen Gross
  2016-01-25  8:10 ` [PATCH-v2 03/12] vhost/scsi: Convert to target_alloc_session usage Nicholas A. Bellinger
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:10 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot

From: Christoph Hellwig <hch@lst.de>

Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Chris Boot <bootc@bootc.net>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Cc: Juergen Gross <jgross@suse.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/target/loopback/tcm_loop.c  | 35 +++++--------------------
 drivers/target/sbp/sbp_target.c     | 33 ++++++------------------
 drivers/usb/gadget/function/f_tcm.c | 45 ++++++++++----------------------
 drivers/xen/xen-scsiback.c          | 51 ++++++++++---------------------------
 4 files changed, 42 insertions(+), 122 deletions(-)

diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index d41a5c3..0216c75 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -806,54 +806,33 @@ static int tcm_loop_make_nexus(
 	struct tcm_loop_tpg *tl_tpg,
 	const char *name)
 {
-	struct se_portal_group *se_tpg;
 	struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
 	struct tcm_loop_nexus *tl_nexus;
-	int ret = -ENOMEM;
 
 	if (tl_tpg->tl_nexus) {
 		pr_debug("tl_tpg->tl_nexus already exists\n");
 		return -EEXIST;
 	}
-	se_tpg = &tl_tpg->tl_se_tpg;
 
 	tl_nexus = kzalloc(sizeof(struct tcm_loop_nexus), GFP_KERNEL);
 	if (!tl_nexus) {
 		pr_err("Unable to allocate struct tcm_loop_nexus\n");
 		return -ENOMEM;
 	}
-	/*
-	 * Initialize the struct se_session pointer
-	 */
-	tl_nexus->se_sess = transport_init_session(
-				TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS);
+
+	tl_nexus->se_sess = target_alloc_session(&tl_tpg->tl_se_tpg, 0, 0,
+					TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS,
+					name, tl_nexus, NULL);
 	if (IS_ERR(tl_nexus->se_sess)) {
-		ret = PTR_ERR(tl_nexus->se_sess);
-		goto out;
-	}
-	/*
-	 * Since we are running in 'demo mode' this call with generate a
-	 * struct se_node_acl for the tcm_loop struct se_portal_group with the SCSI
-	 * Initiator port name of the passed configfs group 'name'.
-	 */
-	tl_nexus->se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
-				se_tpg, (unsigned char *)name);
-	if (!tl_nexus->se_sess->se_node_acl) {
-		transport_free_session(tl_nexus->se_sess);
-		goto out;
+		kfree(tl_nexus);
+		return PTR_ERR(tl_nexus->se_sess);
 	}
-	/* Now, register the I_T Nexus as active. */
-	transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
-			tl_nexus->se_sess, tl_nexus);
+
 	tl_tpg->tl_nexus = tl_nexus;
 	pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
 		" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
 		name);
 	return 0;
-
-out:
-	kfree(tl_nexus);
-	return ret;
 }
 
 static int tcm_loop_drop_nexus(
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 3072f1a..ddd3398 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -196,45 +196,28 @@ static struct sbp_session *sbp_session_create(
 	struct sbp_session *sess;
 	int ret;
 	char guid_str[17];
-	struct se_node_acl *se_nacl;
+
+	snprintf(guid_str, sizeof(guid_str), "%016llx", guid);
 
 	sess = kmalloc(sizeof(*sess), GFP_KERNEL);
 	if (!sess) {
 		pr_err("failed to allocate session descriptor\n");
 		return ERR_PTR(-ENOMEM);
 	}
+	spin_lock_init(&sess->lock);
+	INIT_LIST_HEAD(&sess->login_list);
+	INIT_DELAYED_WORK(&sess->maint_work, session_maintenance_work);
+	sess->guid = guid;
 
-	sess->se_sess = transport_init_session(TARGET_PROT_NORMAL);
+	sess->se_sess = target_alloc_session(&tpg->se_tpg, 0, 0, TARGET_PROT_NORMAL,
+					     guid_str, sess, NULL);
 	if (IS_ERR(sess->se_sess)) {
 		pr_err("failed to init se_session\n");
-
 		ret = PTR_ERR(sess->se_sess);
 		kfree(sess);
 		return ERR_PTR(ret);
 	}
 
-	snprintf(guid_str, sizeof(guid_str), "%016llx", guid);
-
-	se_nacl = core_tpg_check_initiator_node_acl(&tpg->se_tpg, guid_str);
-	if (!se_nacl) {
-		pr_warn("Node ACL not found for %s\n", guid_str);
-
-		transport_free_session(sess->se_sess);
-		kfree(sess);
-
-		return ERR_PTR(-EPERM);
-	}
-
-	sess->se_sess->se_node_acl = se_nacl;
-
-	spin_lock_init(&sess->lock);
-	INIT_LIST_HEAD(&sess->login_list);
-	INIT_DELAYED_WORK(&sess->maint_work, session_maintenance_work);
-
-	sess->guid = guid;
-
-	transport_register_session(&tpg->se_tpg, se_nacl, sess->se_sess, sess);
-
 	return sess;
 }
 
diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
index bad007b5..2e8b91d 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -1581,53 +1581,34 @@ out:
 
 static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
 {
-	struct se_portal_group *se_tpg;
 	struct tcm_usbg_nexus *tv_nexus;
-	int ret;
+	int ret = 0;
 
 	mutex_lock(&tpg->tpg_mutex);
 	if (tpg->tpg_nexus) {
 		ret = -EEXIST;
 		pr_debug("tpg->tpg_nexus already exists\n");
-		goto err_unlock;
+		goto out_unlock;
 	}
-	se_tpg = &tpg->se_tpg;
 
-	ret = -ENOMEM;
 	tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL);
-	if (!tv_nexus)
-		goto err_unlock;
-	tv_nexus->tvn_se_sess = transport_init_session(TARGET_PROT_NORMAL);
-	if (IS_ERR(tv_nexus->tvn_se_sess))
-		goto err_free;
+	if (!tv_nexus) {
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
 
-	/*
-	 * Since we are running in 'demo mode' this call with generate a
-	 * struct se_node_acl for the tcm_vhost struct se_portal_group with
-	 * the SCSI Initiator port name of the passed configfs group 'name'.
-	 */
-	tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
-			se_tpg, name);
-	if (!tv_nexus->tvn_se_sess->se_node_acl) {
+	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 0, 0,
+						     TARGET_PROT_NORMAL, name,
+						     tv_nexus, NULL);
+	if (IS_ERR(tv_nexus->tvn_se_sess)) {
 #define MAKE_NEXUS_MSG "core_tpg_check_initiator_node_acl() failed for %s\n"
 		pr_debug(MAKE_NEXUS_MSG, name);
 #undef MAKE_NEXUS_MSG
-		goto err_session;
+		kfree(tv_nexus);
+		ret = PTR_ERR(tv_nexus->tvn_se_sess);
 	}
-	/*
-	 * Now register the TCM vHost virtual I_T Nexus as active.
-	 */
-	transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
-			tv_nexus->tvn_se_sess, tv_nexus);
-	tpg->tpg_nexus = tv_nexus;
-	mutex_unlock(&tpg->tpg_mutex);
-	return 0;
 
-err_session:
-	transport_free_session(tv_nexus->tvn_se_sess);
-err_free:
-	kfree(tv_nexus);
-err_unlock:
+out_unlock:
 	mutex_unlock(&tpg->tpg_mutex);
 	return ret;
 }
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 43bcae8..594f8a7 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -1485,58 +1485,35 @@ static struct configfs_attribute *scsiback_param_attrs[] = {
 static int scsiback_make_nexus(struct scsiback_tpg *tpg,
 				const char *name)
 {
-	struct se_portal_group *se_tpg;
-	struct se_session *se_sess;
 	struct scsiback_nexus *tv_nexus;
+	int ret = 0;
 
 	mutex_lock(&tpg->tv_tpg_mutex);
 	if (tpg->tpg_nexus) {
-		mutex_unlock(&tpg->tv_tpg_mutex);
 		pr_debug("tpg->tpg_nexus already exists\n");
-		return -EEXIST;
+		ret = -EEXIST;
+		goto out_unlock;
 	}
-	se_tpg = &tpg->se_tpg;
 
 	tv_nexus = kzalloc(sizeof(struct scsiback_nexus), GFP_KERNEL);
 	if (!tv_nexus) {
-		mutex_unlock(&tpg->tv_tpg_mutex);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out_unlock;
 	}
-	/*
-	 * Initialize the struct se_session pointer
-	 */
-	tv_nexus->tvn_se_sess = transport_init_session(TARGET_PROT_NORMAL);
+
+	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 0, 0,
+						     TARGET_PROT_NORMAL, name,
+						     tv_nexus, NULL);
 	if (IS_ERR(tv_nexus->tvn_se_sess)) {
-		mutex_unlock(&tpg->tv_tpg_mutex);
 		kfree(tv_nexus);
-		return -ENOMEM;
-	}
-	se_sess = tv_nexus->tvn_se_sess;
-	/*
-	 * Since we are running in 'demo mode' this call with generate a
-	 * struct se_node_acl for the scsiback struct se_portal_group with
-	 * the SCSI Initiator port name of the passed configfs group 'name'.
-	 */
-	tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
-				se_tpg, (unsigned char *)name);
-	if (!tv_nexus->tvn_se_sess->se_node_acl) {
-		mutex_unlock(&tpg->tv_tpg_mutex);
-		pr_debug("core_tpg_check_initiator_node_acl() failed for %s\n",
-			 name);
-		goto out;
+		ret = -ENOMEM;
+		goto out_unlock;
 	}
-	/* Now register the TCM pvscsi virtual I_T Nexus as active. */
-	transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
-			tv_nexus->tvn_se_sess, tv_nexus);
-	tpg->tpg_nexus = tv_nexus;
 
+	tpg->tpg_nexus = tv_nexus;
+out_unlock:
 	mutex_unlock(&tpg->tv_tpg_mutex);
-	return 0;
-
-out:
-	transport_free_session(se_sess);
-	kfree(tv_nexus);
-	return -ENOMEM;
+	return ret;
 }
 
 static int scsiback_drop_nexus(struct scsiback_tpg *tpg)
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 03/12] vhost/scsi: Convert to target_alloc_session usage
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
  2016-01-25  8:10 ` [PATCH-v2 01/12] target: Add target_alloc_session() helper function Nicholas A. Bellinger
  2016-01-25  8:10 ` [PATCH-v2 02/12] target: Convert demo-mode only drivers to target_alloc_session Nicholas A. Bellinger
@ 2016-01-25  8:10 ` Nicholas A. Bellinger
  2016-01-25  8:10 ` [PATCH-v2 04/12] tcm_qla2xxx: " Nicholas A. Bellinger
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:10 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c | 99 ++++++++++++++++++++++------------------------------
 1 file changed, 41 insertions(+), 58 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 29cfc57..cd5f20f 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1664,8 +1664,7 @@ static void vhost_scsi_port_unlink(struct se_portal_group *se_tpg,
 	mutex_unlock(&vhost_scsi_mutex);
 }
 
-static void vhost_scsi_free_cmd_map_res(struct vhost_scsi_nexus *nexus,
-				       struct se_session *se_sess)
+static void vhost_scsi_free_cmd_map_res(struct se_session *se_sess)
 {
 	struct vhost_scsi_cmd *tv_cmd;
 	unsigned int i;
@@ -1721,98 +1720,82 @@ static struct configfs_attribute *vhost_scsi_tpg_attrib_attrs[] = {
 	NULL,
 };
 
-static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg,
-				const char *name)
+static int vhost_scsi_nexus_cb(struct se_portal_group *se_tpg,
+			       struct se_session *se_sess, void *p)
 {
-	struct se_portal_group *se_tpg;
-	struct se_session *se_sess;
-	struct vhost_scsi_nexus *tv_nexus;
 	struct vhost_scsi_cmd *tv_cmd;
 	unsigned int i;
 
-	mutex_lock(&tpg->tv_tpg_mutex);
-	if (tpg->tpg_nexus) {
-		mutex_unlock(&tpg->tv_tpg_mutex);
-		pr_debug("tpg->tpg_nexus already exists\n");
-		return -EEXIST;
-	}
-	se_tpg = &tpg->se_tpg;
-
-	tv_nexus = kzalloc(sizeof(struct vhost_scsi_nexus), GFP_KERNEL);
-	if (!tv_nexus) {
-		mutex_unlock(&tpg->tv_tpg_mutex);
-		pr_err("Unable to allocate struct vhost_scsi_nexus\n");
-		return -ENOMEM;
-	}
-	/*
-	 *  Initialize the struct se_session pointer and setup tagpool
-	 *  for struct vhost_scsi_cmd descriptors
-	 */
-	tv_nexus->tvn_se_sess = transport_init_session_tags(
-					VHOST_SCSI_DEFAULT_TAGS,
-					sizeof(struct vhost_scsi_cmd),
-					TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS);
-	if (IS_ERR(tv_nexus->tvn_se_sess)) {
-		mutex_unlock(&tpg->tv_tpg_mutex);
-		kfree(tv_nexus);
-		return -ENOMEM;
-	}
-	se_sess = tv_nexus->tvn_se_sess;
 	for (i = 0; i < VHOST_SCSI_DEFAULT_TAGS; i++) {
 		tv_cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[i];
 
 		tv_cmd->tvc_sgl = kzalloc(sizeof(struct scatterlist) *
 					VHOST_SCSI_PREALLOC_SGLS, GFP_KERNEL);
 		if (!tv_cmd->tvc_sgl) {
-			mutex_unlock(&tpg->tv_tpg_mutex);
 			pr_err("Unable to allocate tv_cmd->tvc_sgl\n");
 			goto out;
 		}
 
 		tv_cmd->tvc_upages = kzalloc(sizeof(struct page *) *
-					VHOST_SCSI_PREALLOC_UPAGES, GFP_KERNEL);
+				VHOST_SCSI_PREALLOC_UPAGES, GFP_KERNEL);
 		if (!tv_cmd->tvc_upages) {
-			mutex_unlock(&tpg->tv_tpg_mutex);
 			pr_err("Unable to allocate tv_cmd->tvc_upages\n");
 			goto out;
 		}
 
 		tv_cmd->tvc_prot_sgl = kzalloc(sizeof(struct scatterlist) *
-					VHOST_SCSI_PREALLOC_PROT_SGLS, GFP_KERNEL);
+				VHOST_SCSI_PREALLOC_PROT_SGLS, GFP_KERNEL);
 		if (!tv_cmd->tvc_prot_sgl) {
-			mutex_unlock(&tpg->tv_tpg_mutex);
 			pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n");
 			goto out;
 		}
 	}
+	return 0;
+out:
+	vhost_scsi_free_cmd_map_res(se_sess);
+	return -ENOMEM;
+}
+
+static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg,
+				const char *name)
+{
+	struct se_portal_group *se_tpg;
+	struct vhost_scsi_nexus *tv_nexus;
+
+	mutex_lock(&tpg->tv_tpg_mutex);
+	if (tpg->tpg_nexus) {
+		mutex_unlock(&tpg->tv_tpg_mutex);
+		pr_debug("tpg->tpg_nexus already exists\n");
+		return -EEXIST;
+	}
+	se_tpg = &tpg->se_tpg;
+
+	tv_nexus = kzalloc(sizeof(struct vhost_scsi_nexus), GFP_KERNEL);
+	if (!tv_nexus) {
+		mutex_unlock(&tpg->tv_tpg_mutex);
+		pr_err("Unable to allocate struct vhost_scsi_nexus\n");
+		return -ENOMEM;
+	}
 	/*
 	 * Since we are running in 'demo mode' this call with generate a
 	 * struct se_node_acl for the vhost_scsi struct se_portal_group with
 	 * the SCSI Initiator port name of the passed configfs group 'name'.
 	 */
-	tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
-				se_tpg, (unsigned char *)name);
-	if (!tv_nexus->tvn_se_sess->se_node_acl) {
+	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg,
+					VHOST_SCSI_DEFAULT_TAGS,
+					sizeof(struct vhost_scsi_cmd),
+					TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS,
+					(unsigned char *)name, tv_nexus,
+					vhost_scsi_nexus_cb);
+	if (IS_ERR(tv_nexus->tvn_se_sess)) {
 		mutex_unlock(&tpg->tv_tpg_mutex);
-		pr_debug("core_tpg_check_initiator_node_acl() failed"
-				" for %s\n", name);
-		goto out;
+		kfree(tv_nexus);
+		return -ENOMEM;
 	}
-	/*
-	 * Now register the TCM vhost virtual I_T Nexus as active.
-	 */
-	transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
-			tv_nexus->tvn_se_sess, tv_nexus);
 	tpg->tpg_nexus = tv_nexus;
 
 	mutex_unlock(&tpg->tv_tpg_mutex);
 	return 0;
-
-out:
-	vhost_scsi_free_cmd_map_res(tv_nexus, se_sess);
-	transport_free_session(se_sess);
-	kfree(tv_nexus);
-	return -ENOMEM;
 }
 
 static int vhost_scsi_drop_nexus(struct vhost_scsi_tpg *tpg)
@@ -1853,7 +1836,7 @@ static int vhost_scsi_drop_nexus(struct vhost_scsi_tpg *tpg)
 		" %s Initiator Port: %s\n", vhost_scsi_dump_proto_id(tpg->tport),
 		tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
 
-	vhost_scsi_free_cmd_map_res(tv_nexus, se_sess);
+	vhost_scsi_free_cmd_map_res(se_sess);
 	/*
 	 * Release the SCSI I_T Nexus to the emulated vhost Target Port
 	 */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 04/12] tcm_qla2xxx: Convert to target_alloc_session usage
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
                   ` (2 preceding siblings ...)
  2016-01-25  8:10 ` [PATCH-v2 03/12] vhost/scsi: Convert to target_alloc_session usage Nicholas A. Bellinger
@ 2016-01-25  8:10 ` Nicholas A. Bellinger
  2016-01-25  8:10 ` [PATCH-v2 05/12] tcm_fc: " Nicholas A. Bellinger
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:10 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger, Himanshu Madhani, Quinn Tran

From: Nicholas Bellinger <nab@linux-iscsi.org>

Cc: Himanshu Madhani <himanshu.madhani@qlogic.com>
Cc: Quinn Tran <quinn.tran@qlogic.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/scsi/qla2xxx/qla_target.c  |  8 +---
 drivers/scsi/qla2xxx/qla_target.h  |  2 +-
 drivers/scsi/qla2xxx/tcm_qla2xxx.c | 79 +++++++++++++++++++-------------------
 3 files changed, 43 insertions(+), 46 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 2c71305..a2da314 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -879,7 +879,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);
@@ -948,17 +947,14 @@ 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) {
+	if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, &fcport->port_name[0],
+						      sess)) {
 		kfree(sess);
 		return NULL;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 71b2865..409bd5f 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 b44f397..bf73c6f 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -1336,6 +1336,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
@@ -1343,20 +1376,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;
 
@@ -1374,15 +1400,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.
@@ -1393,28 +1410,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;
 }
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 05/12] tcm_fc: Convert to target_alloc_session usage
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
                   ` (3 preceding siblings ...)
  2016-01-25  8:10 ` [PATCH-v2 04/12] tcm_qla2xxx: " Nicholas A. Bellinger
@ 2016-01-25  8:10 ` Nicholas A. Bellinger
  2016-01-25  8:11 ` [PATCH-v2 06/12] ib_srpt: " Nicholas A. Bellinger
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:10 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger, Vasu Dev

From: Nicholas Bellinger <nab@linux-iscsi.org>

Cc: Vasu Dev <vasu.dev@linux.intel.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/target/tcm_fc/tfc_sess.c | 44 ++++++++++++++++++++--------------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index e19f4c5..d0c3e18 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -186,6 +186,20 @@ out:
 	return NULL;
 }
 
+static int ft_sess_alloc_cb(struct se_portal_group *se_tpg,
+			    struct se_session *se_sess, void *p)
+{
+	struct ft_sess *sess = p;
+	struct ft_tport *tport = sess->tport;
+	struct hlist_head *head = &tport->hash[ft_sess_hash(sess->port_id)];
+
+	pr_debug("port_id %x sess %p\n", sess->port_id, sess);
+	hlist_add_head_rcu(&sess->hash, head);
+	tport->sess_count++;
+
+	return 0;
+}
+
 /*
  * Allocate session and enter it in the hash for the local port.
  * Caller holds ft_lport_lock.
@@ -194,7 +208,6 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
 				      struct fc_rport_priv *rdata)
 {
 	struct se_portal_group *se_tpg = &tport->tpg->se_tpg;
-	struct se_node_acl *se_acl;
 	struct ft_sess *sess;
 	struct hlist_head *head;
 	unsigned char initiatorname[TRANSPORT_IQN_LEN];
@@ -210,31 +223,18 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
 	if (!sess)
 		return NULL;
 
-	sess->se_sess = transport_init_session_tags(TCM_FC_DEFAULT_TAGS,
-						    sizeof(struct ft_cmd),
-						    TARGET_PROT_NORMAL);
-	if (IS_ERR(sess->se_sess)) {
-		kfree(sess);
-		return NULL;
-	}
+	kref_init(&sess->kref); /* ref for table entry */
+	sess->tport = tport;
+	sess->port_id = port_id;
 
-	se_acl = core_tpg_get_initiator_node_acl(se_tpg, &initiatorname[0]);
-	if (!se_acl) {
-		transport_free_session(sess->se_sess);
+	sess->se_sess = target_alloc_session(se_tpg, TCM_FC_DEFAULT_TAGS,
+					     sizeof(struct ft_cmd),
+					     TARGET_PROT_NORMAL, &initiatorname[0],
+					     sess, ft_sess_alloc_cb);
+	if (IS_ERR(sess->se_sess)) {
 		kfree(sess);
 		return NULL;
 	}
-	sess->se_sess->se_node_acl = se_acl;
-	sess->tport = tport;
-	sess->port_id = port_id;
-	kref_init(&sess->kref);	/* ref for table entry */
-	hlist_add_head_rcu(&sess->hash, head);
-	tport->sess_count++;
-
-	pr_debug("port_id %x sess %p\n", port_id, sess);
-
-	transport_register_session(&tport->tpg->se_tpg, se_acl,
-				   sess->se_sess, sess);
 	return sess;
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 06/12] ib_srpt: Convert to target_alloc_session usage
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
                   ` (4 preceding siblings ...)
  2016-01-25  8:10 ` [PATCH-v2 05/12] tcm_fc: " Nicholas A. Bellinger
@ 2016-01-25  8:11 ` Nicholas A. Bellinger
  2016-01-25  8:11 ` [PATCH-v2 07/12] sbp-target: Conversion to percpu_ida tag pre-allocation Nicholas A. Bellinger
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:11 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger, Vu Pham

From: Nicholas Bellinger <nab@linux-iscsi.org>

Cc: Vu Pham <vu@mellanox.com>
Cc: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/infiniband/ulp/srpt/ib_srpt.c | 23 ++++++-----------------
 1 file changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index bc5470c..5a35c1f 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -2387,7 +2387,6 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
 	struct srp_login_rej *rej;
 	struct ib_cm_rep_param *rep_param;
 	struct srpt_rdma_ch *ch, *tmp_ch;
-	struct se_node_acl *se_acl;
 	u32 it_iu_len;
 	int i, ret = 0;
 	unsigned char *p;
@@ -2553,19 +2552,12 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
 	pr_debug("registering session %s\n", ch->sess_name);
 	p = &ch->sess_name[0];
 
-	ch->sess = transport_init_session(TARGET_PROT_NORMAL);
-	if (IS_ERR(ch->sess)) {
-		rej->reason = cpu_to_be32(
-				SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
-		pr_debug("Failed to create session\n");
-		goto destroy_ib;
-	}
-
 try_again:
-	se_acl = core_tpg_get_initiator_node_acl(&sport->port_tpg_1, p);
-	if (!se_acl) {
+	ch->sess = target_alloc_session(&sport->port_tpg_1, 0, 0,
+					TARGET_PROT_NORMAL, p, ch, NULL);
+	if (IS_ERR(ch->sess)) {
 		pr_info("Rejected login because no ACL has been"
-			" configured yet for initiator %s.\n", ch->sess_name);
+			" configured yet for initiator %s.\n", p);
 		/*
 		 * XXX: Hack to retry of ch->i_port_id without leading '0x'
 		 */
@@ -2573,14 +2565,11 @@ try_again:
 			p += 2;
 			goto try_again;
 		}
-		rej->reason = cpu_to_be32(
+		rej->reason = cpu_to_be32((PTR_ERR(ch->sess) == -ENOMEM) ?
+				SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES :
 				SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED);
-		transport_free_session(ch->sess);
 		goto destroy_ib;
 	}
-	ch->sess->se_node_acl = se_acl;
-
-	transport_register_session(&sport->port_tpg_1, se_acl, ch->sess, ch);
 
 	pr_debug("Establish connection sess=%p name=%s cm_id=%p\n", ch->sess,
 		 ch->sess_name, ch->cm_id);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 07/12] sbp-target: Conversion to percpu_ida tag pre-allocation
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
                   ` (5 preceding siblings ...)
  2016-01-25  8:11 ` [PATCH-v2 06/12] ib_srpt: " Nicholas A. Bellinger
@ 2016-01-25  8:11 ` Nicholas A. Bellinger
  2016-01-25  8:11 ` [PATCH-v2 08/12] sbp-target: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:11 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

Cc: Chris Boot <bootc@bootc.net>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/target/sbp/sbp_target.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index ddd3398..756e87f 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -209,8 +209,10 @@ static struct sbp_session *sbp_session_create(
 	INIT_DELAYED_WORK(&sess->maint_work, session_maintenance_work);
 	sess->guid = guid;
 
-	sess->se_sess = target_alloc_session(&tpg->se_tpg, 0, 0, TARGET_PROT_NORMAL,
-					     guid_str, sess, NULL);
+	sess->se_sess = target_alloc_session(&tpg->se_tpg, 128,
+					     sizeof(struct sbp_target_request),
+					     TARGET_PROT_NORMAL, guid_str,
+					     sess, NULL);
 	if (IS_ERR(sess->se_sess)) {
 		pr_err("failed to init se_session\n");
 		ret = PTR_ERR(sess->se_sess);
@@ -921,6 +923,24 @@ static inline bool tgt_agent_check_active(struct sbp_target_agent *agent)
 	return active;
 }
 
+static struct sbp_target_request *sbp_mgt_get_req(struct sbp_session *sess,
+	struct fw_card *card, u64 next_orb)
+{
+	struct se_session *se_sess = sess->se_sess;
+	struct sbp_target_request *req;
+	int tag;
+
+	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
+	if (tag < 0)
+		return ERR_PTR(-ENOMEM);
+
+	req = &((struct sbp_target_request *)se_sess->sess_cmd_map)[tag];
+	req->se_cmd.map_tag = tag;
+	req->se_cmd.tag = next_orb;
+
+	return req;
+}
+
 static void tgt_agent_fetch_work(struct work_struct *work)
 {
 	struct sbp_target_agent *agent =
@@ -932,7 +952,7 @@ static void tgt_agent_fetch_work(struct work_struct *work)
 	u64 next_orb = agent->orb_pointer;
 
 	while (next_orb && tgt_agent_check_active(agent)) {
-		req = kzalloc(sizeof(*req), GFP_KERNEL);
+		req = sbp_mgt_get_req(sess, sess->card, next_orb);
 		if (!req) {
 			spin_lock_bh(&agent->lock);
 			agent->state = AGENT_STATE_DEAD;
@@ -1430,9 +1450,13 @@ static int sbp_send_sense(struct sbp_target_request *req)
 
 static void sbp_free_request(struct sbp_target_request *req)
 {
+	struct se_cmd *se_cmd = &req->se_cmd;
+	struct se_session *se_sess = se_cmd->se_sess;
+
 	kfree(req->pg_tbl);
 	kfree(req->cmd_buf);
-	kfree(req);
+
+	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
 }
 
 static void sbp_mgt_agent_process(struct work_struct *work)
@@ -1592,8 +1616,12 @@ static void sbp_mgt_agent_rw(struct fw_card *card,
 			rcode = RCODE_CONFLICT_ERROR;
 			goto out;
 		}
-
+		// XXX:
+#if 0
+		req = sbp_mgt_get_req(agent->login->sess, card);
+#else
 		req = kzalloc(sizeof(*req), GFP_ATOMIC);
+#endif
 		if (!req) {
 			rcode = RCODE_CONFLICT_ERROR;
 			goto out;
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 08/12] sbp-target: Convert to TARGET_SCF_ACK_KREF I/O krefs
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
                   ` (6 preceding siblings ...)
  2016-01-25  8:11 ` [PATCH-v2 07/12] sbp-target: Conversion to percpu_ida tag pre-allocation Nicholas A. Bellinger
@ 2016-01-25  8:11 ` Nicholas A. Bellinger
  2016-01-25  8:11 ` [PATCH-v2 09/12] usb-gadget/tcm: Conversion to percpu_ida tag pre-allocation Nicholas A. Bellinger
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:11 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

Cc: Chris Boot <bootc@bootc.net>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/target/sbp/sbp_target.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 756e87f..251d532 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -893,7 +893,6 @@ static void tgt_agent_process_work(struct work_struct *work)
 					STATUS_BLOCK_SBP_STATUS(
 						SBP_STATUS_REQ_TYPE_NOTSUPP));
 			sbp_send_status(req);
-			sbp_free_request(req);
 			return;
 		case 3: /* Dummy ORB */
 			req->status.status |= cpu_to_be32(
@@ -904,7 +903,6 @@ static void tgt_agent_process_work(struct work_struct *work)
 					STATUS_BLOCK_SBP_STATUS(
 						SBP_STATUS_DUMMY_ORB_COMPLETE));
 			sbp_send_status(req);
-			sbp_free_request(req);
 			return;
 		default:
 			BUG();
@@ -988,7 +986,6 @@ static void tgt_agent_fetch_work(struct work_struct *work)
 			spin_unlock_bh(&agent->lock);
 
 			sbp_send_status(req);
-			sbp_free_request(req);
 			return;
 		}
 
@@ -1235,7 +1232,7 @@ static void sbp_handle_command(struct sbp_target_request *req)
 	req->se_cmd.tag = req->orb_pointer;
 	if (target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf,
 			      req->sense_buf, unpacked_lun, data_length,
-			      TCM_SIMPLE_TAG, data_dir, 0))
+			      TCM_SIMPLE_TAG, data_dir, TARGET_SCF_ACK_KREF))
 		goto err;
 
 	return;
@@ -1247,7 +1244,6 @@ err:
 		STATUS_BLOCK_LEN(1) |
 		STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
 	sbp_send_status(req);
-	sbp_free_request(req);
 }
 
 /*
@@ -1346,22 +1342,29 @@ static int sbp_rw_data(struct sbp_target_request *req)
 
 static int sbp_send_status(struct sbp_target_request *req)
 {
-	int ret, length;
+	int rc, ret = 0, length;
 	struct sbp_login_descriptor *login = req->login;
 
 	length = (((be32_to_cpu(req->status.status) >> 24) & 0x07) + 1) * 4;
 
-	ret = sbp_run_request_transaction(req, TCODE_WRITE_BLOCK_REQUEST,
+	rc = sbp_run_request_transaction(req, TCODE_WRITE_BLOCK_REQUEST,
 			login->status_fifo_addr, &req->status, length);
-	if (ret != RCODE_COMPLETE) {
-		pr_debug("sbp_send_status: write failed: 0x%x\n", ret);
-		return -EIO;
+	if (rc != RCODE_COMPLETE) {
+		pr_debug("sbp_send_status: write failed: 0x%x\n", rc);
+		ret = -EIO;
+		goto put_ref;
 	}
 
 	pr_debug("sbp_send_status: status write complete for ORB: 0x%llx\n",
 			req->orb_pointer);
-
-	return 0;
+	/*
+	 * Drop the extra ACK_KREF reference taken by target_submit_cmd()
+	 * ahead of sbp_check_stop_free() -> transport_generic_free_cmd()
+	 * final se_cmd->cmd_kref put.
+	 */
+put_ref:
+	target_put_sess_cmd(&req->se_cmd);
+	return ret;
 }
 
 static void sbp_sense_mangle(struct sbp_target_request *req)
@@ -1826,8 +1829,7 @@ static int sbp_check_stop_free(struct se_cmd *se_cmd)
 	struct sbp_target_request *req = container_of(se_cmd,
 			struct sbp_target_request, se_cmd);
 
-	transport_generic_free_cmd(&req->se_cmd, 0);
-	return 1;
+	return transport_generic_free_cmd(&req->se_cmd, 0);
 }
 
 static int sbp_count_se_tpg_luns(struct se_portal_group *tpg)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 09/12] usb-gadget/tcm: Conversion to percpu_ida tag pre-allocation
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
                   ` (7 preceding siblings ...)
  2016-01-25  8:11 ` [PATCH-v2 08/12] sbp-target: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
@ 2016-01-25  8:11 ` Nicholas A. Bellinger
  2016-01-25  8:11 ` [PATCH-v2 10/12] usb-gadget/tcm: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:11 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/usb/gadget/function/f_tcm.c | 95 ++++++++++++++++++++++---------------
 1 file changed, 56 insertions(+), 39 deletions(-)

diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
index 2e8b91d..8773572 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -1073,39 +1073,65 @@ out:
 	usbg_cleanup_cmd(cmd);
 }
 
+static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu,
+		struct tcm_usbg_nexus *tv_nexus, u32 scsi_tag)
+{
+	struct se_session *se_sess = tv_nexus->tvn_se_sess;
+	struct usbg_cmd *cmd;
+	int tag;
+
+	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
+	if (tag < 0)
+		return ERR_PTR(-ENOMEM);
+
+	cmd = &((struct usbg_cmd *)se_sess->sess_cmd_map)[tag];
+	cmd->se_cmd.map_tag = tag;
+	cmd->se_cmd.tag = cmd->tag = scsi_tag;
+	cmd->fu = fu;
+
+	return cmd;
+}
+
+static void usbg_release_cmd(struct se_cmd *);
+
 static int usbg_submit_command(struct f_uas *fu,
 		void *cmdbuf, unsigned int len)
 {
 	struct command_iu *cmd_iu = cmdbuf;
 	struct usbg_cmd *cmd;
-	struct usbg_tpg *tpg;
-	struct tcm_usbg_nexus *tv_nexus;
+	struct usbg_tpg *tpg = fu->tpg;
+	struct tcm_usbg_nexus *tv_nexus = tpg->tpg_nexus;
 	u32 cmd_len;
+	u16 scsi_tag;
 
 	if (cmd_iu->iu_id != IU_ID_COMMAND) {
 		pr_err("Unsupported type %d\n", cmd_iu->iu_id);
 		return -EINVAL;
 	}
 
-	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
-	if (!cmd)
-		return -ENOMEM;
+	tv_nexus = tpg->tpg_nexus;
+	if (!tv_nexus) {
+		pr_err("Missing nexus, ignoring command\n");
+		return -EINVAL;
+	}
 
-	cmd->fu = fu;
+	cmd_len = (cmd_iu->len & ~0x3) + 16;
+	if (cmd_len > USBG_MAX_CMD)
+		return -EINVAL;
+
+	scsi_tag = be16_to_cpup(&cmd_iu->tag);
+	cmd = usbg_get_cmd(fu, tv_nexus, scsi_tag);
+	if (IS_ERR(cmd)) {
+		pr_err("usbg_get_cmd failed\n");
+		return -ENOMEM;
+	}
 
 	/* XXX until I figure out why I can't free in on complete */
 	kref_init(&cmd->ref);
 	kref_get(&cmd->ref);
 
-	tpg = fu->tpg;
-	cmd_len = (cmd_iu->len & ~0x3) + 16;
-	if (cmd_len > USBG_MAX_CMD)
-		goto err;
-
 	memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
 
-	cmd->tag = be16_to_cpup(&cmd_iu->tag);
-	cmd->se_cmd.tag = cmd->tag;
 	if (fu->flags & USBG_USE_STREAMS) {
 		if (cmd->tag > UASP_SS_EP_COMP_NUM_STREAMS)
 			goto err;
@@ -1117,12 +1143,6 @@ static int usbg_submit_command(struct f_uas *fu,
 		cmd->stream = &fu->stream[0];
 	}
 
-	tv_nexus = tpg->tpg_nexus;
-	if (!tv_nexus) {
-		pr_err("Missing nexus, ignoring command\n");
-		goto err;
-	}
-
 	switch (cmd_iu->prio_attr & 0x7) {
 	case UAS_HEAD_TAG:
 		cmd->prio_attr = TCM_HEAD_TAG;
@@ -1148,7 +1168,7 @@ static int usbg_submit_command(struct f_uas *fu,
 
 	return 0;
 err:
-	kfree(cmd);
+	usbg_release_cmd(&cmd->se_cmd);
 	return -EINVAL;
 }
 
@@ -1190,7 +1210,7 @@ static int bot_submit_command(struct f_uas *fu,
 {
 	struct bulk_cb_wrap *cbw = cmdbuf;
 	struct usbg_cmd *cmd;
-	struct usbg_tpg *tpg;
+	struct usbg_tpg *tpg = fu->tpg;
 	struct tcm_usbg_nexus *tv_nexus;
 	u32 cmd_len;
 
@@ -1207,28 +1227,25 @@ static int bot_submit_command(struct f_uas *fu,
 	if (cmd_len < 1 || cmd_len > 16)
 		return -EINVAL;
 
-	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
-	if (!cmd)
-		return -ENOMEM;
+	tv_nexus = tpg->tpg_nexus;
+	if (!tv_nexus) {
+		pr_err("Missing nexus, ignoring command\n");
+		return -ENODEV;
+	}
 
-	cmd->fu = fu;
+	cmd = usbg_get_cmd(fu, tv_nexus, cbw->Tag);
+	if (IS_ERR(cmd)) {
+		pr_err("usbg_get_cmd failed\n");
+		return -ENOMEM;
+	}
 
 	/* XXX until I figure out why I can't free in on complete */
 	kref_init(&cmd->ref);
 	kref_get(&cmd->ref);
 
-	tpg = fu->tpg;
-
 	memcpy(cmd->cmd_buf, cbw->CDB, cmd_len);
 
 	cmd->bot_tag = cbw->Tag;
-
-	tv_nexus = tpg->tpg_nexus;
-	if (!tv_nexus) {
-		pr_err("Missing nexus, ignoring command\n");
-		goto err;
-	}
-
 	cmd->prio_attr = TCM_SIMPLE_TAG;
 	cmd->unpacked_lun = cbw->Lun;
 	cmd->is_read = cbw->Flags & US_BULK_FLAG_IN ? 1 : 0;
@@ -1239,9 +1256,6 @@ static int bot_submit_command(struct f_uas *fu,
 	queue_work(tpg->workqueue, &cmd->work);
 
 	return 0;
-err:
-	kfree(cmd);
-	return -EINVAL;
 }
 
 /* Start fabric.c code */
@@ -1294,8 +1308,10 @@ static void usbg_release_cmd(struct se_cmd *se_cmd)
 {
 	struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
 			se_cmd);
+	struct se_session *se_sess = se_cmd->se_sess;
+
 	kfree(cmd->data_buf);
-	kfree(cmd);
+	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
 }
 
 static int usbg_shutdown_session(struct se_session *se_sess)
@@ -1597,7 +1613,8 @@ static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
 		goto out_unlock;
 	}
 
-	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 0, 0,
+	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 128,
+						     sizeof(struct usbg_cmd),
 						     TARGET_PROT_NORMAL, name,
 						     tv_nexus, NULL);
 	if (IS_ERR(tv_nexus->tvn_se_sess)) {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 10/12] usb-gadget/tcm: Convert to TARGET_SCF_ACK_KREF I/O krefs
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
                   ` (8 preceding siblings ...)
  2016-01-25  8:11 ` [PATCH-v2 09/12] usb-gadget/tcm: Conversion to percpu_ida tag pre-allocation Nicholas A. Bellinger
@ 2016-01-25  8:11 ` Nicholas A. Bellinger
  2016-01-25  8:11 ` [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation Nicholas A. Bellinger
  2016-01-25  8:11 ` [PATCH-v2 12/12] xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
  11 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:11 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

This patch drops struct usbg_cmd->kref internal kref-erence
usage, for proper TARGET_SCF_ACK_KREF conversion.

Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/usb/gadget/function/f_tcm.c | 51 ++++++++-----------------------------
 1 file changed, 11 insertions(+), 40 deletions(-)

diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
index 8773572..7276a73 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -41,13 +41,6 @@ static inline struct f_uas *to_f_uas(struct usb_function *f)
 	return container_of(f, struct f_uas, function);
 }
 
-static void usbg_cmd_release(struct kref *);
-
-static inline void usbg_cleanup_cmd(struct usbg_cmd *cmd)
-{
-	kref_put(&cmd->ref, usbg_cmd_release);
-}
-
 /* Start bot.c code */
 
 static int bot_enqueue_cmd_cbw(struct f_uas *fu)
@@ -68,7 +61,7 @@ static void bot_status_complete(struct usb_ep *ep, struct usb_request *req)
 	struct usbg_cmd *cmd = req->context;
 	struct f_uas *fu = cmd->fu;
 
-	usbg_cleanup_cmd(cmd);
+	transport_generic_free_cmd(&cmd->se_cmd, 0);
 	if (req->status < 0) {
 		pr_err("ERR %s(%d)\n", __func__, __LINE__);
 		return;
@@ -605,7 +598,7 @@ static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
 		break;
 
 	case UASP_QUEUE_COMMAND:
-		usbg_cleanup_cmd(cmd);
+		transport_generic_free_cmd(&cmd->se_cmd, 0);
 		usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
 		break;
 
@@ -615,7 +608,7 @@ static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
 	return;
 
 cleanup:
-	usbg_cleanup_cmd(cmd);
+	transport_generic_free_cmd(&cmd->se_cmd, 0);
 }
 
 static int uasp_send_status_response(struct usbg_cmd *cmd)
@@ -977,7 +970,7 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
 	return;
 
 cleanup:
-	usbg_cleanup_cmd(cmd);
+	transport_generic_free_cmd(&cmd->se_cmd, 0);
 }
 
 static int usbg_prepare_w_request(struct usbg_cmd *cmd, struct usb_request *req)
@@ -1046,7 +1039,7 @@ static void usbg_cmd_work(struct work_struct *work)
 	struct se_cmd *se_cmd;
 	struct tcm_usbg_nexus *tv_nexus;
 	struct usbg_tpg *tpg;
-	int dir;
+	int dir, flags = (TARGET_SCF_UNKNOWN_SIZE | TARGET_SCF_ACK_KREF);
 
 	se_cmd = &cmd->se_cmd;
 	tpg = cmd->fu->tpg;
@@ -1060,9 +1053,9 @@ static void usbg_cmd_work(struct work_struct *work)
 		goto out;
 	}
 
-	if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
-			cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
-			0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE) < 0)
+	if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, cmd->cmd_buf,
+			      cmd->sense_iu.sense, cmd->unpacked_lun, 0,
+			      cmd->prio_attr, dir, flags) < 0)
 		goto out;
 
 	return;
@@ -1070,7 +1063,7 @@ static void usbg_cmd_work(struct work_struct *work)
 out:
 	transport_send_check_condition_and_sense(se_cmd,
 			TCM_UNSUPPORTED_SCSI_OPCODE, 1);
-	usbg_cleanup_cmd(cmd);
+	transport_generic_free_cmd(&cmd->se_cmd, 0);
 }
 
 static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu,
@@ -1125,11 +1118,6 @@ static int usbg_submit_command(struct f_uas *fu,
 		pr_err("usbg_get_cmd failed\n");
 		return -ENOMEM;
 	}
-
-	/* XXX until I figure out why I can't free in on complete */
-	kref_init(&cmd->ref);
-	kref_get(&cmd->ref);
-
 	memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
 
 	if (fu->flags & USBG_USE_STREAMS) {
@@ -1202,7 +1190,7 @@ static void bot_cmd_work(struct work_struct *work)
 out:
 	transport_send_check_condition_and_sense(se_cmd,
 				TCM_UNSUPPORTED_SCSI_OPCODE, 1);
-	usbg_cleanup_cmd(cmd);
+	transport_generic_free_cmd(&cmd->se_cmd, 0);
 }
 
 static int bot_submit_command(struct f_uas *fu,
@@ -1238,11 +1226,6 @@ static int bot_submit_command(struct f_uas *fu,
 		pr_err("usbg_get_cmd failed\n");
 		return -ENOMEM;
 	}
-
-	/* XXX until I figure out why I can't free in on complete */
-	kref_init(&cmd->ref);
-	kref_get(&cmd->ref);
-
 	memcpy(cmd->cmd_buf, cbw->CDB, cmd_len);
 
 	cmd->bot_tag = cbw->Tag;
@@ -1296,14 +1279,6 @@ static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg)
 	return 1;
 }
 
-static void usbg_cmd_release(struct kref *ref)
-{
-	struct usbg_cmd *cmd = container_of(ref, struct usbg_cmd,
-			ref);
-
-	transport_generic_free_cmd(&cmd->se_cmd, 0);
-}
-
 static void usbg_release_cmd(struct se_cmd *se_cmd)
 {
 	struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
@@ -1733,11 +1708,7 @@ static void usbg_port_unlink(struct se_portal_group *se_tpg,
 
 static int usbg_check_stop_free(struct se_cmd *se_cmd)
 {
-	struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
-			se_cmd);
-
-	kref_put(&cmd->ref, usbg_cmd_release);
-	return 1;
+	return target_put_sess_cmd(se_cmd);
 }
 
 static const struct target_core_fabric_ops usbg_ops = {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
                   ` (9 preceding siblings ...)
  2016-01-25  8:11 ` [PATCH-v2 10/12] usb-gadget/tcm: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
@ 2016-01-25  8:11 ` Nicholas A. Bellinger
  2016-01-25 15:42   ` Juergen Gross
  2016-01-26  9:45   ` Juergen Gross
  2016-01-25  8:11 ` [PATCH-v2 12/12] xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
  11 siblings, 2 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:11 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger, David Vrabel

From: Nicholas Bellinger <nab@linux-iscsi.org>

Cc: Juergen Gross <jgross@suse.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/xen/xen-scsiback.c | 163 ++++++++++++++++++++++++---------------------
 1 file changed, 87 insertions(+), 76 deletions(-)

diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 594f8a7..640fb22 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -190,7 +190,6 @@ module_param_named(max_buffer_pages, scsiback_max_buffer_pages, int, 0644);
 MODULE_PARM_DESC(max_buffer_pages,
 "Maximum number of free pages to keep in backend buffer");
 
-static struct kmem_cache *scsiback_cachep;
 static DEFINE_SPINLOCK(free_pages_lock);
 static int free_pages_num;
 static LIST_HEAD(scsiback_free_pages);
@@ -322,7 +321,8 @@ static void scsiback_free_translation_entry(struct kref *kref)
 }
 
 static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
-			uint32_t resid, struct vscsibk_pend *pending_req)
+			uint32_t resid, struct vscsibk_pend *pending_req,
+			uint16_t rqid)
 {
 	struct vscsiif_response *ring_res;
 	struct vscsibk_info *info = pending_req->info;
@@ -337,7 +337,7 @@ static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
 	info->ring.rsp_prod_pvt++;
 
 	ring_res->rslt   = result;
-	ring_res->rqid   = pending_req->rqid;
+	ring_res->rqid   = rqid;
 
 	if (sense_buffer != NULL &&
 	    scsi_normalize_sense(sense_buffer, VSCSIIF_SENSE_BUFFERSIZE,
@@ -358,7 +358,7 @@ static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
 	if (notify)
 		notify_remote_via_irq(info->irq);
 
-	if (pending_req->v2p)
+	if (pending_req && pending_req->v2p)
 		kref_put(&pending_req->v2p->kref,
 			 scsiback_free_translation_entry);
 }
@@ -378,7 +378,8 @@ static void scsiback_cmd_done(struct vscsibk_pend *pending_req)
 		scsiback_print_status(sense_buffer, errors, pending_req);
 
 	scsiback_fast_flush_area(pending_req);
-	scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req);
+	scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req,
+				    pending_req->rqid);
 	scsiback_put(info);
 }
 
@@ -616,15 +617,15 @@ static void scsiback_device_action(struct vscsibk_pend *pending_req,
 	err = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
 		SUCCESS : FAILED;
 
-out:
-	if (tmr) {
-		transport_generic_free_cmd(&pending_req->se_cmd, 1);
+	scsiback_do_resp_with_sense(NULL, err, 0, pending_req,
+				    pending_req->rqid);
+	transport_generic_free_cmd(&pending_req->se_cmd, 1);
+	return;
+err:
+	if (tmr)
 		kfree(tmr);
-	}
-
-	scsiback_do_resp_with_sense(NULL, err, 0, pending_req);
-
-	kmem_cache_free(scsiback_cachep, pending_req);
+	scsiback_do_resp_with_sense(NULL, err, 0, pending_req,
+				    pending_req->rqid);
 }
 
 /*
@@ -653,15 +654,53 @@ out:
 	return entry;
 }
 
-static int prepare_pending_reqs(struct vscsibk_info *info,
-				struct vscsiif_request *ring_req,
-				struct vscsibk_pend *pending_req)
+static struct vscsibk_pend *scsiback_get_pend_req(struct vscsiif_back_ring *ring,
+				struct v2p_entry *v2p)
+{
+	struct scsiback_tpg *tpg = v2p->tpg;
+	struct scsiback_nexus *nexus = tpg->tpg_nexus;
+	struct se_session *se_sess = nexus->tvn_se_sess;
+	struct vscsibk_pend *req;
+	int tag, i;
+
+	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
+	if (tag < 0) {
+		pr_err("Unable to obtain tag for vscsiif_request\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	req = &((struct vscsibk_pend *)se_sess->sess_cmd_map)[tag];
+	memset(req, 0, sizeof(*req));
+	req->se_cmd.map_tag = tag;
+
+	for (i = 0; i < VSCSI_MAX_GRANTS; i++)
+		req->grant_handles[i] = SCSIBACK_INVALID_HANDLE;
+
+	return req;
+}
+
+static struct vscsibk_pend *prepare_pending_reqs(struct vscsibk_info *info,
+				struct vscsiif_back_ring *ring,
+				struct vscsiif_request *ring_req)
 {
+	struct vscsibk_pend *pending_req;
 	struct v2p_entry *v2p;
 	struct ids_tuple vir;
 
-	pending_req->rqid       = ring_req->rqid;
-	pending_req->info       = info;
+	/* request range check from frontend */
+	if ((ring_req->sc_data_direction != DMA_BIDIRECTIONAL) &&
+		(ring_req->sc_data_direction != DMA_TO_DEVICE) &&
+		(ring_req->sc_data_direction != DMA_FROM_DEVICE) &&
+		(ring_req->sc_data_direction != DMA_NONE)) {
+		pr_debug("invalid parameter data_dir = %d\n",
+			ring_req->sc_data_direction);
+		return ERR_PTR(-EINVAL);
+	}
+	if (ring_req->cmd_len > VSCSIIF_MAX_COMMAND_SIZE) {
+		pr_debug("invalid parameter cmd_len = %d\n",
+			ring_req->cmd_len);
+		return ERR_PTR(-EINVAL);
+	}
 
 	vir.chn = ring_req->channel;
 	vir.tgt = ring_req->id;
@@ -669,33 +708,24 @@ static int prepare_pending_reqs(struct vscsibk_info *info,
 
 	v2p = scsiback_do_translation(info, &vir);
 	if (!v2p) {
-		pending_req->v2p = NULL;
 		pr_debug("the v2p of (chn:%d, tgt:%d, lun:%d) doesn't exist.\n",
-			vir.chn, vir.tgt, vir.lun);
-		return -ENODEV;
+			 vir.chn, vir.tgt, vir.lun);
+		return ERR_PTR(-ENODEV);
 	}
-	pending_req->v2p = v2p;
 
-	/* request range check from frontend */
-	pending_req->sc_data_direction = ring_req->sc_data_direction;
-	if ((pending_req->sc_data_direction != DMA_BIDIRECTIONAL) &&
-		(pending_req->sc_data_direction != DMA_TO_DEVICE) &&
-		(pending_req->sc_data_direction != DMA_FROM_DEVICE) &&
-		(pending_req->sc_data_direction != DMA_NONE)) {
-		pr_debug("invalid parameter data_dir = %d\n",
-			pending_req->sc_data_direction);
-		return -EINVAL;
+	pending_req = scsiback_get_pend_req(ring, v2p);
+	if (IS_ERR(pending_req)) {
+		kref_put(&v2p->kref, scsiback_free_translation_entry);
+		return ERR_PTR(-ENOMEM);
 	}
-
+	pending_req->rqid = ring_req->rqid;
+	pending_req->info = info;
+	pending_req->v2p = v2p;
+	pending_req->sc_data_direction = ring_req->sc_data_direction;
 	pending_req->cmd_len = ring_req->cmd_len;
-	if (pending_req->cmd_len > VSCSIIF_MAX_COMMAND_SIZE) {
-		pr_debug("invalid parameter cmd_len = %d\n",
-			pending_req->cmd_len);
-		return -EINVAL;
-	}
 	memcpy(pending_req->cmnd, ring_req->cmnd, pending_req->cmd_len);
 
-	return 0;
+	return pending_req;
 }
 
 static int scsiback_do_cmd_fn(struct vscsibk_info *info)
@@ -704,7 +734,7 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
 	struct vscsiif_request ring_req;
 	struct vscsibk_pend *pending_req;
 	RING_IDX rc, rp;
-	int err, more_to_do;
+	int more_to_do;
 	uint32_t result;
 
 	rc = ring->req_cons;
@@ -722,16 +752,13 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
 	while ((rc != rp)) {
 		if (RING_REQUEST_CONS_OVERFLOW(ring, rc))
 			break;
-		pending_req = kmem_cache_alloc(scsiback_cachep, GFP_KERNEL);
-		if (!pending_req)
-			return 1;
 
 		ring_req = *RING_GET_REQUEST(ring, rc);
 		ring->req_cons = ++rc;
 
-		err = prepare_pending_reqs(info, &ring_req, pending_req);
-		if (err) {
-			switch (err) {
+		pending_req = prepare_pending_reqs(info, ring, &ring_req);
+		if (IS_ERR(pending_req)) {
+			switch (PTR_ERR(pending_req)) {
 			case -ENODEV:
 				result = DID_NO_CONNECT;
 				break;
@@ -739,9 +766,8 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
 				result = DRIVER_ERROR;
 				break;
 			}
-			scsiback_do_resp_with_sense(NULL, result << 24, 0,
-						    pending_req);
-			kmem_cache_free(scsiback_cachep, pending_req);
+			scsiback_do_resp_with_sense(NULL, result << 24, 0, NULL,
+						    ring_req.rqid);
 			return 1;
 		}
 
@@ -750,8 +776,9 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
 			if (scsiback_gnttab_data_map(&ring_req, pending_req)) {
 				scsiback_fast_flush_area(pending_req);
 				scsiback_do_resp_with_sense(NULL,
-					DRIVER_ERROR << 24, 0, pending_req);
-				kmem_cache_free(scsiback_cachep, pending_req);
+						DRIVER_ERROR << 24, 0, pending_req,
+					        pending_req->rqid);
+				transport_generic_free_cmd(&pending_req->se_cmd, 0);
 			} else {
 				scsiback_cmd_exec(pending_req);
 			}
@@ -765,9 +792,9 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
 			break;
 		default:
 			pr_err_ratelimited("invalid request\n");
-			scsiback_do_resp_with_sense(NULL, DRIVER_ERROR << 24,
-						    0, pending_req);
-			kmem_cache_free(scsiback_cachep, pending_req);
+			scsiback_do_resp_with_sense(NULL, DRIVER_ERROR << 24, 0,
+						    pending_req, pending_req->rqid);
+			transport_generic_free_cmd(&pending_req->se_cmd, 0);
 			break;
 		}
 
@@ -1355,10 +1382,10 @@ static int scsiback_check_stop_free(struct se_cmd *se_cmd)
 
 static void scsiback_release_cmd(struct se_cmd *se_cmd)
 {
-	struct vscsibk_pend *pending_req = container_of(se_cmd,
-				struct vscsibk_pend, se_cmd);
+	struct se_session *se_sess = se_cmd->se_sess;
+	struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
 
-	kmem_cache_free(scsiback_cachep, pending_req);
+	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
 }
 
 static int scsiback_shutdown_session(struct se_session *se_sess)
@@ -1501,7 +1528,8 @@ static int scsiback_make_nexus(struct scsiback_tpg *tpg,
 		goto out_unlock;
 	}
 
-	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 0, 0,
+	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 128,
+						     sizeof(struct vscsibk_pend),
 						     TARGET_PROT_NORMAL, name,
 						     tv_nexus, NULL);
 	if (IS_ERR(tv_nexus->tvn_se_sess)) {
@@ -1831,16 +1859,6 @@ static struct xenbus_driver scsiback_driver = {
 	.otherend_changed	= scsiback_frontend_changed
 };
 
-static void scsiback_init_pend(void *p)
-{
-	struct vscsibk_pend *pend = p;
-	int i;
-
-	memset(pend, 0, sizeof(*pend));
-	for (i = 0; i < VSCSI_MAX_GRANTS; i++)
-		pend->grant_handles[i] = SCSIBACK_INVALID_HANDLE;
-}
-
 static int __init scsiback_init(void)
 {
 	int ret;
@@ -1851,14 +1869,9 @@ static int __init scsiback_init(void)
 	pr_debug("xen-pvscsi: fabric module %s on %s/%s on "UTS_RELEASE"\n",
 		 VSCSI_VERSION, utsname()->sysname, utsname()->machine);
 
-	scsiback_cachep = kmem_cache_create("vscsiif_cache",
-		sizeof(struct vscsibk_pend), 0, 0, scsiback_init_pend);
-	if (!scsiback_cachep)
-		return -ENOMEM;
-
 	ret = xenbus_register_backend(&scsiback_driver);
 	if (ret)
-		goto out_cache_destroy;
+		goto out;
 
 	ret = target_register_template(&scsiback_ops);
 	if (ret)
@@ -1868,8 +1881,7 @@ static int __init scsiback_init(void)
 
 out_unregister_xenbus:
 	xenbus_unregister_driver(&scsiback_driver);
-out_cache_destroy:
-	kmem_cache_destroy(scsiback_cachep);
+out:
 	pr_err("%s: error %d\n", __func__, ret);
 	return ret;
 }
@@ -1885,7 +1897,6 @@ static void __exit scsiback_exit(void)
 	}
 	target_unregister_template(&scsiback_ops);
 	xenbus_unregister_driver(&scsiback_driver);
-	kmem_cache_destroy(scsiback_cachep);
 }
 
 module_init(scsiback_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH-v2 12/12] xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs
  2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
                   ` (10 preceding siblings ...)
  2016-01-25  8:11 ` [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation Nicholas A. Bellinger
@ 2016-01-25  8:11 ` Nicholas A. Bellinger
  2016-01-26  9:49   ` Juergen Gross
  11 siblings, 1 reply; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-25  8:11 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Juergen Gross, Andrzej Pietrasiewicz, Chris Boot,
	Nicholas Bellinger, David Vrabel

From: Nicholas Bellinger <nab@linux-iscsi.org>

Cc: Juergen Gross <jgross@suse.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/xen/xen-scsiback.c | 53 +++++++++++++++++++++++-----------------------
 1 file changed, 26 insertions(+), 27 deletions(-)

diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 640fb22..a10e5f1 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -381,6 +381,12 @@ static void scsiback_cmd_done(struct vscsibk_pend *pending_req)
 	scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req,
 				    pending_req->rqid);
 	scsiback_put(info);
+	/*
+	 * Drop the extra KREF_ACK reference taken by target_submit_cmd_map_sgls()
+	 * ahead of scsiback_check_stop_free() ->  transport_generic_free_cmd()
+	 * final se_cmd->cmd_kref put.
+	 */
+	target_put_sess_cmd(&pending_req->se_cmd);
 }
 
 static void scsiback_cmd_exec(struct vscsibk_pend *pending_req)
@@ -398,7 +404,7 @@ static void scsiback_cmd_exec(struct vscsibk_pend *pending_req)
 	rc = target_submit_cmd_map_sgls(se_cmd, sess, pending_req->cmnd,
 			pending_req->sense_buffer, pending_req->v2p->lun,
 			pending_req->data_len, 0,
-			pending_req->sc_data_direction, 0,
+			pending_req->sc_data_direction, TARGET_SCF_ACK_KREF,
 			pending_req->sgl, pending_req->n_sg,
 			NULL, 0, NULL, 0);
 	if (rc < 0) {
@@ -587,31 +593,28 @@ static void scsiback_disconnect(struct vscsibk_info *info)
 static void scsiback_device_action(struct vscsibk_pend *pending_req,
 	enum tcm_tmreq_table act, int tag)
 {
-	int rc, err = FAILED;
 	struct scsiback_tpg *tpg = pending_req->v2p->tpg;
+	struct scsiback_nexus *nexus = tpg->tpg_nexus;
 	struct se_cmd *se_cmd = &pending_req->se_cmd;
 	struct scsiback_tmr *tmr;
+	u64 unpacked_lun = pending_req->v2p->lun;
+	int rc, err = FAILED;
 
 	tmr = kzalloc(sizeof(struct scsiback_tmr), GFP_KERNEL);
-	if (!tmr)
-		goto out;
+	if (!tmr) {
+		target_put_sess_cmd(se_cmd);
+		goto err;
+	}
 
 	init_waitqueue_head(&tmr->tmr_wait);
 
-	transport_init_se_cmd(se_cmd, tpg->se_tpg.se_tpg_tfo,
-		tpg->tpg_nexus->tvn_se_sess, 0, DMA_NONE, TCM_SIMPLE_TAG,
-		&pending_req->sense_buffer[0]);
-
-	rc = core_tmr_alloc_req(se_cmd, tmr, act, GFP_KERNEL);
-	if (rc < 0)
-		goto out;
-
-	se_cmd->se_tmr_req->ref_task_tag = tag;
+	rc = target_submit_tmr(&pending_req->se_cmd, nexus->tvn_se_sess,
+			       &pending_req->sense_buffer[0],
+			       unpacked_lun, tmr, act, GFP_KERNEL,
+			       tag, TARGET_SCF_ACK_KREF);
+	if (rc)
+		goto err;
 
-	if (transport_lookup_tmr_lun(se_cmd, pending_req->v2p->lun) < 0)
-		goto out;
-
-	transport_generic_handle_tmr(se_cmd);
 	wait_event(tmr->tmr_wait, atomic_read(&tmr->tmr_complete));
 
 	err = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
@@ -1368,16 +1371,7 @@ static u32 scsiback_tpg_get_inst_index(struct se_portal_group *se_tpg)
 
 static int scsiback_check_stop_free(struct se_cmd *se_cmd)
 {
-	/*
-	 * Do not release struct se_cmd's containing a valid TMR pointer.
-	 * These will be released directly in scsiback_device_action()
-	 * with transport_generic_free_cmd().
-	 */
-	if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
-		return 0;
-
-	transport_generic_free_cmd(se_cmd, 0);
-	return 1;
+	return transport_generic_free_cmd(se_cmd, 0);
 }
 
 static void scsiback_release_cmd(struct se_cmd *se_cmd)
@@ -1385,6 +1379,11 @@ static void scsiback_release_cmd(struct se_cmd *se_cmd)
 	struct se_session *se_sess = se_cmd->se_sess;
 	struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
 
+	if (se_tmr && se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) {
+		struct scsiback_tmr *tmr = se_tmr->fabric_tmr_ptr;
+		kfree(tmr);
+	}
+
 	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation
  2016-01-25  8:11 ` [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation Nicholas A. Bellinger
@ 2016-01-25 15:42   ` Juergen Gross
  2016-01-26  5:15     ` Nicholas A. Bellinger
  2016-01-26  9:45   ` Juergen Gross
  1 sibling, 1 reply; 22+ messages in thread
From: Juergen Gross @ 2016-01-25 15:42 UTC (permalink / raw)
  To: Nicholas A. Bellinger, target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Andrzej Pietrasiewicz, Chris Boot, Nicholas Bellinger,
	David Vrabel

On 25/01/16 09:11, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
> 
> Cc: Juergen Gross <jgross@suse.com>
> Cc: Hannes Reinecke <hare@suse.de>
> Cc: David Vrabel <david.vrabel@citrix.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

Could you please rebase to current version? The patch won't apply.


Juergen

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation
  2016-01-25 15:42   ` Juergen Gross
@ 2016-01-26  5:15     ` Nicholas A. Bellinger
  0 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-26  5:15 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Nicholas A. Bellinger, target-devel, linux-scsi,
	Christoph Hellwig, Hannes Reinecke, Mike Christie, Sagi Grimberg,
	Andy Grover, Sebastian Andrzej Siewior, Andrzej Pietrasiewicz,
	Chris Boot, David Vrabel

On Mon, 2016-01-25 at 16:42 +0100, Juergen Gross wrote:
> On 25/01/16 09:11, Nicholas A. Bellinger wrote:
> > From: Nicholas Bellinger <nab@linux-iscsi.org>
> > 
> > Cc: Juergen Gross <jgross@suse.com>
> > Cc: Hannes Reinecke <hare@suse.de>
> > Cc: David Vrabel <david.vrabel@citrix.com>
> > Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> 
> Could you please rebase to current version? The patch won't apply.
> 

Yep, will be updating target-pending/queue-next to v4.5-rc1 over the
next days.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation
  2016-01-25  8:11 ` [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation Nicholas A. Bellinger
  2016-01-25 15:42   ` Juergen Gross
@ 2016-01-26  9:45   ` Juergen Gross
  2016-01-27  6:28     ` Nicholas A. Bellinger
  1 sibling, 1 reply; 22+ messages in thread
From: Juergen Gross @ 2016-01-26  9:45 UTC (permalink / raw)
  To: Nicholas A. Bellinger, target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Andrzej Pietrasiewicz, Chris Boot, Nicholas Bellinger,
	David Vrabel

On 25/01/16 09:11, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
> 
> Cc: Juergen Gross <jgross@suse.com>
> Cc: Hannes Reinecke <hare@suse.de>
> Cc: David Vrabel <david.vrabel@citrix.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> ---
>  drivers/xen/xen-scsiback.c | 163 ++++++++++++++++++++++++---------------------
>  1 file changed, 87 insertions(+), 76 deletions(-)
> 
> diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
> index 594f8a7..640fb22 100644
> --- a/drivers/xen/xen-scsiback.c
> +++ b/drivers/xen/xen-scsiback.c
> @@ -190,7 +190,6 @@ module_param_named(max_buffer_pages, scsiback_max_buffer_pages, int, 0644);
>  MODULE_PARM_DESC(max_buffer_pages,
>  "Maximum number of free pages to keep in backend buffer");
>  
> -static struct kmem_cache *scsiback_cachep;
>  static DEFINE_SPINLOCK(free_pages_lock);
>  static int free_pages_num;
>  static LIST_HEAD(scsiback_free_pages);
> @@ -322,7 +321,8 @@ static void scsiback_free_translation_entry(struct kref *kref)
>  }
>  
>  static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
> -			uint32_t resid, struct vscsibk_pend *pending_req)
> +			uint32_t resid, struct vscsibk_pend *pending_req,
> +			uint16_t rqid)
>  {
>  	struct vscsiif_response *ring_res;
>  	struct vscsibk_info *info = pending_req->info;

pending_req might be NULL now, so this will panic the system.


Juergen

> @@ -337,7 +337,7 @@ static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
>  	info->ring.rsp_prod_pvt++;
>  
>  	ring_res->rslt   = result;
> -	ring_res->rqid   = pending_req->rqid;
> +	ring_res->rqid   = rqid;
>  
>  	if (sense_buffer != NULL &&
>  	    scsi_normalize_sense(sense_buffer, VSCSIIF_SENSE_BUFFERSIZE,
> @@ -358,7 +358,7 @@ static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
>  	if (notify)
>  		notify_remote_via_irq(info->irq);
>  
> -	if (pending_req->v2p)
> +	if (pending_req && pending_req->v2p)
>  		kref_put(&pending_req->v2p->kref,
>  			 scsiback_free_translation_entry);
>  }
> @@ -378,7 +378,8 @@ static void scsiback_cmd_done(struct vscsibk_pend *pending_req)
>  		scsiback_print_status(sense_buffer, errors, pending_req);
>  
>  	scsiback_fast_flush_area(pending_req);
> -	scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req);
> +	scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req,
> +				    pending_req->rqid);
>  	scsiback_put(info);
>  }
>  
> @@ -616,15 +617,15 @@ static void scsiback_device_action(struct vscsibk_pend *pending_req,
>  	err = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
>  		SUCCESS : FAILED;
>  
> -out:
> -	if (tmr) {
> -		transport_generic_free_cmd(&pending_req->se_cmd, 1);
> +	scsiback_do_resp_with_sense(NULL, err, 0, pending_req,
> +				    pending_req->rqid);
> +	transport_generic_free_cmd(&pending_req->se_cmd, 1);
> +	return;
> +err:
> +	if (tmr)
>  		kfree(tmr);
> -	}
> -
> -	scsiback_do_resp_with_sense(NULL, err, 0, pending_req);
> -
> -	kmem_cache_free(scsiback_cachep, pending_req);
> +	scsiback_do_resp_with_sense(NULL, err, 0, pending_req,
> +				    pending_req->rqid);
>  }
>  
>  /*
> @@ -653,15 +654,53 @@ out:
>  	return entry;
>  }
>  
> -static int prepare_pending_reqs(struct vscsibk_info *info,
> -				struct vscsiif_request *ring_req,
> -				struct vscsibk_pend *pending_req)
> +static struct vscsibk_pend *scsiback_get_pend_req(struct vscsiif_back_ring *ring,
> +				struct v2p_entry *v2p)
> +{
> +	struct scsiback_tpg *tpg = v2p->tpg;
> +	struct scsiback_nexus *nexus = tpg->tpg_nexus;
> +	struct se_session *se_sess = nexus->tvn_se_sess;
> +	struct vscsibk_pend *req;
> +	int tag, i;
> +
> +	tag = percpu_ida_alloc(&se_sess->sess_tag_pool, TASK_RUNNING);
> +	if (tag < 0) {
> +		pr_err("Unable to obtain tag for vscsiif_request\n");
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	req = &((struct vscsibk_pend *)se_sess->sess_cmd_map)[tag];
> +	memset(req, 0, sizeof(*req));
> +	req->se_cmd.map_tag = tag;
> +
> +	for (i = 0; i < VSCSI_MAX_GRANTS; i++)
> +		req->grant_handles[i] = SCSIBACK_INVALID_HANDLE;
> +
> +	return req;
> +}
> +
> +static struct vscsibk_pend *prepare_pending_reqs(struct vscsibk_info *info,
> +				struct vscsiif_back_ring *ring,
> +				struct vscsiif_request *ring_req)
>  {
> +	struct vscsibk_pend *pending_req;
>  	struct v2p_entry *v2p;
>  	struct ids_tuple vir;
>  
> -	pending_req->rqid       = ring_req->rqid;
> -	pending_req->info       = info;
> +	/* request range check from frontend */
> +	if ((ring_req->sc_data_direction != DMA_BIDIRECTIONAL) &&
> +		(ring_req->sc_data_direction != DMA_TO_DEVICE) &&
> +		(ring_req->sc_data_direction != DMA_FROM_DEVICE) &&
> +		(ring_req->sc_data_direction != DMA_NONE)) {
> +		pr_debug("invalid parameter data_dir = %d\n",
> +			ring_req->sc_data_direction);
> +		return ERR_PTR(-EINVAL);
> +	}
> +	if (ring_req->cmd_len > VSCSIIF_MAX_COMMAND_SIZE) {
> +		pr_debug("invalid parameter cmd_len = %d\n",
> +			ring_req->cmd_len);
> +		return ERR_PTR(-EINVAL);
> +	}
>  
>  	vir.chn = ring_req->channel;
>  	vir.tgt = ring_req->id;
> @@ -669,33 +708,24 @@ static int prepare_pending_reqs(struct vscsibk_info *info,
>  
>  	v2p = scsiback_do_translation(info, &vir);
>  	if (!v2p) {
> -		pending_req->v2p = NULL;
>  		pr_debug("the v2p of (chn:%d, tgt:%d, lun:%d) doesn't exist.\n",
> -			vir.chn, vir.tgt, vir.lun);
> -		return -ENODEV;
> +			 vir.chn, vir.tgt, vir.lun);
> +		return ERR_PTR(-ENODEV);
>  	}
> -	pending_req->v2p = v2p;
>  
> -	/* request range check from frontend */
> -	pending_req->sc_data_direction = ring_req->sc_data_direction;
> -	if ((pending_req->sc_data_direction != DMA_BIDIRECTIONAL) &&
> -		(pending_req->sc_data_direction != DMA_TO_DEVICE) &&
> -		(pending_req->sc_data_direction != DMA_FROM_DEVICE) &&
> -		(pending_req->sc_data_direction != DMA_NONE)) {
> -		pr_debug("invalid parameter data_dir = %d\n",
> -			pending_req->sc_data_direction);
> -		return -EINVAL;
> +	pending_req = scsiback_get_pend_req(ring, v2p);
> +	if (IS_ERR(pending_req)) {
> +		kref_put(&v2p->kref, scsiback_free_translation_entry);
> +		return ERR_PTR(-ENOMEM);
>  	}
> -
> +	pending_req->rqid = ring_req->rqid;
> +	pending_req->info = info;
> +	pending_req->v2p = v2p;
> +	pending_req->sc_data_direction = ring_req->sc_data_direction;
>  	pending_req->cmd_len = ring_req->cmd_len;
> -	if (pending_req->cmd_len > VSCSIIF_MAX_COMMAND_SIZE) {
> -		pr_debug("invalid parameter cmd_len = %d\n",
> -			pending_req->cmd_len);
> -		return -EINVAL;
> -	}
>  	memcpy(pending_req->cmnd, ring_req->cmnd, pending_req->cmd_len);
>  
> -	return 0;
> +	return pending_req;
>  }
>  
>  static int scsiback_do_cmd_fn(struct vscsibk_info *info)
> @@ -704,7 +734,7 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
>  	struct vscsiif_request ring_req;
>  	struct vscsibk_pend *pending_req;
>  	RING_IDX rc, rp;
> -	int err, more_to_do;
> +	int more_to_do;
>  	uint32_t result;
>  
>  	rc = ring->req_cons;
> @@ -722,16 +752,13 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
>  	while ((rc != rp)) {
>  		if (RING_REQUEST_CONS_OVERFLOW(ring, rc))
>  			break;
> -		pending_req = kmem_cache_alloc(scsiback_cachep, GFP_KERNEL);
> -		if (!pending_req)
> -			return 1;
>  
>  		ring_req = *RING_GET_REQUEST(ring, rc);
>  		ring->req_cons = ++rc;
>  
> -		err = prepare_pending_reqs(info, &ring_req, pending_req);
> -		if (err) {
> -			switch (err) {
> +		pending_req = prepare_pending_reqs(info, ring, &ring_req);
> +		if (IS_ERR(pending_req)) {
> +			switch (PTR_ERR(pending_req)) {
>  			case -ENODEV:
>  				result = DID_NO_CONNECT;
>  				break;
> @@ -739,9 +766,8 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
>  				result = DRIVER_ERROR;
>  				break;
>  			}
> -			scsiback_do_resp_with_sense(NULL, result << 24, 0,
> -						    pending_req);
> -			kmem_cache_free(scsiback_cachep, pending_req);
> +			scsiback_do_resp_with_sense(NULL, result << 24, 0, NULL,
> +						    ring_req.rqid);
>  			return 1;
>  		}
>  
> @@ -750,8 +776,9 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
>  			if (scsiback_gnttab_data_map(&ring_req, pending_req)) {
>  				scsiback_fast_flush_area(pending_req);
>  				scsiback_do_resp_with_sense(NULL,
> -					DRIVER_ERROR << 24, 0, pending_req);
> -				kmem_cache_free(scsiback_cachep, pending_req);
> +						DRIVER_ERROR << 24, 0, pending_req,
> +					        pending_req->rqid);
> +				transport_generic_free_cmd(&pending_req->se_cmd, 0);
>  			} else {
>  				scsiback_cmd_exec(pending_req);
>  			}
> @@ -765,9 +792,9 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
>  			break;
>  		default:
>  			pr_err_ratelimited("invalid request\n");
> -			scsiback_do_resp_with_sense(NULL, DRIVER_ERROR << 24,
> -						    0, pending_req);
> -			kmem_cache_free(scsiback_cachep, pending_req);
> +			scsiback_do_resp_with_sense(NULL, DRIVER_ERROR << 24, 0,
> +						    pending_req, pending_req->rqid);
> +			transport_generic_free_cmd(&pending_req->se_cmd, 0);
>  			break;
>  		}
>  
> @@ -1355,10 +1382,10 @@ static int scsiback_check_stop_free(struct se_cmd *se_cmd)
>  
>  static void scsiback_release_cmd(struct se_cmd *se_cmd)
>  {
> -	struct vscsibk_pend *pending_req = container_of(se_cmd,
> -				struct vscsibk_pend, se_cmd);
> +	struct se_session *se_sess = se_cmd->se_sess;
> +	struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
>  
> -	kmem_cache_free(scsiback_cachep, pending_req);
> +	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
>  }
>  
>  static int scsiback_shutdown_session(struct se_session *se_sess)
> @@ -1501,7 +1528,8 @@ static int scsiback_make_nexus(struct scsiback_tpg *tpg,
>  		goto out_unlock;
>  	}
>  
> -	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 0, 0,
> +	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 128,
> +						     sizeof(struct vscsibk_pend),
>  						     TARGET_PROT_NORMAL, name,
>  						     tv_nexus, NULL);
>  	if (IS_ERR(tv_nexus->tvn_se_sess)) {
> @@ -1831,16 +1859,6 @@ static struct xenbus_driver scsiback_driver = {
>  	.otherend_changed	= scsiback_frontend_changed
>  };
>  
> -static void scsiback_init_pend(void *p)
> -{
> -	struct vscsibk_pend *pend = p;
> -	int i;
> -
> -	memset(pend, 0, sizeof(*pend));
> -	for (i = 0; i < VSCSI_MAX_GRANTS; i++)
> -		pend->grant_handles[i] = SCSIBACK_INVALID_HANDLE;
> -}
> -
>  static int __init scsiback_init(void)
>  {
>  	int ret;
> @@ -1851,14 +1869,9 @@ static int __init scsiback_init(void)
>  	pr_debug("xen-pvscsi: fabric module %s on %s/%s on "UTS_RELEASE"\n",
>  		 VSCSI_VERSION, utsname()->sysname, utsname()->machine);
>  
> -	scsiback_cachep = kmem_cache_create("vscsiif_cache",
> -		sizeof(struct vscsibk_pend), 0, 0, scsiback_init_pend);
> -	if (!scsiback_cachep)
> -		return -ENOMEM;
> -
>  	ret = xenbus_register_backend(&scsiback_driver);
>  	if (ret)
> -		goto out_cache_destroy;
> +		goto out;
>  
>  	ret = target_register_template(&scsiback_ops);
>  	if (ret)
> @@ -1868,8 +1881,7 @@ static int __init scsiback_init(void)
>  
>  out_unregister_xenbus:
>  	xenbus_unregister_driver(&scsiback_driver);
> -out_cache_destroy:
> -	kmem_cache_destroy(scsiback_cachep);
> +out:
>  	pr_err("%s: error %d\n", __func__, ret);
>  	return ret;
>  }
> @@ -1885,7 +1897,6 @@ static void __exit scsiback_exit(void)
>  	}
>  	target_unregister_template(&scsiback_ops);
>  	xenbus_unregister_driver(&scsiback_driver);
> -	kmem_cache_destroy(scsiback_cachep);
>  }
>  
>  module_init(scsiback_init);
> 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH-v2 02/12] target: Convert demo-mode only drivers to target_alloc_session
  2016-01-25  8:10 ` [PATCH-v2 02/12] target: Convert demo-mode only drivers to target_alloc_session Nicholas A. Bellinger
@ 2016-01-26  9:45   ` Juergen Gross
  0 siblings, 0 replies; 22+ messages in thread
From: Juergen Gross @ 2016-01-26  9:45 UTC (permalink / raw)
  To: Nicholas A. Bellinger, target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Andrzej Pietrasiewicz, Chris Boot

On 25/01/16 09:10, Nicholas A. Bellinger wrote:
> From: Christoph Hellwig <hch@lst.de>
> 
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: Hannes Reinecke <hare@suse.de>
> Cc: Chris Boot <bootc@bootc.net>
> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Cc: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
> Cc: Juergen Gross <jgross@suse.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> ---
>  drivers/target/loopback/tcm_loop.c  | 35 +++++--------------------
>  drivers/target/sbp/sbp_target.c     | 33 ++++++------------------
>  drivers/usb/gadget/function/f_tcm.c | 45 ++++++++++----------------------
>  drivers/xen/xen-scsiback.c          | 51 ++++++++++---------------------------
>  4 files changed, 42 insertions(+), 122 deletions(-)

Regarding drivers/xen/xen-scsiback.c:
Acked-by: Juergen Gross <jgross@suse.com>

> 
> diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
> index d41a5c3..0216c75 100644
> --- a/drivers/target/loopback/tcm_loop.c
> +++ b/drivers/target/loopback/tcm_loop.c
> @@ -806,54 +806,33 @@ static int tcm_loop_make_nexus(
>  	struct tcm_loop_tpg *tl_tpg,
>  	const char *name)
>  {
> -	struct se_portal_group *se_tpg;
>  	struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
>  	struct tcm_loop_nexus *tl_nexus;
> -	int ret = -ENOMEM;
>  
>  	if (tl_tpg->tl_nexus) {
>  		pr_debug("tl_tpg->tl_nexus already exists\n");
>  		return -EEXIST;
>  	}
> -	se_tpg = &tl_tpg->tl_se_tpg;
>  
>  	tl_nexus = kzalloc(sizeof(struct tcm_loop_nexus), GFP_KERNEL);
>  	if (!tl_nexus) {
>  		pr_err("Unable to allocate struct tcm_loop_nexus\n");
>  		return -ENOMEM;
>  	}
> -	/*
> -	 * Initialize the struct se_session pointer
> -	 */
> -	tl_nexus->se_sess = transport_init_session(
> -				TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS);
> +
> +	tl_nexus->se_sess = target_alloc_session(&tl_tpg->tl_se_tpg, 0, 0,
> +					TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS,
> +					name, tl_nexus, NULL);
>  	if (IS_ERR(tl_nexus->se_sess)) {
> -		ret = PTR_ERR(tl_nexus->se_sess);
> -		goto out;
> -	}
> -	/*
> -	 * Since we are running in 'demo mode' this call with generate a
> -	 * struct se_node_acl for the tcm_loop struct se_portal_group with the SCSI
> -	 * Initiator port name of the passed configfs group 'name'.
> -	 */
> -	tl_nexus->se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
> -				se_tpg, (unsigned char *)name);
> -	if (!tl_nexus->se_sess->se_node_acl) {
> -		transport_free_session(tl_nexus->se_sess);
> -		goto out;
> +		kfree(tl_nexus);
> +		return PTR_ERR(tl_nexus->se_sess);
>  	}
> -	/* Now, register the I_T Nexus as active. */
> -	transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
> -			tl_nexus->se_sess, tl_nexus);
> +
>  	tl_tpg->tl_nexus = tl_nexus;
>  	pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
>  		" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
>  		name);
>  	return 0;
> -
> -out:
> -	kfree(tl_nexus);
> -	return ret;
>  }
>  
>  static int tcm_loop_drop_nexus(
> diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
> index 3072f1a..ddd3398 100644
> --- a/drivers/target/sbp/sbp_target.c
> +++ b/drivers/target/sbp/sbp_target.c
> @@ -196,45 +196,28 @@ static struct sbp_session *sbp_session_create(
>  	struct sbp_session *sess;
>  	int ret;
>  	char guid_str[17];
> -	struct se_node_acl *se_nacl;
> +
> +	snprintf(guid_str, sizeof(guid_str), "%016llx", guid);
>  
>  	sess = kmalloc(sizeof(*sess), GFP_KERNEL);
>  	if (!sess) {
>  		pr_err("failed to allocate session descriptor\n");
>  		return ERR_PTR(-ENOMEM);
>  	}
> +	spin_lock_init(&sess->lock);
> +	INIT_LIST_HEAD(&sess->login_list);
> +	INIT_DELAYED_WORK(&sess->maint_work, session_maintenance_work);
> +	sess->guid = guid;
>  
> -	sess->se_sess = transport_init_session(TARGET_PROT_NORMAL);
> +	sess->se_sess = target_alloc_session(&tpg->se_tpg, 0, 0, TARGET_PROT_NORMAL,
> +					     guid_str, sess, NULL);
>  	if (IS_ERR(sess->se_sess)) {
>  		pr_err("failed to init se_session\n");
> -
>  		ret = PTR_ERR(sess->se_sess);
>  		kfree(sess);
>  		return ERR_PTR(ret);
>  	}
>  
> -	snprintf(guid_str, sizeof(guid_str), "%016llx", guid);
> -
> -	se_nacl = core_tpg_check_initiator_node_acl(&tpg->se_tpg, guid_str);
> -	if (!se_nacl) {
> -		pr_warn("Node ACL not found for %s\n", guid_str);
> -
> -		transport_free_session(sess->se_sess);
> -		kfree(sess);
> -
> -		return ERR_PTR(-EPERM);
> -	}
> -
> -	sess->se_sess->se_node_acl = se_nacl;
> -
> -	spin_lock_init(&sess->lock);
> -	INIT_LIST_HEAD(&sess->login_list);
> -	INIT_DELAYED_WORK(&sess->maint_work, session_maintenance_work);
> -
> -	sess->guid = guid;
> -
> -	transport_register_session(&tpg->se_tpg, se_nacl, sess->se_sess, sess);
> -
>  	return sess;
>  }
>  
> diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
> index bad007b5..2e8b91d 100644
> --- a/drivers/usb/gadget/function/f_tcm.c
> +++ b/drivers/usb/gadget/function/f_tcm.c
> @@ -1581,53 +1581,34 @@ out:
>  
>  static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
>  {
> -	struct se_portal_group *se_tpg;
>  	struct tcm_usbg_nexus *tv_nexus;
> -	int ret;
> +	int ret = 0;
>  
>  	mutex_lock(&tpg->tpg_mutex);
>  	if (tpg->tpg_nexus) {
>  		ret = -EEXIST;
>  		pr_debug("tpg->tpg_nexus already exists\n");
> -		goto err_unlock;
> +		goto out_unlock;
>  	}
> -	se_tpg = &tpg->se_tpg;
>  
> -	ret = -ENOMEM;
>  	tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL);
> -	if (!tv_nexus)
> -		goto err_unlock;
> -	tv_nexus->tvn_se_sess = transport_init_session(TARGET_PROT_NORMAL);
> -	if (IS_ERR(tv_nexus->tvn_se_sess))
> -		goto err_free;
> +	if (!tv_nexus) {
> +		ret = -ENOMEM;
> +		goto out_unlock;
> +	}
>  
> -	/*
> -	 * Since we are running in 'demo mode' this call with generate a
> -	 * struct se_node_acl for the tcm_vhost struct se_portal_group with
> -	 * the SCSI Initiator port name of the passed configfs group 'name'.
> -	 */
> -	tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
> -			se_tpg, name);
> -	if (!tv_nexus->tvn_se_sess->se_node_acl) {
> +	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 0, 0,
> +						     TARGET_PROT_NORMAL, name,
> +						     tv_nexus, NULL);
> +	if (IS_ERR(tv_nexus->tvn_se_sess)) {
>  #define MAKE_NEXUS_MSG "core_tpg_check_initiator_node_acl() failed for %s\n"
>  		pr_debug(MAKE_NEXUS_MSG, name);
>  #undef MAKE_NEXUS_MSG
> -		goto err_session;
> +		kfree(tv_nexus);
> +		ret = PTR_ERR(tv_nexus->tvn_se_sess);
>  	}
> -	/*
> -	 * Now register the TCM vHost virtual I_T Nexus as active.
> -	 */
> -	transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
> -			tv_nexus->tvn_se_sess, tv_nexus);
> -	tpg->tpg_nexus = tv_nexus;
> -	mutex_unlock(&tpg->tpg_mutex);
> -	return 0;
>  
> -err_session:
> -	transport_free_session(tv_nexus->tvn_se_sess);
> -err_free:
> -	kfree(tv_nexus);
> -err_unlock:
> +out_unlock:
>  	mutex_unlock(&tpg->tpg_mutex);
>  	return ret;
>  }
> diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
> index 43bcae8..594f8a7 100644
> --- a/drivers/xen/xen-scsiback.c
> +++ b/drivers/xen/xen-scsiback.c
> @@ -1485,58 +1485,35 @@ static struct configfs_attribute *scsiback_param_attrs[] = {
>  static int scsiback_make_nexus(struct scsiback_tpg *tpg,
>  				const char *name)
>  {
> -	struct se_portal_group *se_tpg;
> -	struct se_session *se_sess;
>  	struct scsiback_nexus *tv_nexus;
> +	int ret = 0;
>  
>  	mutex_lock(&tpg->tv_tpg_mutex);
>  	if (tpg->tpg_nexus) {
> -		mutex_unlock(&tpg->tv_tpg_mutex);
>  		pr_debug("tpg->tpg_nexus already exists\n");
> -		return -EEXIST;
> +		ret = -EEXIST;
> +		goto out_unlock;
>  	}
> -	se_tpg = &tpg->se_tpg;
>  
>  	tv_nexus = kzalloc(sizeof(struct scsiback_nexus), GFP_KERNEL);
>  	if (!tv_nexus) {
> -		mutex_unlock(&tpg->tv_tpg_mutex);
> -		return -ENOMEM;
> +		ret = -ENOMEM;
> +		goto out_unlock;
>  	}
> -	/*
> -	 * Initialize the struct se_session pointer
> -	 */
> -	tv_nexus->tvn_se_sess = transport_init_session(TARGET_PROT_NORMAL);
> +
> +	tv_nexus->tvn_se_sess = target_alloc_session(&tpg->se_tpg, 0, 0,
> +						     TARGET_PROT_NORMAL, name,
> +						     tv_nexus, NULL);
>  	if (IS_ERR(tv_nexus->tvn_se_sess)) {
> -		mutex_unlock(&tpg->tv_tpg_mutex);
>  		kfree(tv_nexus);
> -		return -ENOMEM;
> -	}
> -	se_sess = tv_nexus->tvn_se_sess;
> -	/*
> -	 * Since we are running in 'demo mode' this call with generate a
> -	 * struct se_node_acl for the scsiback struct se_portal_group with
> -	 * the SCSI Initiator port name of the passed configfs group 'name'.
> -	 */
> -	tv_nexus->tvn_se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
> -				se_tpg, (unsigned char *)name);
> -	if (!tv_nexus->tvn_se_sess->se_node_acl) {
> -		mutex_unlock(&tpg->tv_tpg_mutex);
> -		pr_debug("core_tpg_check_initiator_node_acl() failed for %s\n",
> -			 name);
> -		goto out;
> +		ret = -ENOMEM;
> +		goto out_unlock;
>  	}
> -	/* Now register the TCM pvscsi virtual I_T Nexus as active. */
> -	transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
> -			tv_nexus->tvn_se_sess, tv_nexus);
> -	tpg->tpg_nexus = tv_nexus;
>  
> +	tpg->tpg_nexus = tv_nexus;
> +out_unlock:
>  	mutex_unlock(&tpg->tv_tpg_mutex);
> -	return 0;
> -
> -out:
> -	transport_free_session(se_sess);
> -	kfree(tv_nexus);
> -	return -ENOMEM;
> +	return ret;
>  }
>  
>  static int scsiback_drop_nexus(struct scsiback_tpg *tpg)
> 


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH-v2 12/12] xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs
  2016-01-25  8:11 ` [PATCH-v2 12/12] xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
@ 2016-01-26  9:49   ` Juergen Gross
  2016-01-27  6:29     ` Nicholas A. Bellinger
  0 siblings, 1 reply; 22+ messages in thread
From: Juergen Gross @ 2016-01-26  9:49 UTC (permalink / raw)
  To: Nicholas A. Bellinger, target-devel
  Cc: linux-scsi, Christoph Hellwig, Hannes Reinecke, Mike Christie,
	Sagi Grimberg, Andy Grover, Sebastian Andrzej Siewior,
	Andrzej Pietrasiewicz, Chris Boot, Nicholas Bellinger,
	David Vrabel

On 25/01/16 09:11, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
> 
> Cc: Juergen Gross <jgross@suse.com>
> Cc: Hannes Reinecke <hare@suse.de>
> Cc: David Vrabel <david.vrabel@citrix.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> ---
>  drivers/xen/xen-scsiback.c | 53 +++++++++++++++++++++++-----------------------
>  1 file changed, 26 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
> index 640fb22..a10e5f1 100644
> --- a/drivers/xen/xen-scsiback.c
> +++ b/drivers/xen/xen-scsiback.c
> @@ -381,6 +381,12 @@ static void scsiback_cmd_done(struct vscsibk_pend *pending_req)
>  	scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req,
>  				    pending_req->rqid);
>  	scsiback_put(info);
> +	/*
> +	 * Drop the extra KREF_ACK reference taken by target_submit_cmd_map_sgls()
> +	 * ahead of scsiback_check_stop_free() ->  transport_generic_free_cmd()
> +	 * final se_cmd->cmd_kref put.
> +	 */
> +	target_put_sess_cmd(&pending_req->se_cmd);
>  }
>  
>  static void scsiback_cmd_exec(struct vscsibk_pend *pending_req)
> @@ -398,7 +404,7 @@ static void scsiback_cmd_exec(struct vscsibk_pend *pending_req)
>  	rc = target_submit_cmd_map_sgls(se_cmd, sess, pending_req->cmnd,
>  			pending_req->sense_buffer, pending_req->v2p->lun,
>  			pending_req->data_len, 0,
> -			pending_req->sc_data_direction, 0,
> +			pending_req->sc_data_direction, TARGET_SCF_ACK_KREF,
>  			pending_req->sgl, pending_req->n_sg,
>  			NULL, 0, NULL, 0);
>  	if (rc < 0) {
> @@ -587,31 +593,28 @@ static void scsiback_disconnect(struct vscsibk_info *info)
>  static void scsiback_device_action(struct vscsibk_pend *pending_req,
>  	enum tcm_tmreq_table act, int tag)
>  {
> -	int rc, err = FAILED;
>  	struct scsiback_tpg *tpg = pending_req->v2p->tpg;
> +	struct scsiback_nexus *nexus = tpg->tpg_nexus;
>  	struct se_cmd *se_cmd = &pending_req->se_cmd;
>  	struct scsiback_tmr *tmr;
> +	u64 unpacked_lun = pending_req->v2p->lun;
> +	int rc, err = FAILED;
>  
>  	tmr = kzalloc(sizeof(struct scsiback_tmr), GFP_KERNEL);
> -	if (!tmr)
> -		goto out;
> +	if (!tmr) {
> +		target_put_sess_cmd(se_cmd);
> +		goto err;

Sure? I think this should still be "goto out;"?

> +	}
>  
>  	init_waitqueue_head(&tmr->tmr_wait);
>  
> -	transport_init_se_cmd(se_cmd, tpg->se_tpg.se_tpg_tfo,
> -		tpg->tpg_nexus->tvn_se_sess, 0, DMA_NONE, TCM_SIMPLE_TAG,
> -		&pending_req->sense_buffer[0]);
> -
> -	rc = core_tmr_alloc_req(se_cmd, tmr, act, GFP_KERNEL);
> -	if (rc < 0)
> -		goto out;
> -
> -	se_cmd->se_tmr_req->ref_task_tag = tag;
> +	rc = target_submit_tmr(&pending_req->se_cmd, nexus->tvn_se_sess,
> +			       &pending_req->sense_buffer[0],
> +			       unpacked_lun, tmr, act, GFP_KERNEL,
> +			       tag, TARGET_SCF_ACK_KREF);
> +	if (rc)
> +		goto err;

Again.


Juergen

>  
> -	if (transport_lookup_tmr_lun(se_cmd, pending_req->v2p->lun) < 0)
> -		goto out;
> -
> -	transport_generic_handle_tmr(se_cmd);
>  	wait_event(tmr->tmr_wait, atomic_read(&tmr->tmr_complete));
>  
>  	err = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
> @@ -1368,16 +1371,7 @@ static u32 scsiback_tpg_get_inst_index(struct se_portal_group *se_tpg)
>  
>  static int scsiback_check_stop_free(struct se_cmd *se_cmd)
>  {
> -	/*
> -	 * Do not release struct se_cmd's containing a valid TMR pointer.
> -	 * These will be released directly in scsiback_device_action()
> -	 * with transport_generic_free_cmd().
> -	 */
> -	if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
> -		return 0;
> -
> -	transport_generic_free_cmd(se_cmd, 0);
> -	return 1;
> +	return transport_generic_free_cmd(se_cmd, 0);
>  }
>  
>  static void scsiback_release_cmd(struct se_cmd *se_cmd)
> @@ -1385,6 +1379,11 @@ static void scsiback_release_cmd(struct se_cmd *se_cmd)
>  	struct se_session *se_sess = se_cmd->se_sess;
>  	struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
>  
> +	if (se_tmr && se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) {
> +		struct scsiback_tmr *tmr = se_tmr->fabric_tmr_ptr;
> +		kfree(tmr);
> +	}
> +
>  	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
>  }
>  
> 

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation
  2016-01-26  9:45   ` Juergen Gross
@ 2016-01-27  6:28     ` Nicholas A. Bellinger
  2016-01-27 10:57       ` Juergen Gross
  0 siblings, 1 reply; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-27  6:28 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Nicholas A. Bellinger, target-devel, linux-scsi,
	Christoph Hellwig, Hannes Reinecke, Mike Christie, Sagi Grimberg,
	Andy Grover, Sebastian Andrzej Siewior, Andrzej Pietrasiewicz,
	Chris Boot, David Vrabel

On Tue, 2016-01-26 at 10:45 +0100, Juergen Gross wrote:
> On 25/01/16 09:11, Nicholas A. Bellinger wrote:
> > From: Nicholas Bellinger <nab@linux-iscsi.org>
> > 
> > Cc: Juergen Gross <jgross@suse.com>
> > Cc: Hannes Reinecke <hare@suse.de>
> > Cc: David Vrabel <david.vrabel@citrix.com>
> > Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> > ---
> >  drivers/xen/xen-scsiback.c | 163 ++++++++++++++++++++++++---------------------
> >  1 file changed, 87 insertions(+), 76 deletions(-)
> > 
> > diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
> > index 594f8a7..640fb22 100644
> > --- a/drivers/xen/xen-scsiback.c
> > +++ b/drivers/xen/xen-scsiback.c
> > @@ -190,7 +190,6 @@ module_param_named(max_buffer_pages, scsiback_max_buffer_pages, int, 0644);
> >  MODULE_PARM_DESC(max_buffer_pages,
> >  "Maximum number of free pages to keep in backend buffer");
> >  
> > -static struct kmem_cache *scsiback_cachep;
> >  static DEFINE_SPINLOCK(free_pages_lock);
> >  static int free_pages_num;
> >  static LIST_HEAD(scsiback_free_pages);
> > @@ -322,7 +321,8 @@ static void scsiback_free_translation_entry(struct kref *kref)
> >  }
> >  
> >  static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
> > -			uint32_t resid, struct vscsibk_pend *pending_req)
> > +			uint32_t resid, struct vscsibk_pend *pending_req,
> > +			uint16_t rqid)
> >  {
> >  	struct vscsiif_response *ring_res;
> >  	struct vscsibk_info *info = pending_req->info;
> 
> pending_req might be NULL now, so this will panic the system.
> 

Thanks for the review.

Added the following to propagate up original *info into
scsiback_do_resp_with_sense() to address the early pending_req
failure case.

https://git.kernel.org/cgit/linux/kernel/git/nab/target-pending.git/commit/?h=queue-next&id=5873f22a9b7c7aa16ff9a85074a07b739f1d06a5

Will plan to fold into the original for -v3 code.

Thanks Juergen!

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH-v2 12/12] xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs
  2016-01-26  9:49   ` Juergen Gross
@ 2016-01-27  6:29     ` Nicholas A. Bellinger
  0 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-27  6:29 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Nicholas A. Bellinger, target-devel, linux-scsi,
	Christoph Hellwig, Hannes Reinecke, Mike Christie, Sagi Grimberg,
	Andy Grover, Sebastian Andrzej Siewior, Andrzej Pietrasiewicz,
	Chris Boot, David Vrabel

On Tue, 2016-01-26 at 10:49 +0100, Juergen Gross wrote:
> On 25/01/16 09:11, Nicholas A. Bellinger wrote:
> > From: Nicholas Bellinger <nab@linux-iscsi.org>
> > 
> > Cc: Juergen Gross <jgross@suse.com>
> > Cc: Hannes Reinecke <hare@suse.de>
> > Cc: David Vrabel <david.vrabel@citrix.com>
> > Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> > ---
> >  drivers/xen/xen-scsiback.c | 53 +++++++++++++++++++++++-----------------------
> >  1 file changed, 26 insertions(+), 27 deletions(-)
> > 
> > diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
> > index 640fb22..a10e5f1 100644
> > --- a/drivers/xen/xen-scsiback.c
> > +++ b/drivers/xen/xen-scsiback.c
> > @@ -381,6 +381,12 @@ static void scsiback_cmd_done(struct vscsibk_pend *pending_req)
> >  	scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req,
> >  				    pending_req->rqid);
> >  	scsiback_put(info);
> > +	/*
> > +	 * Drop the extra KREF_ACK reference taken by target_submit_cmd_map_sgls()
> > +	 * ahead of scsiback_check_stop_free() ->  transport_generic_free_cmd()
> > +	 * final se_cmd->cmd_kref put.
> > +	 */
> > +	target_put_sess_cmd(&pending_req->se_cmd);
> >  }
> >  
> >  static void scsiback_cmd_exec(struct vscsibk_pend *pending_req)
> > @@ -398,7 +404,7 @@ static void scsiback_cmd_exec(struct vscsibk_pend *pending_req)
> >  	rc = target_submit_cmd_map_sgls(se_cmd, sess, pending_req->cmnd,
> >  			pending_req->sense_buffer, pending_req->v2p->lun,
> >  			pending_req->data_len, 0,
> > -			pending_req->sc_data_direction, 0,
> > +			pending_req->sc_data_direction, TARGET_SCF_ACK_KREF,
> >  			pending_req->sgl, pending_req->n_sg,
> >  			NULL, 0, NULL, 0);
> >  	if (rc < 0) {
> > @@ -587,31 +593,28 @@ static void scsiback_disconnect(struct vscsibk_info *info)
> >  static void scsiback_device_action(struct vscsibk_pend *pending_req,
> >  	enum tcm_tmreq_table act, int tag)
> >  {
> > -	int rc, err = FAILED;
> >  	struct scsiback_tpg *tpg = pending_req->v2p->tpg;
> > +	struct scsiback_nexus *nexus = tpg->tpg_nexus;
> >  	struct se_cmd *se_cmd = &pending_req->se_cmd;
> >  	struct scsiback_tmr *tmr;
> > +	u64 unpacked_lun = pending_req->v2p->lun;
> > +	int rc, err = FAILED;
> >  
> >  	tmr = kzalloc(sizeof(struct scsiback_tmr), GFP_KERNEL);
> > -	if (!tmr)
> > -		goto out;
> > +	if (!tmr) {
> > +		target_put_sess_cmd(se_cmd);
> > +		goto err;
> 
> Sure? I think this should still be "goto out;"?
> 
> > +	}
> >  
> >  	init_waitqueue_head(&tmr->tmr_wait);
> >  
> > -	transport_init_se_cmd(se_cmd, tpg->se_tpg.se_tpg_tfo,
> > -		tpg->tpg_nexus->tvn_se_sess, 0, DMA_NONE, TCM_SIMPLE_TAG,
> > -		&pending_req->sense_buffer[0]);
> > -
> > -	rc = core_tmr_alloc_req(se_cmd, tmr, act, GFP_KERNEL);
> > -	if (rc < 0)
> > -		goto out;
> > -
> > -	se_cmd->se_tmr_req->ref_task_tag = tag;
> > +	rc = target_submit_tmr(&pending_req->se_cmd, nexus->tvn_se_sess,
> > +			       &pending_req->sense_buffer[0],
> > +			       unpacked_lun, tmr, act, GFP_KERNEL,
> > +			       tag, TARGET_SCF_ACK_KREF);
> > +	if (rc)
> > +		goto err;
> 
> Again.
> 

Whoops, bisect breakage here..

Fixed up this in latest target-pending/queue-next.


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation
  2016-01-27  6:28     ` Nicholas A. Bellinger
@ 2016-01-27 10:57       ` Juergen Gross
  2016-01-28  5:13         ` Nicholas A. Bellinger
  0 siblings, 1 reply; 22+ messages in thread
From: Juergen Gross @ 2016-01-27 10:57 UTC (permalink / raw)
  To: Nicholas A. Bellinger
  Cc: Nicholas A. Bellinger, target-devel, linux-scsi,
	Christoph Hellwig, Hannes Reinecke, Mike Christie, Sagi Grimberg,
	Andy Grover, Sebastian Andrzej Siewior, Andrzej Pietrasiewicz,
	Chris Boot, David Vrabel

On 27/01/16 07:28, Nicholas A. Bellinger wrote:
> On Tue, 2016-01-26 at 10:45 +0100, Juergen Gross wrote:
>> On 25/01/16 09:11, Nicholas A. Bellinger wrote:
>>> From: Nicholas Bellinger <nab@linux-iscsi.org>
>>>
>>> Cc: Juergen Gross <jgross@suse.com>
>>> Cc: Hannes Reinecke <hare@suse.de>
>>> Cc: David Vrabel <david.vrabel@citrix.com>
>>> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
>>> ---
>>>  drivers/xen/xen-scsiback.c | 163 ++++++++++++++++++++++++---------------------
>>>  1 file changed, 87 insertions(+), 76 deletions(-)
>>>
>>> diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
>>> index 594f8a7..640fb22 100644
>>> --- a/drivers/xen/xen-scsiback.c
>>> +++ b/drivers/xen/xen-scsiback.c
>>> @@ -190,7 +190,6 @@ module_param_named(max_buffer_pages, scsiback_max_buffer_pages, int, 0644);
>>>  MODULE_PARM_DESC(max_buffer_pages,
>>>  "Maximum number of free pages to keep in backend buffer");
>>>  
>>> -static struct kmem_cache *scsiback_cachep;
>>>  static DEFINE_SPINLOCK(free_pages_lock);
>>>  static int free_pages_num;
>>>  static LIST_HEAD(scsiback_free_pages);
>>> @@ -322,7 +321,8 @@ static void scsiback_free_translation_entry(struct kref *kref)
>>>  }
>>>  
>>>  static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
>>> -			uint32_t resid, struct vscsibk_pend *pending_req)
>>> +			uint32_t resid, struct vscsibk_pend *pending_req,
>>> +			uint16_t rqid)
>>>  {
>>>  	struct vscsiif_response *ring_res;
>>>  	struct vscsibk_info *info = pending_req->info;
>>
>> pending_req might be NULL now, so this will panic the system.
>>
> 
> Thanks for the review.
> 
> Added the following to propagate up original *info into
> scsiback_do_resp_with_sense() to address the early pending_req
> failure case.
> 
> https://git.kernel.org/cgit/linux/kernel/git/nab/target-pending.git/commit/?h=queue-next&id=5873f22a9b7c7aa16ff9a85074a07b739f1d06a5

Hmm, wouldn't it make more sense to split scsiback_do_resp_with_sense()
into two functions now? Something like:


diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index ad4eb10..0d71467 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -321,11 +321,10 @@ static void scsiback_free_translation_entry(struct
kref *kref)
        kfree(entry);
 }

-static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
-                       uint32_t resid, struct vscsibk_pend *pending_req)
+static void scsiback_send_response(struct vscsibk_info *info,
+       char *sense_buffer, int32_t result, uint32_t resid, uint16_t rqid)
 {
        struct vscsiif_response *ring_res;
-       struct vscsibk_info *info = pending_req->info;
        int notify;
        struct scsi_sense_hdr sshdr;
        unsigned long flags;
@@ -337,7 +336,7 @@ static void scsiback_do_resp_with_sense(char
*sense_buffer, int32_t result,
        info->ring.rsp_prod_pvt++;

        ring_res->rslt   = result;
-       ring_res->rqid   = pending_req->rqid;
+       ring_res->rqid   = rqid;

        if (sense_buffer != NULL &&
            scsi_normalize_sense(sense_buffer, VSCSIIF_SENSE_BUFFERSIZE,
@@ -357,6 +356,13 @@ static void scsiback_do_resp_with_sense(char
*sense_buffer, int32_t result,

        if (notify)
                notify_remote_via_irq(info->irq);
+}
+
+static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
+                       uint32_t resid, struct vscsibk_pend *pending_req)
+{
+       scsiback_send_response(pending_req->info, sense_buffer, result,
+                              resid, pending_req->rqid);

        if (pending_req->v2p)
                kref_put(&pending_req->v2p->kref,


And then call scsiback_send_response() directly in case pending_req
is NULL.


Juergen

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation
  2016-01-27 10:57       ` Juergen Gross
@ 2016-01-28  5:13         ` Nicholas A. Bellinger
  0 siblings, 0 replies; 22+ messages in thread
From: Nicholas A. Bellinger @ 2016-01-28  5:13 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Nicholas A. Bellinger, target-devel, linux-scsi,
	Christoph Hellwig, Hannes Reinecke, Mike Christie, Sagi Grimberg,
	Andy Grover, Sebastian Andrzej Siewior, Andrzej Pietrasiewicz,
	Chris Boot, David Vrabel

On Wed, 2016-01-27 at 11:57 +0100, Juergen Gross wrote:
> On 27/01/16 07:28, Nicholas A. Bellinger wrote:
> > On Tue, 2016-01-26 at 10:45 +0100, Juergen Gross wrote:
> >> On 25/01/16 09:11, Nicholas A. Bellinger wrote:
> >>> From: Nicholas Bellinger <nab@linux-iscsi.org>
> >>>
> >>> Cc: Juergen Gross <jgross@suse.com>
> >>> Cc: Hannes Reinecke <hare@suse.de>
> >>> Cc: David Vrabel <david.vrabel@citrix.com>
> >>> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> >>> ---
> >>>  drivers/xen/xen-scsiback.c | 163 ++++++++++++++++++++++++---------------------
> >>>  1 file changed, 87 insertions(+), 76 deletions(-)
> >>>
> >>> diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
> >>> index 594f8a7..640fb22 100644
> >>> --- a/drivers/xen/xen-scsiback.c
> >>> +++ b/drivers/xen/xen-scsiback.c
> >>> @@ -190,7 +190,6 @@ module_param_named(max_buffer_pages, scsiback_max_buffer_pages, int, 0644);
> >>>  MODULE_PARM_DESC(max_buffer_pages,
> >>>  "Maximum number of free pages to keep in backend buffer");
> >>>  
> >>> -static struct kmem_cache *scsiback_cachep;
> >>>  static DEFINE_SPINLOCK(free_pages_lock);
> >>>  static int free_pages_num;
> >>>  static LIST_HEAD(scsiback_free_pages);
> >>> @@ -322,7 +321,8 @@ static void scsiback_free_translation_entry(struct kref *kref)
> >>>  }
> >>>  
> >>>  static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
> >>> -			uint32_t resid, struct vscsibk_pend *pending_req)
> >>> +			uint32_t resid, struct vscsibk_pend *pending_req,
> >>> +			uint16_t rqid)
> >>>  {
> >>>  	struct vscsiif_response *ring_res;
> >>>  	struct vscsibk_info *info = pending_req->info;
> >>
> >> pending_req might be NULL now, so this will panic the system.
> >>
> > 
> > Thanks for the review.
> > 
> > Added the following to propagate up original *info into
> > scsiback_do_resp_with_sense() to address the early pending_req
> > failure case.
> > 
> > https://git.kernel.org/cgit/linux/kernel/git/nab/target-pending.git/commit/?h=queue-next&id=5873f22a9b7c7aa16ff9a85074a07b739f1d06a5
> 
> Hmm, wouldn't it make more sense to split scsiback_do_resp_with_sense()
> into two functions now? Something like:
> 

<SNIP>

> And then call scsiback_send_response() directly in case pending_req
> is NULL.
> 

That makes alot more sense.

Just updated the series in queue-next, and folded your change into the
original patch.

Thanks Juergen.


^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2016-01-28  5:13 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-01-25  8:10 [PATCH-v2 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion Nicholas A. Bellinger
2016-01-25  8:10 ` [PATCH-v2 01/12] target: Add target_alloc_session() helper function Nicholas A. Bellinger
2016-01-25  8:10 ` [PATCH-v2 02/12] target: Convert demo-mode only drivers to target_alloc_session Nicholas A. Bellinger
2016-01-26  9:45   ` Juergen Gross
2016-01-25  8:10 ` [PATCH-v2 03/12] vhost/scsi: Convert to target_alloc_session usage Nicholas A. Bellinger
2016-01-25  8:10 ` [PATCH-v2 04/12] tcm_qla2xxx: " Nicholas A. Bellinger
2016-01-25  8:10 ` [PATCH-v2 05/12] tcm_fc: " Nicholas A. Bellinger
2016-01-25  8:11 ` [PATCH-v2 06/12] ib_srpt: " Nicholas A. Bellinger
2016-01-25  8:11 ` [PATCH-v2 07/12] sbp-target: Conversion to percpu_ida tag pre-allocation Nicholas A. Bellinger
2016-01-25  8:11 ` [PATCH-v2 08/12] sbp-target: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
2016-01-25  8:11 ` [PATCH-v2 09/12] usb-gadget/tcm: Conversion to percpu_ida tag pre-allocation Nicholas A. Bellinger
2016-01-25  8:11 ` [PATCH-v2 10/12] usb-gadget/tcm: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
2016-01-25  8:11 ` [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation Nicholas A. Bellinger
2016-01-25 15:42   ` Juergen Gross
2016-01-26  5:15     ` Nicholas A. Bellinger
2016-01-26  9:45   ` Juergen Gross
2016-01-27  6:28     ` Nicholas A. Bellinger
2016-01-27 10:57       ` Juergen Gross
2016-01-28  5:13         ` Nicholas A. Bellinger
2016-01-25  8:11 ` [PATCH-v2 12/12] xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs Nicholas A. Bellinger
2016-01-26  9:49   ` Juergen Gross
2016-01-27  6:29     ` Nicholas A. Bellinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).