Re: [PATCH] target: simplify the target template registration API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Apr 07, 2015 at 11:12:50PM -0700, Nicholas A. Bellinger wrote:
> So I was going to just merge this because having a single register
> template function for fabric drivers does make alot of sense, but it
> currently conflicts with the T10-PI fabric bits in for-next.  Sigh..
> 
> Looking further, I really don't like how the target_fabric_copy_attrs()
> stuff works in target_register_template().  Just punting to direct use
> struct configfs_attributes pointers in target_core_fabric_ops is a hack.
> 
> I'd much rather see target_fabric_setup_cits() do this proper setup,
> instead of unnecessarily duplicating the target_core_fabric_configfs.c
> list of defined config_item_types in two new locations.

Does this version look better?  It adds a new TF_CIT_SETUP_DRV macro,
so that the core configfs code can declare attributes as either core
only or for drivers.  That way we also avoid the case where the core
code defines an attribute and a fabric driver accidentally overrides it.

It's also been rebased to latest target/for-next.

---
>From 548ddc8084f98afaf6fbb82c8e276a268905d75f Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@xxxxxx>
Date: Tue, 17 Feb 2015 17:22:25 +0100
Subject: target: simplify the target template registration API

Instead of calling target_fabric_configfs_init() +
target_fabric_configfs_register() / target_fabric_configfs_deregister()
target_fabric_configfs_free() from every target driver, rewrite the API
so that we have simple register/unregister functions that operate on
a const operations vector.

This patch also fixes a memory leak in several target drivers. Several
target drivers namely called target_fabric_configfs_deregister()
without calling target_fabric_configfs_free().

A large part of this patch is based on earlier changes from
Bart Van Assche <bart.vanassche@xxxxxxxxxxx>.

Signed-off-by: Christoph Hellwig <hch@xxxxxx>
---
 Documentation/target/tcm_mod_builder.py      |  79 ++----------
 drivers/infiniband/ulp/srpt/ib_srpt.c        |  49 ++------
 drivers/scsi/qla2xxx/qla_target.c            |   2 +-
 drivers/scsi/qla2xxx/tcm_qla2xxx.c           | 118 ++++--------------
 drivers/target/iscsi/iscsi_target.c          |  23 ++--
 drivers/target/iscsi/iscsi_target.h          |   2 +-
 drivers/target/iscsi/iscsi_target_configfs.c | 180 +++++++++------------------
 drivers/target/iscsi/iscsi_target_configfs.h |   7 --
 drivers/target/iscsi/iscsi_target_tpg.c      |   6 +-
 drivers/target/loopback/tcm_loop.c           | 178 ++++++++------------------
 drivers/target/sbp/sbp_target.c              |  68 ++--------
 drivers/target/target_core_configfs.c        | 176 +++++++-------------------
 drivers/target/target_core_fabric_configfs.c |  38 ++++--
 drivers/target/target_core_pr.c              |  16 +--
 drivers/target/target_core_tpg.c             |   2 +-
 drivers/target/target_core_transport.c       |   6 +-
 drivers/target/target_core_xcopy.c           |   2 +-
 drivers/target/tcm_fc/tcm_fc.h               |   1 -
 drivers/target/tcm_fc/tfc_conf.c             |  89 ++++---------
 drivers/usb/gadget/legacy/tcm_usb_gadget.c   |  57 ++-------
 drivers/vhost/scsi.c                         |  76 ++---------
 drivers/xen/xen-scsiback.c                   |  74 ++---------
 include/target/target_core_base.h            |   4 +-
 include/target/target_core_configfs.h        |   6 -
 include/target/target_core_fabric.h          |  24 +++-
 25 files changed, 356 insertions(+), 927 deletions(-)
 delete mode 100644 drivers/target/iscsi/iscsi_target_configfs.h

diff --git a/Documentation/target/tcm_mod_builder.py b/Documentation/target/tcm_mod_builder.py
index 2b47704..27afc03 100755
--- a/Documentation/target/tcm_mod_builder.py
+++ b/Documentation/target/tcm_mod_builder.py
@@ -237,8 +237,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
 	buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
 
-	buf += "/* Local pointer to allocated TCM configfs fabric module */\n"
-	buf += "struct target_fabric_configfs *" + fabric_mod_name + "_fabric_configfs;\n\n"
+	buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops;\n\n"
 
 	buf += "static struct se_node_acl *" + fabric_mod_name + "_make_nodeacl(\n"
 	buf += "	struct se_portal_group *se_tpg,\n"
@@ -309,8 +308,8 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "	}\n"
 	buf += "	tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
 	buf += "	tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
-	buf += "	ret = core_tpg_register(&" + fabric_mod_name + "_fabric_configfs->tf_ops, wwn,\n"
-	buf += "				&tpg->se_tpg, (void *)tpg,\n"
+	buf += "	ret = core_tpg_register(&" + fabric_mod_name + "_ops, wwn,\n"
+	buf += "				&tpg->se_tpg, tpg,\n"
 	buf += "				TRANSPORT_TPG_TYPE_NORMAL);\n"
 	buf += "	if (ret < 0) {\n"
 	buf += "		kfree(tpg);\n"
@@ -370,7 +369,10 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "	NULL,\n"
 	buf += "};\n\n"
 
-	buf += "static struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
+	buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
+	buf += "	.module				= THIS_MODULE\n",
+	buf += "	.name				= " + fabric_mod_name + ",\n"
+	buf += "	.get_fabric_proto_ident		= " + fabric_mod_name + "_get_fabric_proto_ident,\n"
 	buf += "	.get_fabric_name		= " + fabric_mod_name + "_get_fabric_name,\n"
 	buf += "	.get_fabric_proto_ident		= " + fabric_mod_name + "_get_fabric_proto_ident,\n"
 	buf += "	.tpg_get_wwn			= " + fabric_mod_name + "_get_fabric_wwn,\n"
@@ -413,75 +415,18 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "	.fabric_drop_np			= NULL,\n"
 	buf += "	.fabric_make_nodeacl		= " + fabric_mod_name + "_make_nodeacl,\n"
 	buf += "	.fabric_drop_nodeacl		= " + fabric_mod_name + "_drop_nodeacl,\n"
-	buf += "};\n\n"
-
-	buf += "static int " + fabric_mod_name + "_register_configfs(void)\n"
-	buf += "{\n"
-	buf += "	struct target_fabric_configfs *fabric;\n"
-	buf += "	int ret;\n\n"
-	buf += "	printk(KERN_INFO \"" + fabric_mod_name.upper() + " fabric module %s on %s/%s\"\n"
-	buf += "		\" on \"UTS_RELEASE\"\\n\"," + fabric_mod_name.upper() + "_VERSION, utsname()->sysname,\n"
-	buf += "		utsname()->machine);\n"
-	buf += "	/*\n"
-	buf += "	 * Register the top level struct config_item_type with TCM core\n"
-	buf += "	 */\n"
-	buf += "	fabric = target_fabric_configfs_init(THIS_MODULE, \"" + fabric_mod_name + "\");\n"
-	buf += "	if (IS_ERR(fabric)) {\n"
-	buf += "		printk(KERN_ERR \"target_fabric_configfs_init() failed\\n\");\n"
-	buf += "		return PTR_ERR(fabric);\n"
-	buf += "	}\n"
-	buf += "	/*\n"
-	buf += "	 * Setup fabric->tf_ops from our local " + fabric_mod_name + "_ops\n"
-	buf += "	 */\n"
-	buf += "	fabric->tf_ops = " + fabric_mod_name + "_ops;\n"
-	buf += "	/*\n"
-	buf += "	 * Setup default attribute lists for various fabric->tf_cit_tmpl\n"
-	buf += "	 */\n"
-	buf += "	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = " + fabric_mod_name + "_wwn_attrs;\n"
-	buf += "	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = NULL;\n"
-	buf += "	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;\n"
-	buf += "	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;\n"
-	buf += "	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;\n"
-	buf += "	fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;\n"
-	buf += "	fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;\n"
-	buf += "	fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;\n"
-	buf += "	fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;\n"
-	buf += "	/*\n"
-	buf += "	 * Register the fabric for use within TCM\n"
-	buf += "	 */\n"
-	buf += "	ret = target_fabric_configfs_register(fabric);\n"
-	buf += "	if (ret < 0) {\n"
-	buf += "		printk(KERN_ERR \"target_fabric_configfs_register() failed\"\n"
-	buf += "				\" for " + fabric_mod_name.upper() + "\\n\");\n"
-	buf += "		return ret;\n"
-	buf += "	}\n"
-	buf += "	/*\n"
-	buf += "	 * Setup our local pointer to *fabric\n"
-	buf += "	 */\n"
-	buf += "	" + fabric_mod_name + "_fabric_configfs = fabric;\n"
-	buf += "	printk(KERN_INFO \"" +  fabric_mod_name.upper() + "[0] - Set fabric -> " + fabric_mod_name + "_fabric_configfs\\n\");\n"
-	buf += "	return 0;\n"
-	buf += "};\n\n"
-	buf += "static void __exit " + fabric_mod_name + "_deregister_configfs(void)\n"
-	buf += "{\n"
-	buf += "	if (!" + fabric_mod_name + "_fabric_configfs)\n"
-	buf += "		return;\n\n"
-	buf += "	target_fabric_configfs_deregister(" + fabric_mod_name + "_fabric_configfs);\n"
-	buf += "	" + fabric_mod_name + "_fabric_configfs = NULL;\n"
-	buf += "	printk(KERN_INFO \"" +  fabric_mod_name.upper() + "[0] - Cleared " + fabric_mod_name + "_fabric_configfs\\n\");\n"
+	buf += "\n"
+	buf += "	.tfc_wwn_attrs			= " + fabric_mod_name + "_wwn_attrs;\n"
 	buf += "};\n\n"
 
 	buf += "static int __init " + fabric_mod_name + "_init(void)\n"
 	buf += "{\n"
-	buf += "	int ret;\n\n"
-	buf += "	ret = " + fabric_mod_name + "_register_configfs();\n"
-	buf += "	if (ret < 0)\n"
-	buf += "		return ret;\n\n"
-	buf += "	return 0;\n"
+	buf += "	return target_register_template(" + fabric_mod_name + "_ops);\n"
 	buf += "};\n\n"
+
 	buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
 	buf += "{\n"
-	buf += "	" + fabric_mod_name + "_deregister_configfs();\n"
+	buf += "	target_unregister_template(" + fabric_mod_name + "_ops);\n"
 	buf += "};\n\n"
 
 	buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 6e0a477..0701538 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -93,7 +93,7 @@ MODULE_PARM_DESC(srpt_service_guid,
 		 " instead of using the node_guid of the first HCA.");
 
 static struct ib_client srpt_client;
-static struct target_fabric_configfs *srpt_target;
+static const struct target_core_fabric_ops srpt_template;
 static void srpt_release_channel(struct srpt_rdma_ch *ch);
 static int srpt_queue_status(struct se_cmd *cmd);
 
@@ -3851,7 +3851,7 @@ static struct se_portal_group *srpt_make_tpg(struct se_wwn *wwn,
 	int res;
 
 	/* Initialize sport->port_wwn and sport->port_tpg_1 */
-	res = core_tpg_register(&srpt_target->tf_ops, &sport->port_wwn,
+	res = core_tpg_register(&srpt_template, &sport->port_wwn,
 			&sport->port_tpg_1, sport, TRANSPORT_TPG_TYPE_NORMAL);
 	if (res)
 		return ERR_PTR(res);
@@ -3919,7 +3919,9 @@ static struct configfs_attribute *srpt_wwn_attrs[] = {
 	NULL,
 };
 
-static struct target_core_fabric_ops srpt_template = {
+static const struct target_core_fabric_ops srpt_template = {
+	.module				= THIS_MODULE,
+	.name				= "srpt",
 	.get_fabric_name		= srpt_get_fabric_name,
 	.get_fabric_proto_ident		= srpt_get_fabric_proto_ident,
 	.tpg_get_wwn			= srpt_get_fabric_wwn,
@@ -3964,6 +3966,10 @@ static struct target_core_fabric_ops srpt_template = {
 	.fabric_drop_np			= NULL,
 	.fabric_make_nodeacl		= srpt_make_nodeacl,
 	.fabric_drop_nodeacl		= srpt_drop_nodeacl,
+
+	.tfc_wwn_attrs			= srpt_wwn_attrs,
+	.tfc_tpg_base_attrs		= srpt_tpg_attrs,
+	.tfc_tpg_attrib_attrs		= srpt_tpg_attrib_attrs,
 };
 
 /**
@@ -3994,33 +4000,9 @@ static int __init srpt_init_module(void)
 		goto out;
 	}
 
-	srpt_target = target_fabric_configfs_init(THIS_MODULE, "srpt");
-	if (IS_ERR(srpt_target)) {
-		printk(KERN_ERR "couldn't register\n");
-		ret = PTR_ERR(srpt_target);
+	ret = target_register_template(&srpt_template);
+	if (ret)
 		goto out;
-	}
-
-	srpt_target->tf_ops = srpt_template;
-
-	/*
-	 * Set up default attribute lists.
-	 */
-	srpt_target->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = srpt_wwn_attrs;
-	srpt_target->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = srpt_tpg_attrs;
-	srpt_target->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = srpt_tpg_attrib_attrs;
-	srpt_target->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-	srpt_target->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-	srpt_target->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-	srpt_target->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-	srpt_target->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-	srpt_target->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-
-	ret = target_fabric_configfs_register(srpt_target);
-	if (ret < 0) {
-		printk(KERN_ERR "couldn't register\n");
-		goto out_free_target;
-	}
 
 	ret = ib_register_client(&srpt_client);
 	if (ret) {
@@ -4031,11 +4013,7 @@ static int __init srpt_init_module(void)
 	return 0;
 
 out_unregister_target:
-	target_fabric_configfs_deregister(srpt_target);
-	srpt_target = NULL;
-out_free_target:
-	if (srpt_target)
-		target_fabric_configfs_free(srpt_target);
+	target_unregister_template(&srpt_template);
 out:
 	return ret;
 }
@@ -4043,8 +4021,7 @@ out:
 static void __exit srpt_cleanup_module(void)
 {
 	ib_unregister_client(&srpt_client);
-	target_fabric_configfs_deregister(srpt_target);
-	srpt_target = NULL;
+	target_unregister_template(&srpt_template);
 }
 
 module_init(srpt_init_module);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 5741825..fe8a8d1 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -3065,7 +3065,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
 {
 	struct qla_hw_data *ha = vha->hw;
 	struct se_cmd *se_cmd;
-	struct target_core_fabric_ops *tfo;
+	const struct target_core_fabric_ops *tfo;
 	struct qla_tgt_cmd *cmd;
 
 	if (handle & CTIO_INTERMEDIATE_HANDLE_MARK) {
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 843b53b..1bd3653 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -53,9 +53,8 @@
 static struct workqueue_struct *tcm_qla2xxx_free_wq;
 static struct workqueue_struct *tcm_qla2xxx_cmd_wq;
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *tcm_qla2xxx_fabric_configfs;
-static struct target_fabric_configfs *tcm_qla2xxx_npiv_fabric_configfs;
+static const struct target_core_fabric_ops tcm_qla2xxx_ops;
+static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops;
 
 /*
  * Parse WWN.
@@ -1177,7 +1176,7 @@ static struct se_portal_group *tcm_qla2xxx_make_tpg(
 	tpg->tpg_attrib.cache_dynamic_acls = 1;
 	tpg->tpg_attrib.demo_mode_login_only = 1;
 
-	ret = core_tpg_register(&tcm_qla2xxx_fabric_configfs->tf_ops, wwn,
+	ret = core_tpg_register(&tcm_qla2xxx_ops, wwn,
 				&tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0) {
 		kfree(tpg);
@@ -1297,7 +1296,7 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg(
 	tpg->tpg_attrib.cache_dynamic_acls = 1;
 	tpg->tpg_attrib.demo_mode_login_only = 1;
 
-	ret = core_tpg_register(&tcm_qla2xxx_npiv_fabric_configfs->tf_ops, wwn,
+	ret = core_tpg_register(&tcm_qla2xxx_npiv_ops, wwn,
 				&tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0) {
 		kfree(tpg);
@@ -1987,7 +1986,9 @@ static struct configfs_attribute *tcm_qla2xxx_wwn_attrs[] = {
 	NULL,
 };
 
-static struct target_core_fabric_ops tcm_qla2xxx_ops = {
+static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
+	.module				= THIS_MODULE,
+	.name				= "qla2xxx",
 	.get_fabric_name		= tcm_qla2xxx_get_fabric_name,
 	.get_fabric_proto_ident		= tcm_qla2xxx_get_fabric_proto_ident,
 	.tpg_get_wwn			= tcm_qla2xxx_get_fabric_wwn,
@@ -2037,9 +2038,15 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = {
 	.fabric_drop_np			= NULL,
 	.fabric_make_nodeacl		= tcm_qla2xxx_make_nodeacl,
 	.fabric_drop_nodeacl		= tcm_qla2xxx_drop_nodeacl,
+
+	.tfc_wwn_attrs			= tcm_qla2xxx_wwn_attrs,
+	.tfc_tpg_base_attrs		= tcm_qla2xxx_tpg_attrs,
+	.tfc_tpg_attrib_attrs		= tcm_qla2xxx_tpg_attrib_attrs,
 };
 
-static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
+static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
+	.module				= THIS_MODULE,
+	.name				= "qla2xxx",
 	.get_fabric_name		= tcm_qla2xxx_npiv_get_fabric_name,
 	.get_fabric_proto_ident		= tcm_qla2xxx_get_fabric_proto_ident,
 	.tpg_get_wwn			= tcm_qla2xxx_get_fabric_wwn,
@@ -2087,94 +2094,26 @@ static struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
 	.fabric_drop_np			= NULL,
 	.fabric_make_nodeacl		= tcm_qla2xxx_make_nodeacl,
 	.fabric_drop_nodeacl		= tcm_qla2xxx_drop_nodeacl,
+
+	.tfc_wwn_attrs			= tcm_qla2xxx_wwn_attrs,
+	.tfc_tpg_base_attrs		= tcm_qla2xxx_npiv_tpg_attrs,
 };
 
 static int tcm_qla2xxx_register_configfs(void)
 {
-	struct target_fabric_configfs *fabric, *npiv_fabric;
 	int ret;
 
 	pr_debug("TCM QLOGIC QLA2XXX fabric module %s on %s/%s on "
 	    UTS_RELEASE"\n", TCM_QLA2XXX_VERSION, utsname()->sysname,
 	    utsname()->machine);
-	/*
-	 * Register the top level struct config_item_type with TCM core
-	 */
-	fabric = target_fabric_configfs_init(THIS_MODULE, "qla2xxx");
-	if (IS_ERR(fabric)) {
-		pr_err("target_fabric_configfs_init() failed\n");
-		return PTR_ERR(fabric);
-	}
-	/*
-	 * Setup fabric->tf_ops from our local tcm_qla2xxx_ops
-	 */
-	fabric->tf_ops = tcm_qla2xxx_ops;
-	/*
-	 * Setup default attribute lists for various fabric->tf_cit_tmpl
-	 */
-	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = tcm_qla2xxx_tpg_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs =
-						tcm_qla2xxx_tpg_attrib_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-	/*
-	 * Register the fabric for use within TCM
-	 */
-	ret = target_fabric_configfs_register(fabric);
-	if (ret < 0) {
-		pr_err("target_fabric_configfs_register() failed for TCM_QLA2XXX\n");
+
+	ret = target_register_template(&tcm_qla2xxx_ops);
+	if (ret)
 		return ret;
-	}
-	/*
-	 * Setup our local pointer to *fabric
-	 */
-	tcm_qla2xxx_fabric_configfs = fabric;
-	pr_debug("TCM_QLA2XXX[0] - Set fabric -> tcm_qla2xxx_fabric_configfs\n");
 
-	/*
-	 * Register the top level struct config_item_type for NPIV with TCM core
-	 */
-	npiv_fabric = target_fabric_configfs_init(THIS_MODULE, "qla2xxx_npiv");
-	if (IS_ERR(npiv_fabric)) {
-		pr_err("target_fabric_configfs_init() failed\n");
-		ret = PTR_ERR(npiv_fabric);
+	ret = target_register_template(&tcm_qla2xxx_npiv_ops);
+	if (ret)
 		goto out_fabric;
-	}
-	/*
-	 * Setup fabric->tf_ops from our local tcm_qla2xxx_npiv_ops
-	 */
-	npiv_fabric->tf_ops = tcm_qla2xxx_npiv_ops;
-	/*
-	 * Setup default attribute lists for various npiv_fabric->tf_cit_tmpl
-	 */
-	npiv_fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_qla2xxx_wwn_attrs;
-	npiv_fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs =
-	    tcm_qla2xxx_npiv_tpg_attrs;
-	npiv_fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-	npiv_fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-	npiv_fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-	npiv_fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-	npiv_fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-	npiv_fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-	npiv_fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-	/*
-	 * Register the npiv_fabric for use within TCM
-	 */
-	ret = target_fabric_configfs_register(npiv_fabric);
-	if (ret < 0) {
-		pr_err("target_fabric_configfs_register() failed for TCM_QLA2XXX\n");
-		goto out_fabric;
-	}
-	/*
-	 * Setup our local pointer to *npiv_fabric
-	 */
-	tcm_qla2xxx_npiv_fabric_configfs = npiv_fabric;
-	pr_debug("TCM_QLA2XXX[0] - Set fabric -> tcm_qla2xxx_npiv_fabric_configfs\n");
 
 	tcm_qla2xxx_free_wq = alloc_workqueue("tcm_qla2xxx_free",
 						WQ_MEM_RECLAIM, 0);
@@ -2194,9 +2133,9 @@ static int tcm_qla2xxx_register_configfs(void)
 out_free_wq:
 	destroy_workqueue(tcm_qla2xxx_free_wq);
 out_fabric_npiv:
-	target_fabric_configfs_deregister(tcm_qla2xxx_npiv_fabric_configfs);
+	target_unregister_template(&tcm_qla2xxx_npiv_ops);
 out_fabric:
-	target_fabric_configfs_deregister(tcm_qla2xxx_fabric_configfs);
+	target_unregister_template(&tcm_qla2xxx_ops);
 	return ret;
 }
 
@@ -2205,13 +2144,8 @@ static void tcm_qla2xxx_deregister_configfs(void)
 	destroy_workqueue(tcm_qla2xxx_cmd_wq);
 	destroy_workqueue(tcm_qla2xxx_free_wq);
 
-	target_fabric_configfs_deregister(tcm_qla2xxx_fabric_configfs);
-	tcm_qla2xxx_fabric_configfs = NULL;
-	pr_debug("TCM_QLA2XXX[0] - Cleared tcm_qla2xxx_fabric_configfs\n");
-
-	target_fabric_configfs_deregister(tcm_qla2xxx_npiv_fabric_configfs);
-	tcm_qla2xxx_npiv_fabric_configfs = NULL;
-	pr_debug("TCM_QLA2XXX[0] - Cleared tcm_qla2xxx_npiv_fabric_configfs\n");
+	target_unregister_template(&tcm_qla2xxx_ops);
+	target_unregister_template(&tcm_qla2xxx_npiv_ops);
 }
 
 static int __init tcm_qla2xxx_init(void)
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index cd611e7..5d75bb4 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -33,7 +33,6 @@
 #include <target/iscsi/iscsi_target_core.h>
 #include "iscsi_target_parameters.h"
 #include "iscsi_target_seq_pdu_list.h"
-#include "iscsi_target_configfs.h"
 #include "iscsi_target_datain_values.h"
 #include "iscsi_target_erl0.h"
 #include "iscsi_target_erl1.h"
@@ -551,8 +550,8 @@ static int __init iscsi_target_init_module(void)
 	idr_init(&tiqn_idr);
 	idr_init(&sess_idr);
 
-	ret = iscsi_target_register_configfs();
-	if (ret < 0)
+	ret = target_register_template(&iscsi_ops);
+	if (ret)
 		goto out;
 
 	size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long);
@@ -616,7 +615,10 @@ qr_out:
 bitmap_out:
 	vfree(iscsit_global->ts_bitmap);
 configfs_out:
-	iscsi_target_deregister_configfs();
+	/* XXX: this probably wants it to be it's own unwind step.. */
+	if (iscsit_global->discovery_tpg)
+		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
+	target_unregister_template(&iscsi_ops);
 out:
 	kfree(iscsit_global);
 	return -ENOMEM;
@@ -631,7 +633,13 @@ static void __exit iscsi_target_cleanup_module(void)
 	kmem_cache_destroy(lio_ooo_cache);
 	kmem_cache_destroy(lio_r2t_cache);
 
-	iscsi_target_deregister_configfs();
+	/*
+	 * Shutdown discovery sessions and disable discovery TPG
+	 */
+	if (iscsit_global->discovery_tpg)
+		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
+
+	target_unregister_template(&iscsi_ops);
 
 	vfree(iscsit_global->ts_bitmap);
 	kfree(iscsit_global);
@@ -983,7 +991,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 	/*
 	 * Initialize struct se_cmd descriptor from target_core_mod infrastructure
 	 */
-	transport_init_se_cmd(&cmd->se_cmd, &lio_target_fabric_configfs->tf_ops,
+	transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
 			conn->sess->se_sess, be32_to_cpu(hdr->data_length),
 			cmd->data_direction, sam_task_attr,
 			cmd->sense_buffer + 2);
@@ -1798,8 +1806,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 		u8 tcm_function;
 		int ret;
 
-		transport_init_se_cmd(&cmd->se_cmd,
-				      &lio_target_fabric_configfs->tf_ops,
+		transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops,
 				      conn->sess->se_sess, 0, DMA_NONE,
 				      TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
 
diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h
index e936d56..7d0f9c0 100644
--- a/drivers/target/iscsi/iscsi_target.h
+++ b/drivers/target/iscsi/iscsi_target.h
@@ -35,7 +35,7 @@ extern void iscsit_stop_session(struct iscsi_session *, int, int);
 extern int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *, int);
 
 extern struct iscsit_global *iscsit_global;
-extern struct target_fabric_configfs *lio_target_fabric_configfs;
+extern const struct target_core_fabric_ops iscsi_ops;
 
 extern struct kmem_cache *lio_dr_cache;
 extern struct kmem_cache *lio_ooo_cache;
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index 9cb5ab4..469fce4 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -37,9 +37,6 @@
 #include "iscsi_target_util.h"
 #include "iscsi_target.h"
 #include <target/iscsi/iscsi_target_stat.h>
-#include "iscsi_target_configfs.h"
-
-struct target_fabric_configfs *lio_target_fabric_configfs;
 
 struct lio_target_configfs_attribute {
 	struct configfs_attribute attr;
@@ -1466,10 +1463,8 @@ static struct se_portal_group *lio_target_tiqn_addtpg(
 	if (!tpg)
 		return NULL;
 
-	ret = core_tpg_register(
-			&lio_target_fabric_configfs->tf_ops,
-			wwn, &tpg->tpg_se_tpg, tpg,
-			TRANSPORT_TPG_TYPE_NORMAL);
+	ret = core_tpg_register(&iscsi_ops, wwn, &tpg->tpg_se_tpg,
+				tpg, TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0)
 		return NULL;
 
@@ -1983,117 +1978,60 @@ static void lio_release_cmd(struct se_cmd *se_cmd)
 	iscsit_release_cmd(cmd);
 }
 
-/* End functions for target_core_fabric_ops */
-
-int iscsi_target_register_configfs(void)
-{
-	struct target_fabric_configfs *fabric;
-	int ret;
-
-	lio_target_fabric_configfs = NULL;
-	fabric = target_fabric_configfs_init(THIS_MODULE, "iscsi");
-	if (IS_ERR(fabric)) {
-		pr_err("target_fabric_configfs_init() for"
-				" LIO-Target failed!\n");
-		return PTR_ERR(fabric);
-	}
-	/*
-	 * Setup the fabric API of function pointers used by target_core_mod..
-	 */
-	fabric->tf_ops.get_fabric_name = &iscsi_get_fabric_name;
-	fabric->tf_ops.get_fabric_proto_ident = &iscsi_get_fabric_proto_ident;
-	fabric->tf_ops.tpg_get_wwn = &lio_tpg_get_endpoint_wwn;
-	fabric->tf_ops.tpg_get_tag = &lio_tpg_get_tag;
-	fabric->tf_ops.tpg_get_default_depth = &lio_tpg_get_default_depth;
-	fabric->tf_ops.tpg_get_pr_transport_id = &iscsi_get_pr_transport_id;
-	fabric->tf_ops.tpg_get_pr_transport_id_len =
-				&iscsi_get_pr_transport_id_len;
-	fabric->tf_ops.tpg_parse_pr_out_transport_id =
-				&iscsi_parse_pr_out_transport_id;
-	fabric->tf_ops.tpg_check_demo_mode = &lio_tpg_check_demo_mode;
-	fabric->tf_ops.tpg_check_demo_mode_cache =
-				&lio_tpg_check_demo_mode_cache;
-	fabric->tf_ops.tpg_check_demo_mode_write_protect =
-				&lio_tpg_check_demo_mode_write_protect;
-	fabric->tf_ops.tpg_check_prod_mode_write_protect =
-				&lio_tpg_check_prod_mode_write_protect;
-	fabric->tf_ops.tpg_check_prot_fabric_only =
-				&lio_tpg_check_prot_fabric_only;
-	fabric->tf_ops.tpg_alloc_fabric_acl = &lio_tpg_alloc_fabric_acl;
-	fabric->tf_ops.tpg_release_fabric_acl = &lio_tpg_release_fabric_acl;
-	fabric->tf_ops.tpg_get_inst_index = &lio_tpg_get_inst_index;
-	fabric->tf_ops.check_stop_free = &lio_check_stop_free,
-	fabric->tf_ops.release_cmd = &lio_release_cmd;
-	fabric->tf_ops.shutdown_session = &lio_tpg_shutdown_session;
-	fabric->tf_ops.close_session = &lio_tpg_close_session;
-	fabric->tf_ops.sess_get_index = &lio_sess_get_index;
-	fabric->tf_ops.sess_get_initiator_sid = &lio_sess_get_initiator_sid;
-	fabric->tf_ops.write_pending = &lio_write_pending;
-	fabric->tf_ops.write_pending_status = &lio_write_pending_status;
-	fabric->tf_ops.set_default_node_attributes =
-				&lio_set_default_node_attributes;
-	fabric->tf_ops.get_task_tag = &iscsi_get_task_tag;
-	fabric->tf_ops.get_cmd_state = &iscsi_get_cmd_state;
-	fabric->tf_ops.queue_data_in = &lio_queue_data_in;
-	fabric->tf_ops.queue_status = &lio_queue_status;
-	fabric->tf_ops.queue_tm_rsp = &lio_queue_tm_rsp;
-	fabric->tf_ops.aborted_task = &lio_aborted_task;
-	/*
-	 * Setup function pointers for generic logic in target_core_fabric_configfs.c
-	 */
-	fabric->tf_ops.fabric_make_wwn = &lio_target_call_coreaddtiqn;
-	fabric->tf_ops.fabric_drop_wwn = &lio_target_call_coredeltiqn;
-	fabric->tf_ops.fabric_make_tpg = &lio_target_tiqn_addtpg;
-	fabric->tf_ops.fabric_drop_tpg = &lio_target_tiqn_deltpg;
-	fabric->tf_ops.fabric_post_link	= NULL;
-	fabric->tf_ops.fabric_pre_unlink = NULL;
-	fabric->tf_ops.fabric_make_np = &lio_target_call_addnptotpg;
-	fabric->tf_ops.fabric_drop_np = &lio_target_call_delnpfromtpg;
-	fabric->tf_ops.fabric_make_nodeacl = &lio_target_make_nodeacl;
-	fabric->tf_ops.fabric_drop_nodeacl = &lio_target_drop_nodeacl;
-	/*
-	 * Setup default attribute lists for various fabric->tf_cit_tmpl
-	 * sturct config_item_type's
-	 */
-	fabric->tf_cit_tmpl.tfc_discovery_cit.ct_attrs = lio_target_discovery_auth_attrs;
-	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = lio_target_wwn_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = lio_target_tpg_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = lio_target_tpg_attrib_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_auth_cit.ct_attrs = lio_target_tpg_auth_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = lio_target_tpg_param_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = lio_target_portal_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = lio_target_initiator_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = lio_target_nacl_attrib_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = lio_target_nacl_auth_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = lio_target_nacl_param_attrs;
-
-	ret = target_fabric_configfs_register(fabric);
-	if (ret < 0) {
-		pr_err("target_fabric_configfs_register() for"
-				" LIO-Target failed!\n");
-		target_fabric_configfs_free(fabric);
-		return ret;
-	}
-
-	lio_target_fabric_configfs = fabric;
-	pr_debug("LIO_TARGET[0] - Set fabric ->"
-			" lio_target_fabric_configfs\n");
-	return 0;
-}
-
-
-void iscsi_target_deregister_configfs(void)
-{
-	if (!lio_target_fabric_configfs)
-		return;
-	/*
-	 * Shutdown discovery sessions and disable discovery TPG
-	 */
-	if (iscsit_global->discovery_tpg)
-		iscsit_tpg_disable_portal_group(iscsit_global->discovery_tpg, 1);
-
-	target_fabric_configfs_deregister(lio_target_fabric_configfs);
-	lio_target_fabric_configfs = NULL;
-	pr_debug("LIO_TARGET[0] - Cleared"
-				" lio_target_fabric_configfs\n");
-}
+const struct target_core_fabric_ops iscsi_ops = {
+	.module				= THIS_MODULE,
+	.name				= "iscsi",
+	.get_fabric_name		= iscsi_get_fabric_name,
+	.get_fabric_proto_ident		= iscsi_get_fabric_proto_ident,
+	.tpg_get_wwn			= lio_tpg_get_endpoint_wwn,
+	.tpg_get_tag			= lio_tpg_get_tag,
+	.tpg_get_default_depth		= lio_tpg_get_default_depth,
+	.tpg_get_pr_transport_id	= iscsi_get_pr_transport_id,
+	.tpg_get_pr_transport_id_len	= iscsi_get_pr_transport_id_len,
+	.tpg_parse_pr_out_transport_id	= iscsi_parse_pr_out_transport_id,
+	.tpg_check_demo_mode		= lio_tpg_check_demo_mode,
+	.tpg_check_demo_mode_cache	= lio_tpg_check_demo_mode_cache,
+	.tpg_check_demo_mode_write_protect =
+			lio_tpg_check_demo_mode_write_protect,
+	.tpg_check_prod_mode_write_protect =
+			lio_tpg_check_prod_mode_write_protect,
+	.tpg_check_prot_fabric_only	= &lio_tpg_check_prot_fabric_only,
+	.tpg_alloc_fabric_acl		= lio_tpg_alloc_fabric_acl,
+	.tpg_release_fabric_acl		= lio_tpg_release_fabric_acl,
+	.tpg_get_inst_index		= lio_tpg_get_inst_index,
+	.check_stop_free		= lio_check_stop_free,
+	.release_cmd			= lio_release_cmd,
+	.shutdown_session		= lio_tpg_shutdown_session,
+	.close_session			= lio_tpg_close_session,
+	.sess_get_index			= lio_sess_get_index,
+	.sess_get_initiator_sid		= lio_sess_get_initiator_sid,
+	.write_pending			= lio_write_pending,
+	.write_pending_status		= lio_write_pending_status,
+	.set_default_node_attributes	= lio_set_default_node_attributes,
+	.get_task_tag			= iscsi_get_task_tag,
+	.get_cmd_state			= iscsi_get_cmd_state,
+	.queue_data_in			= lio_queue_data_in,
+	.queue_status			= lio_queue_status,
+	.queue_tm_rsp			= lio_queue_tm_rsp,
+	.aborted_task			= lio_aborted_task,
+	.fabric_make_wwn		= lio_target_call_coreaddtiqn,
+	.fabric_drop_wwn		= lio_target_call_coredeltiqn,
+	.fabric_make_tpg		= lio_target_tiqn_addtpg,
+	.fabric_drop_tpg		= lio_target_tiqn_deltpg,
+	.fabric_make_np			= lio_target_call_addnptotpg,
+	.fabric_drop_np			= lio_target_call_delnpfromtpg,
+	.fabric_make_nodeacl		= lio_target_make_nodeacl,
+	.fabric_drop_nodeacl		= lio_target_drop_nodeacl,
+
+	.tfc_discovery_attrs		= lio_target_discovery_auth_attrs,
+	.tfc_wwn_attrs			= lio_target_wwn_attrs,
+	.tfc_tpg_base_attrs		= lio_target_tpg_attrs,
+	.tfc_tpg_attrib_attrs		= lio_target_tpg_attrib_attrs,
+	.tfc_tpg_auth_attrs		= lio_target_tpg_auth_attrs,
+	.tfc_tpg_param_attrs		= lio_target_tpg_param_attrs,
+	.tfc_tpg_np_base_attrs		= lio_target_portal_attrs,
+	.tfc_tpg_nacl_base_attrs	= lio_target_initiator_attrs,
+	.tfc_tpg_nacl_attrib_attrs	= lio_target_nacl_attrib_attrs,
+	.tfc_tpg_nacl_auth_attrs	= lio_target_nacl_auth_attrs,
+	.tfc_tpg_nacl_param_attrs	= lio_target_nacl_param_attrs,
+};
diff --git a/drivers/target/iscsi/iscsi_target_configfs.h b/drivers/target/iscsi/iscsi_target_configfs.h
deleted file mode 100644
index 8cd5a63..0000000
--- a/drivers/target/iscsi/iscsi_target_configfs.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef ISCSI_TARGET_CONFIGFS_H
-#define ISCSI_TARGET_CONFIGFS_H
-
-extern int iscsi_target_register_configfs(void);
-extern void iscsi_target_deregister_configfs(void);
-
-#endif /* ISCSI_TARGET_CONFIGFS_H */
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index 3076e6f..e8a2408 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -68,10 +68,8 @@ int iscsit_load_discovery_tpg(void)
 		return -1;
 	}
 
-	ret = core_tpg_register(
-			&lio_target_fabric_configfs->tf_ops,
-			NULL, &tpg->tpg_se_tpg, tpg,
-			TRANSPORT_TPG_TYPE_DISCOVERY);
+	ret = core_tpg_register(&iscsi_ops, NULL, &tpg->tpg_se_tpg,
+				tpg, TRANSPORT_TPG_TYPE_DISCOVERY);
 	if (ret < 0) {
 		kfree(tpg);
 		return -1;
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 2114c1d..5b143d2 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -41,8 +41,7 @@
 
 #define to_tcm_loop_hba(hba)	container_of(hba, struct tcm_loop_hba, dev)
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *tcm_loop_fabric_configfs;
+static const struct target_core_fabric_ops loop_ops;
 
 static struct workqueue_struct *tcm_loop_workqueue;
 static struct kmem_cache *tcm_loop_cmd_cache;
@@ -1238,8 +1237,7 @@ static struct se_portal_group *tcm_loop_make_naa_tpg(
 	/*
 	 * Register the tl_tpg as a emulated SAS TCM Target Endpoint
 	 */
-	ret = core_tpg_register(&tcm_loop_fabric_configfs->tf_ops,
-			wwn, &tl_tpg->tl_se_tpg, tl_tpg,
+	ret = core_tpg_register(&loop_ops, wwn, &tl_tpg->tl_se_tpg, tl_tpg,
 			TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0)
 		return ERR_PTR(-ENOMEM);
@@ -1387,129 +1385,51 @@ static struct configfs_attribute *tcm_loop_wwn_attrs[] = {
 
 /* End items for tcm_loop_cit */
 
-static int tcm_loop_register_configfs(void)
-{
-	struct target_fabric_configfs *fabric;
-	int ret;
-	/*
-	 * Set the TCM Loop HBA counter to zero
-	 */
-	tcm_loop_hba_no_cnt = 0;
-	/*
-	 * Register the top level struct config_item_type with TCM core
-	 */
-	fabric = target_fabric_configfs_init(THIS_MODULE, "loopback");
-	if (IS_ERR(fabric)) {
-		pr_err("tcm_loop_register_configfs() failed!\n");
-		return PTR_ERR(fabric);
-	}
-	/*
-	 * Setup the fabric API of function pointers used by target_core_mod
-	 */
-	fabric->tf_ops.get_fabric_name = &tcm_loop_get_fabric_name;
-	fabric->tf_ops.get_fabric_proto_ident = &tcm_loop_get_fabric_proto_ident;
-	fabric->tf_ops.tpg_get_wwn = &tcm_loop_get_endpoint_wwn;
-	fabric->tf_ops.tpg_get_tag = &tcm_loop_get_tag;
-	fabric->tf_ops.tpg_get_default_depth = &tcm_loop_get_default_depth;
-	fabric->tf_ops.tpg_get_pr_transport_id = &tcm_loop_get_pr_transport_id;
-	fabric->tf_ops.tpg_get_pr_transport_id_len =
-					&tcm_loop_get_pr_transport_id_len;
-	fabric->tf_ops.tpg_parse_pr_out_transport_id =
-					&tcm_loop_parse_pr_out_transport_id;
-	fabric->tf_ops.tpg_check_demo_mode = &tcm_loop_check_demo_mode;
-	fabric->tf_ops.tpg_check_demo_mode_cache =
-					&tcm_loop_check_demo_mode_cache;
-	fabric->tf_ops.tpg_check_demo_mode_write_protect =
-					&tcm_loop_check_demo_mode_write_protect;
-	fabric->tf_ops.tpg_check_prod_mode_write_protect =
-					&tcm_loop_check_prod_mode_write_protect;
-	fabric->tf_ops.tpg_check_prot_fabric_only =
-					&tcm_loop_check_prot_fabric_only;
-	/*
-	 * The TCM loopback fabric module runs in demo-mode to a local
-	 * virtual SCSI device, so fabric dependent initator ACLs are
-	 * not required.
-	 */
-	fabric->tf_ops.tpg_alloc_fabric_acl = &tcm_loop_tpg_alloc_fabric_acl;
-	fabric->tf_ops.tpg_release_fabric_acl =
-					&tcm_loop_tpg_release_fabric_acl;
-	fabric->tf_ops.tpg_get_inst_index = &tcm_loop_get_inst_index;
-	/*
-	 * Used for setting up remaining TCM resources in process context
-	 */
-	fabric->tf_ops.check_stop_free = &tcm_loop_check_stop_free;
-	fabric->tf_ops.release_cmd = &tcm_loop_release_cmd;
-	fabric->tf_ops.shutdown_session = &tcm_loop_shutdown_session;
-	fabric->tf_ops.close_session = &tcm_loop_close_session;
-	fabric->tf_ops.sess_get_index = &tcm_loop_sess_get_index;
-	fabric->tf_ops.sess_get_initiator_sid = NULL;
-	fabric->tf_ops.write_pending = &tcm_loop_write_pending;
-	fabric->tf_ops.write_pending_status = &tcm_loop_write_pending_status;
-	/*
-	 * Not used for TCM loopback
-	 */
-	fabric->tf_ops.set_default_node_attributes =
-					&tcm_loop_set_default_node_attributes;
-	fabric->tf_ops.get_task_tag = &tcm_loop_get_task_tag;
-	fabric->tf_ops.get_cmd_state = &tcm_loop_get_cmd_state;
-	fabric->tf_ops.queue_data_in = &tcm_loop_queue_data_in;
-	fabric->tf_ops.queue_status = &tcm_loop_queue_status;
-	fabric->tf_ops.queue_tm_rsp = &tcm_loop_queue_tm_rsp;
-	fabric->tf_ops.aborted_task = &tcm_loop_aborted_task;
-
-	/*
-	 * Setup function pointers for generic logic in target_core_fabric_configfs.c
-	 */
-	fabric->tf_ops.fabric_make_wwn = &tcm_loop_make_scsi_hba;
-	fabric->tf_ops.fabric_drop_wwn = &tcm_loop_drop_scsi_hba;
-	fabric->tf_ops.fabric_make_tpg = &tcm_loop_make_naa_tpg;
-	fabric->tf_ops.fabric_drop_tpg = &tcm_loop_drop_naa_tpg;
-	/*
-	 * fabric_post_link() and fabric_pre_unlink() are used for
-	 * registration and release of TCM Loop Virtual SCSI LUNs.
-	 */
-	fabric->tf_ops.fabric_post_link = &tcm_loop_port_link;
-	fabric->tf_ops.fabric_pre_unlink = &tcm_loop_port_unlink;
-	fabric->tf_ops.fabric_make_np = NULL;
-	fabric->tf_ops.fabric_drop_np = NULL;
-	/*
-	 * Setup default attribute lists for various fabric->tf_cit_tmpl
-	 */
-	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = tcm_loop_wwn_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = tcm_loop_tpg_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = tcm_loop_tpg_attrib_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-	/*
-	 * Once fabric->tf_ops has been setup, now register the fabric for
-	 * use within TCM
-	 */
-	ret = target_fabric_configfs_register(fabric);
-	if (ret < 0) {
-		pr_err("target_fabric_configfs_register() for"
-				" TCM_Loop failed!\n");
-		target_fabric_configfs_free(fabric);
-		return -1;
-	}
-	/*
-	 * Setup our local pointer to *fabric.
-	 */
-	tcm_loop_fabric_configfs = fabric;
-	pr_debug("TCM_LOOP[0] - Set fabric ->"
-			" tcm_loop_fabric_configfs\n");
-	return 0;
-}
-
-static void tcm_loop_deregister_configfs(void)
-{
-	if (!tcm_loop_fabric_configfs)
-		return;
-
-	target_fabric_configfs_deregister(tcm_loop_fabric_configfs);
-	tcm_loop_fabric_configfs = NULL;
-	pr_debug("TCM_LOOP[0] - Cleared"
-				" tcm_loop_fabric_configfs\n");
-}
+static const struct target_core_fabric_ops loop_ops = {
+	.module				= THIS_MODULE,
+	.name				= "loopback",
+	.get_fabric_name		= tcm_loop_get_fabric_name,
+	.get_fabric_proto_ident		= tcm_loop_get_fabric_proto_ident,
+	.tpg_get_wwn			= tcm_loop_get_endpoint_wwn,
+	.tpg_get_tag			= tcm_loop_get_tag,
+	.tpg_get_default_depth		= tcm_loop_get_default_depth,
+	.tpg_get_pr_transport_id	= tcm_loop_get_pr_transport_id,
+	.tpg_get_pr_transport_id_len	= tcm_loop_get_pr_transport_id_len,
+	.tpg_parse_pr_out_transport_id	= tcm_loop_parse_pr_out_transport_id,
+	.tpg_check_demo_mode		= tcm_loop_check_demo_mode,
+	.tpg_check_demo_mode_cache	= tcm_loop_check_demo_mode_cache,
+	.tpg_check_demo_mode_write_protect =
+				tcm_loop_check_demo_mode_write_protect,
+	.tpg_check_prod_mode_write_protect =
+				tcm_loop_check_prod_mode_write_protect,
+	.tpg_check_prot_fabric_only	= tcm_loop_check_prot_fabric_only,
+	.tpg_alloc_fabric_acl		= tcm_loop_tpg_alloc_fabric_acl,
+	.tpg_release_fabric_acl		= tcm_loop_tpg_release_fabric_acl,
+	.tpg_get_inst_index		= tcm_loop_get_inst_index,
+	.check_stop_free		= tcm_loop_check_stop_free,
+	.release_cmd			= tcm_loop_release_cmd,
+	.shutdown_session		= tcm_loop_shutdown_session,
+	.close_session			= tcm_loop_close_session,
+	.sess_get_index			= tcm_loop_sess_get_index,
+	.write_pending			= tcm_loop_write_pending,
+	.write_pending_status		= tcm_loop_write_pending_status,
+	.set_default_node_attributes	= tcm_loop_set_default_node_attributes,
+	.get_task_tag			= tcm_loop_get_task_tag,
+	.get_cmd_state			= tcm_loop_get_cmd_state,
+	.queue_data_in			= tcm_loop_queue_data_in,
+	.queue_status			= tcm_loop_queue_status,
+	.queue_tm_rsp			= tcm_loop_queue_tm_rsp,
+	.aborted_task			= tcm_loop_aborted_task,
+	.fabric_make_wwn		= tcm_loop_make_scsi_hba,
+	.fabric_drop_wwn		= tcm_loop_drop_scsi_hba,
+	.fabric_make_tpg		= tcm_loop_make_naa_tpg,
+	.fabric_drop_tpg		= tcm_loop_drop_naa_tpg,
+	.fabric_post_link		= tcm_loop_port_link,
+	.fabric_pre_unlink		= tcm_loop_port_unlink,
+	.tfc_wwn_attrs			= tcm_loop_wwn_attrs,
+	.tfc_tpg_base_attrs		= tcm_loop_tpg_attrs,
+	.tfc_tpg_attrib_attrs		= tcm_loop_tpg_attrib_attrs,
+};
 
 static int __init tcm_loop_fabric_init(void)
 {
@@ -1533,7 +1453,7 @@ static int __init tcm_loop_fabric_init(void)
 	if (ret)
 		goto out_destroy_cache;
 
-	ret = tcm_loop_register_configfs();
+	ret = target_register_template(&loop_ops);
 	if (ret)
 		goto out_release_core_bus;
 
@@ -1551,7 +1471,7 @@ out:
 
 static void __exit tcm_loop_fabric_exit(void)
 {
-	tcm_loop_deregister_configfs();
+	target_unregister_template(&loop_ops);
 	tcm_loop_release_core_bus();
 	kmem_cache_destroy(tcm_loop_cmd_cache);
 	destroy_workqueue(tcm_loop_workqueue);
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 9512af6..18b0f97 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -42,8 +42,7 @@
 
 #include "sbp_target.h"
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *sbp_fabric_configfs;
+static const struct target_core_fabric_ops sbp_ops;
 
 /* FireWire address region for management and command block address handlers */
 static const struct fw_address_region sbp_register_region = {
@@ -2215,8 +2214,7 @@ static struct se_portal_group *sbp_make_tpg(
 		goto out_free_tpg;
 	}
 
-	ret = core_tpg_register(&sbp_fabric_configfs->tf_ops, wwn,
-			&tpg->se_tpg, (void *)tpg,
+	ret = core_tpg_register(&sbp_ops, wwn, &tpg->se_tpg, tpg,
 			TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0)
 		goto out_unreg_mgt_agt;
@@ -2503,7 +2501,9 @@ static struct configfs_attribute *sbp_tpg_attrib_attrs[] = {
 	NULL,
 };
 
-static struct target_core_fabric_ops sbp_ops = {
+static const struct target_core_fabric_ops sbp_ops = {
+	.module				= THIS_MODULE,
+	.name				= "sbp",
 	.get_fabric_name		= sbp_get_fabric_name,
 	.get_fabric_proto_ident		= sbp_get_fabric_proto_ident,
 	.tpg_get_wwn			= sbp_get_fabric_wwn,
@@ -2544,68 +2544,20 @@ static struct target_core_fabric_ops sbp_ops = {
 	.fabric_drop_np			= NULL,
 	.fabric_make_nodeacl		= sbp_make_nodeacl,
 	.fabric_drop_nodeacl		= sbp_drop_nodeacl,
-};
-
-static int sbp_register_configfs(void)
-{
-	struct target_fabric_configfs *fabric;
-	int ret;
-
-	fabric = target_fabric_configfs_init(THIS_MODULE, "sbp");
-	if (IS_ERR(fabric)) {
-		pr_err("target_fabric_configfs_init() failed\n");
-		return PTR_ERR(fabric);
-	}
-
-	fabric->tf_ops = sbp_ops;
-
-	/*
-	 * Setup default attribute lists for various fabric->tf_cit_tmpl
-	 */
-	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = sbp_wwn_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = sbp_tpg_base_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = sbp_tpg_attrib_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-
-	ret = target_fabric_configfs_register(fabric);
-	if (ret < 0) {
-		pr_err("target_fabric_configfs_register() failed for SBP\n");
-		return ret;
-	}
 
-	sbp_fabric_configfs = fabric;
-
-	return 0;
-};
-
-static void sbp_deregister_configfs(void)
-{
-	if (!sbp_fabric_configfs)
-		return;
-
-	target_fabric_configfs_deregister(sbp_fabric_configfs);
-	sbp_fabric_configfs = NULL;
+	.tfc_wwn_attrs			= sbp_wwn_attrs,
+	.tfc_tpg_base_attrs		= sbp_tpg_base_attrs,
+	.tfc_tpg_attrib_attrs		= sbp_tpg_attrib_attrs,
 };
 
 static int __init sbp_init(void)
 {
-	int ret;
-
-	ret = sbp_register_configfs();
-	if (ret < 0)
-		return ret;
-
-	return 0;
+	return target_register_template(&sbp_ops);
 };
 
 static void __exit sbp_exit(void)
 {
-	sbp_deregister_configfs();
+	target_unregister_template(&sbp_ops);
 };
 
 MODULE_DESCRIPTION("FireWire SBP fabric driver");
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 69baf1c..5a35d3b66 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -300,81 +300,17 @@ struct configfs_subsystem *target_core_subsystem[] = {
 // Start functions called by external Target Fabrics Modules
 //############################################################################*/
 
-/*
- * First function called by fabric modules to:
- *
- * 1) Allocate a struct target_fabric_configfs and save the *fabric_cit pointer.
- * 2) Add struct target_fabric_configfs to g_tf_list
- * 3) Return struct target_fabric_configfs to fabric module to be passed
- *    into target_fabric_configfs_register().
- */
-struct target_fabric_configfs *target_fabric_configfs_init(
-	struct module *fabric_mod,
-	const char *name)
+static int target_fabric_tf_ops_check(const struct target_core_fabric_ops *tfo)
 {
-	struct target_fabric_configfs *tf;
-
-	if (!(name)) {
-		pr_err("Unable to locate passed fabric name\n");
-		return ERR_PTR(-EINVAL);
+	if (!tfo->name) {
+		pr_err("Missing tfo->name\n");
+		return -EINVAL;
 	}
-	if (strlen(name) >= TARGET_FABRIC_NAME_SIZE) {
+	if (strlen(tfo->name) >= TARGET_FABRIC_NAME_SIZE) {
 		pr_err("Passed name: %s exceeds TARGET_FABRIC"
-			"_NAME_SIZE\n", name);
-		return ERR_PTR(-EINVAL);
+			"_NAME_SIZE\n", tfo->name);
+		return -EINVAL;
 	}
-
-	tf = kzalloc(sizeof(struct target_fabric_configfs), GFP_KERNEL);
-	if (!tf)
-		return ERR_PTR(-ENOMEM);
-
-	INIT_LIST_HEAD(&tf->tf_list);
-	atomic_set(&tf->tf_access_cnt, 0);
-	/*
-	 * Setup the default generic struct config_item_type's (cits) in
-	 * struct target_fabric_configfs->tf_cit_tmpl
-	 */
-	tf->tf_module = fabric_mod;
-	target_fabric_setup_cits(tf);
-
-	tf->tf_subsys = target_core_subsystem[0];
-	snprintf(tf->tf_name, TARGET_FABRIC_NAME_SIZE, "%s", name);
-
-	mutex_lock(&g_tf_lock);
-	list_add_tail(&tf->tf_list, &g_tf_list);
-	mutex_unlock(&g_tf_lock);
-
-	pr_debug("<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>"
-			">>>>>>>>>>>>>>\n");
-	pr_debug("Initialized struct target_fabric_configfs: %p for"
-			" %s\n", tf, tf->tf_name);
-	return tf;
-}
-EXPORT_SYMBOL(target_fabric_configfs_init);
-
-/*
- * Called by fabric plugins after FAILED target_fabric_configfs_register() call.
- */
-void target_fabric_configfs_free(
-	struct target_fabric_configfs *tf)
-{
-	mutex_lock(&g_tf_lock);
-	list_del(&tf->tf_list);
-	mutex_unlock(&g_tf_lock);
-
-	kfree(tf);
-}
-EXPORT_SYMBOL(target_fabric_configfs_free);
-
-/*
- * Perform a sanity check of the passed tf->tf_ops before completing
- * TCM fabric module registration.
- */
-static int target_fabric_tf_ops_check(
-	struct target_fabric_configfs *tf)
-{
-	struct target_core_fabric_ops *tfo = &tf->tf_ops;
-
 	if (!tfo->get_fabric_name) {
 		pr_err("Missing tfo->get_fabric_name()\n");
 		return -EINVAL;
@@ -508,77 +444,59 @@ static int target_fabric_tf_ops_check(
 	return 0;
 }
 
-/*
- * Called 2nd from fabric module with returned parameter of
- * struct target_fabric_configfs * from target_fabric_configfs_init().
- *
- * Upon a successful registration, the new fabric's struct config_item is
- * return.  Also, a pointer to this struct is set in the passed
- * struct target_fabric_configfs.
- */
-int target_fabric_configfs_register(
-	struct target_fabric_configfs *tf)
+int target_register_template(const struct target_core_fabric_ops *fo)
 {
+	struct target_fabric_configfs *tf;
 	int ret;
 
+	ret = target_fabric_tf_ops_check(fo);
+	if (ret)
+		return ret;
+
+	tf = kzalloc(sizeof(struct target_fabric_configfs), GFP_KERNEL);
 	if (!tf) {
-		pr_err("Unable to locate target_fabric_configfs"
-			" pointer\n");
-		return -EINVAL;
-	}
-	if (!tf->tf_subsys) {
-		pr_err("Unable to target struct config_subsystem"
-			" pointer\n");
-		return -EINVAL;
+		pr_err("%s: could not allocate memory!\n", __func__);
+		return -ENOMEM;
 	}
-	ret = target_fabric_tf_ops_check(tf);
-	if (ret < 0)
-		return ret;
 
-	pr_debug("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>"
-		">>>>>>>>>>\n");
+	INIT_LIST_HEAD(&tf->tf_list);
+	atomic_set(&tf->tf_access_cnt, 0);
+
+	/*
+	 * Setup the default generic struct config_item_type's (cits) in
+	 * struct target_fabric_configfs->tf_cit_tmpl
+	 */
+	tf->tf_module = fo->module;
+	tf->tf_subsys = target_core_subsystem[0];
+	snprintf(tf->tf_name, TARGET_FABRIC_NAME_SIZE, "%s", fo->name);
+
+	tf->tf_ops = *fo;
+	target_fabric_setup_cits(tf);
+
+	mutex_lock(&g_tf_lock);
+	list_add_tail(&tf->tf_list, &g_tf_list);
+	mutex_unlock(&g_tf_lock);
+
 	return 0;
 }
-EXPORT_SYMBOL(target_fabric_configfs_register);
+EXPORT_SYMBOL(target_register_template);
 
-void target_fabric_configfs_deregister(
-	struct target_fabric_configfs *tf)
+void target_unregister_template(const struct target_core_fabric_ops *fo)
 {
-	struct configfs_subsystem *su;
+	struct target_fabric_configfs *t;
 
-	if (!tf) {
-		pr_err("Unable to locate passed target_fabric_"
-			"configfs\n");
-		return;
-	}
-	su = tf->tf_subsys;
-	if (!su) {
-		pr_err("Unable to locate passed tf->tf_subsys"
-			" pointer\n");
-		return;
-	}
-	pr_debug("<<<<<<<<<<<<<<<<<<<<<< BEGIN FABRIC API >>>>>>>>>>"
-			">>>>>>>>>>>>\n");
 	mutex_lock(&g_tf_lock);
-	if (atomic_read(&tf->tf_access_cnt)) {
-		mutex_unlock(&g_tf_lock);
-		pr_err("Non zero tf->tf_access_cnt for fabric %s\n",
-			tf->tf_name);
-		BUG();
+	list_for_each_entry(t, &g_tf_list, tf_list) {
+		if (strcmp(t->tf_name, fo->name)) {
+			BUG_ON(atomic_read(&t->tf_access_cnt));
+			list_del(&t->tf_list);
+			kfree(t);
+			break;
+		}
 	}
-	list_del(&tf->tf_list);
 	mutex_unlock(&g_tf_lock);
-
-	pr_debug("Target_Core_ConfigFS: DEREGISTER -> Releasing tf:"
-			" %s\n", tf->tf_name);
-	tf->tf_module = NULL;
-	tf->tf_subsys = NULL;
-	kfree(tf);
-
-	pr_debug("<<<<<<<<<<<<<<<<<<<<<< END FABRIC API >>>>>>>>>>>>>>>>>"
-			">>>>>\n");
 }
-EXPORT_SYMBOL(target_fabric_configfs_deregister);
+EXPORT_SYMBOL(target_unregister_template);
 
 /*##############################################################################
 // Stop functions called by external Target Fabrics Modules
@@ -945,7 +863,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
 	struct se_lun *lun;
 	struct se_portal_group *se_tpg;
 	struct t10_pr_registration *pr_reg;
-	struct target_core_fabric_ops *tfo;
+	const struct target_core_fabric_ops *tfo;
 	ssize_t len = 0;
 
 	spin_lock(&dev->dev_reservation_lock);
@@ -979,7 +897,7 @@ SE_DEV_PR_ATTR_RO(res_pr_holder_tg_port);
 static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
 		struct se_device *dev, char *page)
 {
-	struct target_core_fabric_ops *tfo;
+	const struct target_core_fabric_ops *tfo;
 	struct t10_pr_registration *pr_reg;
 	unsigned char buf[384];
 	char i_buf[PR_REG_ISID_ID_LEN];
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c
index 0c3f901..1f7886b 100644
--- a/drivers/target/target_core_fabric_configfs.c
+++ b/drivers/target/target_core_fabric_configfs.c
@@ -56,6 +56,20 @@ static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf)
 	pr_debug("Setup generic %s\n", __stringify(_name));		\
 }
 
+#define TF_CIT_SETUP_DRV(_name, _item_ops, _group_ops)		\
+static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
+{									\
+	struct target_fabric_configfs_template *tfc = &tf->tf_cit_tmpl;	\
+	struct config_item_type *cit = &tfc->tfc_##_name##_cit;		\
+	struct configfs_attribute **attrs = tf->tf_ops.tfc_##_name##_attrs; \
+									\
+	cit->ct_item_ops = _item_ops;					\
+	cit->ct_group_ops = _group_ops;					\
+	cit->ct_attrs = attrs;						\
+	cit->ct_owner = tf->tf_module;					\
+	pr_debug("Setup generic %s\n", __stringify(_name));		\
+}
+
 /* Start of tfc_tpg_mappedlun_cit */
 
 static int target_fabric_mappedlun_link(
@@ -278,7 +292,7 @@ static struct configfs_item_operations target_fabric_nacl_attrib_item_ops = {
 	.store_attribute	= target_fabric_nacl_attrib_attr_store,
 };
 
-TF_CIT_SETUP(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL);
 
 /* End of tfc_tpg_nacl_attrib_cit */
 
@@ -291,7 +305,7 @@ static struct configfs_item_operations target_fabric_nacl_auth_item_ops = {
 	.store_attribute	= target_fabric_nacl_auth_attr_store,
 };
 
-TF_CIT_SETUP(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL);
 
 /* End of tfc_tpg_nacl_auth_cit */
 
@@ -304,7 +318,7 @@ static struct configfs_item_operations target_fabric_nacl_param_item_ops = {
 	.store_attribute	= target_fabric_nacl_param_attr_store,
 };
 
-TF_CIT_SETUP(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL);
 
 /* End of tfc_tpg_nacl_param_cit */
 
@@ -461,8 +475,8 @@ static struct configfs_group_operations target_fabric_nacl_base_group_ops = {
 	.drop_item		= target_fabric_drop_mappedlun,
 };
 
-TF_CIT_SETUP(tpg_nacl_base, &target_fabric_nacl_base_item_ops,
-		&target_fabric_nacl_base_group_ops, NULL);
+TF_CIT_SETUP_DRV(tpg_nacl_base, &target_fabric_nacl_base_item_ops,
+		&target_fabric_nacl_base_group_ops);
 
 /* End of tfc_tpg_nacl_base_cit */
 
@@ -570,7 +584,7 @@ static struct configfs_item_operations target_fabric_np_base_item_ops = {
 	.store_attribute	= target_fabric_np_base_attr_store,
 };
 
-TF_CIT_SETUP(tpg_np_base, &target_fabric_np_base_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_np_base, &target_fabric_np_base_item_ops, NULL);
 
 /* End of tfc_tpg_np_base_cit */
 
@@ -966,7 +980,7 @@ static struct configfs_item_operations target_fabric_tpg_attrib_item_ops = {
 	.store_attribute	= target_fabric_tpg_attrib_attr_store,
 };
 
-TF_CIT_SETUP(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL);
 
 /* End of tfc_tpg_attrib_cit */
 
@@ -979,7 +993,7 @@ static struct configfs_item_operations target_fabric_tpg_auth_item_ops = {
 	.store_attribute	= target_fabric_tpg_auth_attr_store,
 };
 
-TF_CIT_SETUP(tpg_auth, &target_fabric_tpg_auth_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_auth, &target_fabric_tpg_auth_item_ops, NULL);
 
 /* End of tfc_tpg_attrib_cit */
 
@@ -992,7 +1006,7 @@ static struct configfs_item_operations target_fabric_tpg_param_item_ops = {
 	.store_attribute	= target_fabric_tpg_param_attr_store,
 };
 
-TF_CIT_SETUP(tpg_param, &target_fabric_tpg_param_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_param, &target_fabric_tpg_param_item_ops, NULL);
 
 /* End of tfc_tpg_param_cit */
 
@@ -1018,7 +1032,7 @@ static struct configfs_item_operations target_fabric_tpg_base_item_ops = {
 	.store_attribute	= target_fabric_tpg_attr_store,
 };
 
-TF_CIT_SETUP(tpg_base, &target_fabric_tpg_base_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(tpg_base, &target_fabric_tpg_base_item_ops, NULL);
 
 /* End of tfc_tpg_base_cit */
 
@@ -1192,7 +1206,7 @@ static struct configfs_item_operations target_fabric_wwn_item_ops = {
 	.store_attribute	= target_fabric_wwn_attr_store,
 };
 
-TF_CIT_SETUP(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops, NULL);
+TF_CIT_SETUP_DRV(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops);
 
 /* End of tfc_wwn_cit */
 
@@ -1206,7 +1220,7 @@ static struct configfs_item_operations target_fabric_discovery_item_ops = {
 	.store_attribute	= target_fabric_discovery_attr_store,
 };
 
-TF_CIT_SETUP(discovery, &target_fabric_discovery_item_ops, NULL, NULL);
+TF_CIT_SETUP_DRV(discovery, &target_fabric_discovery_item_ops, NULL);
 
 /* End of tfc_discovery_cit */
 
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 7436fda..963a677 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -680,7 +680,7 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
 	struct se_dev_entry *deve_tmp;
 	struct se_node_acl *nacl_tmp;
 	struct se_port *port, *port_tmp;
-	struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
+	const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
 	struct t10_pr_registration *pr_reg, *pr_reg_atp, *pr_reg_tmp, *pr_reg_tmp_safe;
 	int ret;
 	/*
@@ -979,7 +979,7 @@ int core_scsi3_check_aptpl_registration(
 }
 
 static void __core_scsi3_dump_registration(
-	struct target_core_fabric_ops *tfo,
+	const struct target_core_fabric_ops *tfo,
 	struct se_device *dev,
 	struct se_node_acl *nacl,
 	struct t10_pr_registration *pr_reg,
@@ -1020,7 +1020,7 @@ static void __core_scsi3_add_registration(
 	enum register_type register_type,
 	int register_move)
 {
-	struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
+	const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
 	struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
 	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 
@@ -1237,7 +1237,7 @@ static void __core_scsi3_free_registration(
 	struct list_head *preempt_and_abort_list,
 	int dec_holders)
 {
-	struct target_core_fabric_ops *tfo =
+	const struct target_core_fabric_ops *tfo =
 			pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo;
 	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	char i_buf[PR_REG_ISID_ID_LEN];
@@ -1461,7 +1461,7 @@ core_scsi3_decode_spec_i_port(
 	struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
 	LIST_HEAD(tid_dest_list);
 	struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
-	struct target_core_fabric_ops *tmp_tf_ops;
+	const struct target_core_fabric_ops *tmp_tf_ops;
 	unsigned char *buf;
 	unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident;
 	char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
@@ -2422,7 +2422,7 @@ static void __core_scsi3_complete_pro_release(
 	int explicit,
 	int unreg)
 {
-	struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo;
+	const struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo;
 	char i_buf[PR_REG_ISID_ID_LEN];
 	int pr_res_type = 0, pr_res_scope = 0;
 
@@ -2734,7 +2734,7 @@ static void __core_scsi3_complete_pro_preempt(
 	enum preempt_type preempt_type)
 {
 	struct se_node_acl *nacl = pr_reg->pr_reg_nacl;
-	struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
+	const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
 	char i_buf[PR_REG_ISID_ID_LEN];
 
 	memset(i_buf, 0, PR_REG_ISID_ID_LEN);
@@ -3119,7 +3119,7 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
 	struct se_node_acl *pr_res_nacl, *pr_reg_nacl, *dest_node_acl = NULL;
 	struct se_port *se_port;
 	struct se_portal_group *se_tpg, *dest_se_tpg = NULL;
-	struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
+	const struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
 	struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
 	struct t10_reservation *pr_tmpl = &dev->t10_pr;
 	unsigned char *buf;
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index 0696de9..47f0644 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -672,7 +672,7 @@ static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
 }
 
 int core_tpg_register(
-	struct target_core_fabric_ops *tfo,
+	const struct target_core_fabric_ops *tfo,
 	struct se_wwn *se_wwn,
 	struct se_portal_group *se_tpg,
 	void *tpg_fabric_ptr,
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 303ae98..47334e5 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -322,7 +322,7 @@ void __transport_register_session(
 	struct se_session *se_sess,
 	void *fabric_sess_ptr)
 {
-	struct target_core_fabric_ops *tfo = se_tpg->se_tpg_tfo;
+	const struct target_core_fabric_ops *tfo = se_tpg->se_tpg_tfo;
 	unsigned char buf[PR_REG_ISID_LEN];
 
 	se_sess->se_tpg = se_tpg;
@@ -494,7 +494,7 @@ EXPORT_SYMBOL(transport_free_session);
 void transport_deregister_session(struct se_session *se_sess)
 {
 	struct se_portal_group *se_tpg = se_sess->se_tpg;
-	struct target_core_fabric_ops *se_tfo;
+	const struct target_core_fabric_ops *se_tfo;
 	struct se_node_acl *se_nacl;
 	unsigned long flags;
 	bool comp_nacl = true;
@@ -1150,7 +1150,7 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
  */
 void transport_init_se_cmd(
 	struct se_cmd *cmd,
-	struct target_core_fabric_ops *tfo,
+	const struct target_core_fabric_ops *tfo,
 	struct se_session *se_sess,
 	u32 data_length,
 	int data_direction,
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index 8585acb..a600ff1 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -425,7 +425,7 @@ static int xcopy_pt_queue_status(struct se_cmd *se_cmd)
 	return 0;
 }
 
-static struct target_core_fabric_ops xcopy_pt_tfo = {
+static const struct target_core_fabric_ops xcopy_pt_tfo = {
 	.get_fabric_name	= xcopy_pt_get_fabric_name,
 	.get_task_tag		= xcopy_pt_get_tag,
 	.get_cmd_state		= xcopy_pt_get_cmd_state,
diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h
index a0bcfd3..881deb3 100644
--- a/drivers/target/tcm_fc/tcm_fc.h
+++ b/drivers/target/tcm_fc/tcm_fc.h
@@ -129,7 +129,6 @@ struct ft_cmd {
 
 extern struct mutex ft_lport_lock;
 extern struct fc4_prov ft_prov;
-extern struct target_fabric_configfs *ft_configfs;
 extern unsigned int ft_debug_logging;
 
 /*
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index efdcb96..65dce13 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -48,7 +48,7 @@
 
 #include "tcm_fc.h"
 
-struct target_fabric_configfs *ft_configfs;
+static const struct target_core_fabric_ops ft_fabric_ops;
 
 static LIST_HEAD(ft_wwn_list);
 DEFINE_MUTEX(ft_lport_lock);
@@ -337,7 +337,7 @@ static struct se_portal_group *ft_add_tpg(
 		return NULL;
 	}
 
-	ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
+	ret = core_tpg_register(&ft_fabric_ops, wwn, &tpg->se_tpg,
 				tpg, TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0) {
 		destroy_workqueue(wq);
@@ -507,7 +507,9 @@ static u32 ft_tpg_get_inst_index(struct se_portal_group *se_tpg)
 	return tpg->index;
 }
 
-static struct target_core_fabric_ops ft_fabric_ops = {
+static const struct target_core_fabric_ops ft_fabric_ops = {
+	.module =			THIS_MODULE,
+	.name =				"fc",
 	.get_fabric_name =		ft_get_fabric_name,
 	.get_fabric_proto_ident =	fc_get_fabric_proto_ident,
 	.tpg_get_wwn =			ft_get_fabric_wwn,
@@ -552,62 +554,10 @@ static struct target_core_fabric_ops ft_fabric_ops = {
 	.fabric_drop_np =		NULL,
 	.fabric_make_nodeacl =		&ft_add_acl,
 	.fabric_drop_nodeacl =		&ft_del_acl,
-};
-
-static int ft_register_configfs(void)
-{
-	struct target_fabric_configfs *fabric;
-	int ret;
-
-	/*
-	 * Register the top level struct config_item_type with TCM core
-	 */
-	fabric = target_fabric_configfs_init(THIS_MODULE, "fc");
-	if (IS_ERR(fabric)) {
-		pr_err("%s: target_fabric_configfs_init() failed!\n",
-		       __func__);
-		return PTR_ERR(fabric);
-	}
-	fabric->tf_ops = ft_fabric_ops;
-
-	/*
-	 * Setup default attribute lists for various fabric->tf_cit_tmpl
-	 */
-	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = ft_wwn_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs =
-						    ft_nacl_base_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-	/*
-	 * register the fabric for use within TCM
-	 */
-	ret = target_fabric_configfs_register(fabric);
-	if (ret < 0) {
-		pr_debug("target_fabric_configfs_register() for"
-			    " FC Target failed!\n");
-		target_fabric_configfs_free(fabric);
-		return -1;
-	}
-
-	/*
-	 * Setup our local pointer to *fabric.
-	 */
-	ft_configfs = fabric;
-	return 0;
-}
 
-static void ft_deregister_configfs(void)
-{
-	if (!ft_configfs)
-		return;
-	target_fabric_configfs_deregister(ft_configfs);
-	ft_configfs = NULL;
-}
+	.tfc_wwn_attrs			= ft_wwn_attrs,
+	.tfc_tpg_nacl_base_attrs	= ft_nacl_base_attrs,
+};
 
 static struct notifier_block ft_notifier = {
 	.notifier_call = ft_lport_notify
@@ -615,15 +565,24 @@ static struct notifier_block ft_notifier = {
 
 static int __init ft_init(void)
 {
-	if (ft_register_configfs())
-		return -1;
-	if (fc_fc4_register_provider(FC_TYPE_FCP, &ft_prov)) {
-		ft_deregister_configfs();
-		return -1;
-	}
+	int ret;
+
+	ret = target_register_template(&ft_fabric_ops);
+	if (ret)
+		goto out;
+
+	ret = fc_fc4_register_provider(FC_TYPE_FCP, &ft_prov);
+	if (ret)
+		goto out_unregister_template;
+
 	blocking_notifier_chain_register(&fc_lport_notifier_head, &ft_notifier);
 	fc_lport_iterate(ft_lport_add, NULL);
 	return 0;
+
+out_unregister_template:
+	target_unregister_template(&ft_fabric_ops);
+out:
+	return ret;
 }
 
 static void __exit ft_exit(void)
@@ -632,7 +591,7 @@ static void __exit ft_exit(void)
 					   &ft_notifier);
 	fc_fc4_deregister_provider(FC_TYPE_FCP, &ft_prov);
 	fc_lport_iterate(ft_lport_del, NULL);
-	ft_deregister_configfs();
+	target_unregister_template(&ft_fabric_ops);
 	synchronize_rcu();
 }
 
diff --git a/drivers/usb/gadget/legacy/tcm_usb_gadget.c b/drivers/usb/gadget/legacy/tcm_usb_gadget.c
index 3a49416..7ea2a44c 100644
--- a/drivers/usb/gadget/legacy/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/legacy/tcm_usb_gadget.c
@@ -29,7 +29,7 @@
 
 USB_GADGET_COMPOSITE_OPTIONS();
 
-static struct target_fabric_configfs *usbg_fabric_configfs;
+static const struct target_core_fabric_ops usbg_ops;
 
 static inline struct f_uas *to_f_uas(struct usb_function *f)
 {
@@ -1572,8 +1572,7 @@ static struct se_portal_group *usbg_make_tpg(
 	tpg->tport = tport;
 	tpg->tport_tpgt = tpgt;
 
-	ret = core_tpg_register(&usbg_fabric_configfs->tf_ops, wwn,
-				&tpg->se_tpg, tpg,
+	ret = core_tpg_register(&usbg_ops, wwn, &tpg->se_tpg, tpg,
 				TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0) {
 		destroy_workqueue(tpg->workqueue);
@@ -1865,7 +1864,9 @@ static int usbg_check_stop_free(struct se_cmd *se_cmd)
 	return 1;
 }
 
-static struct target_core_fabric_ops usbg_ops = {
+static const struct target_core_fabric_ops usbg_ops = {
+	.module				= THIS_MODULE,
+	.name				= "usb_gadget",
 	.get_fabric_name		= usbg_get_fabric_name,
 	.get_fabric_proto_ident		= usbg_get_fabric_proto_ident,
 	.tpg_get_wwn			= usbg_get_fabric_wwn,
@@ -1907,46 +1908,9 @@ static struct target_core_fabric_ops usbg_ops = {
 	.fabric_drop_np			= NULL,
 	.fabric_make_nodeacl		= usbg_make_nodeacl,
 	.fabric_drop_nodeacl		= usbg_drop_nodeacl,
-};
-
-static int usbg_register_configfs(void)
-{
-	struct target_fabric_configfs *fabric;
-	int ret;
-
-	fabric = target_fabric_configfs_init(THIS_MODULE, "usb_gadget");
-	if (IS_ERR(fabric)) {
-		printk(KERN_ERR "target_fabric_configfs_init() failed\n");
-		return PTR_ERR(fabric);
-	}
-
-	fabric->tf_ops = usbg_ops;
-	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = usbg_wwn_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = usbg_base_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-	ret = target_fabric_configfs_register(fabric);
-	if (ret < 0) {
-		printk(KERN_ERR "target_fabric_configfs_register() failed"
-				" for usb-gadget\n");
-		return ret;
-	}
-	usbg_fabric_configfs = fabric;
-	return 0;
-};
 
-static void usbg_deregister_configfs(void)
-{
-	if (!(usbg_fabric_configfs))
-		return;
-
-	target_fabric_configfs_deregister(usbg_fabric_configfs);
-	usbg_fabric_configfs = NULL;
+	.tfc_wwn_attrs			= usbg_wwn_attrs,
+	.tfc_tpg_base_attrs		= usbg_base_attrs,
 };
 
 /* Start gadget.c code */
@@ -2455,16 +2419,13 @@ static void usbg_detach(struct usbg_tpg *tpg)
 
 static int __init usb_target_gadget_init(void)
 {
-	int ret;
-
-	ret = usbg_register_configfs();
-	return ret;
+	return target_register_template(&usbg_ops);
 }
 module_init(usb_target_gadget_init);
 
 static void __exit usb_target_gadget_exit(void)
 {
-	usbg_deregister_configfs();
+	target_unregister_template(&usbg_ops);
 }
 module_exit(usb_target_gadget_exit);
 
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 27ed964..e8c88b4 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -216,9 +216,7 @@ struct vhost_scsi {
 	int vs_events_nr; /* num of pending events, protected by vq->mutex */
 };
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *vhost_scsi_fabric_configfs;
-
+static struct target_core_fabric_ops vhost_scsi_ops;
 static struct workqueue_struct *vhost_scsi_workqueue;
 
 /* Global spinlock to protect vhost_scsi TPG list for vhost IOCTL access */
@@ -2205,7 +2203,7 @@ vhost_scsi_make_tpg(struct se_wwn *wwn,
 	tpg->tport = tport;
 	tpg->tport_tpgt = tpgt;
 
-	ret = core_tpg_register(&vhost_scsi_fabric_configfs->tf_ops, wwn,
+	ret = core_tpg_register(&vhost_scsi_ops, wwn,
 				&tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0) {
 		kfree(tpg);
@@ -2327,6 +2325,8 @@ static struct configfs_attribute *vhost_scsi_wwn_attrs[] = {
 };
 
 static struct target_core_fabric_ops vhost_scsi_ops = {
+	.module				= THIS_MODULE,
+	.name				= "vhost",
 	.get_fabric_name		= vhost_scsi_get_fabric_name,
 	.get_fabric_proto_ident		= vhost_scsi_get_fabric_proto_ident,
 	.tpg_get_wwn			= vhost_scsi_get_fabric_wwn,
@@ -2371,70 +2371,20 @@ static struct target_core_fabric_ops vhost_scsi_ops = {
 	.fabric_drop_np			= NULL,
 	.fabric_make_nodeacl		= vhost_scsi_make_nodeacl,
 	.fabric_drop_nodeacl		= vhost_scsi_drop_nodeacl,
+
+	.tfc_wwn_attrs			= vhost_scsi_wwn_attrs,
+	.tfc_tpg_base_attrs		= vhost_scsi_tpg_attrs,
+	.tfc_tpg_attrib_attrs		= vhost_scsi_tpg_attrib_attrs,
 };
 
-static int vhost_scsi_register_configfs(void)
+static int __init vhost_scsi_init(void)
 {
-	struct target_fabric_configfs *fabric;
-	int ret;
+	int ret = -ENOMEM;
 
-	pr_debug("vhost-scsi fabric module %s on %s/%s"
+	pr_debug("TCM_VHOST fabric module %s on %s/%s"
 		" on "UTS_RELEASE"\n", VHOST_SCSI_VERSION, utsname()->sysname,
 		utsname()->machine);
-	/*
-	 * Register the top level struct config_item_type with TCM core
-	 */
-	fabric = target_fabric_configfs_init(THIS_MODULE, "vhost");
-	if (IS_ERR(fabric)) {
-		pr_err("target_fabric_configfs_init() failed\n");
-		return PTR_ERR(fabric);
-	}
-	/*
-	 * Setup fabric->tf_ops from our local vhost_scsi_ops
-	 */
-	fabric->tf_ops = vhost_scsi_ops;
-	/*
-	 * Setup default attribute lists for various fabric->tf_cit_tmpl
-	 */
-	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = vhost_scsi_wwn_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = vhost_scsi_tpg_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = vhost_scsi_tpg_attrib_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-	/*
-	 * Register the fabric for use within TCM
-	 */
-	ret = target_fabric_configfs_register(fabric);
-	if (ret < 0) {
-		pr_err("target_fabric_configfs_register() failed"
-				" for TCM_VHOST\n");
-		return ret;
-	}
-	/*
-	 * Setup our local pointer to *fabric
-	 */
-	vhost_scsi_fabric_configfs = fabric;
-	pr_debug("TCM_VHOST[0] - Set fabric -> vhost_scsi_fabric_configfs\n");
-	return 0;
-};
-
-static void vhost_scsi_deregister_configfs(void)
-{
-	if (!vhost_scsi_fabric_configfs)
-		return;
-
-	target_fabric_configfs_deregister(vhost_scsi_fabric_configfs);
-	vhost_scsi_fabric_configfs = NULL;
-	pr_debug("TCM_VHOST[0] - Cleared vhost_scsi_fabric_configfs\n");
-};
 
-static int __init vhost_scsi_init(void)
-{
-	int ret = -ENOMEM;
 	/*
 	 * Use our own dedicated workqueue for submitting I/O into
 	 * target core to avoid contention within system_wq.
@@ -2447,7 +2397,7 @@ static int __init vhost_scsi_init(void)
 	if (ret < 0)
 		goto out_destroy_workqueue;
 
-	ret = vhost_scsi_register_configfs();
+	ret = target_register_template(&vhost_scsi_ops);
 	if (ret < 0)
 		goto out_vhost_scsi_deregister;
 
@@ -2463,7 +2413,7 @@ out:
 
 static void vhost_scsi_exit(void)
 {
-	vhost_scsi_deregister_configfs();
+	target_unregister_template(&vhost_scsi_ops);
 	vhost_scsi_deregister();
 	destroy_workqueue(vhost_scsi_workqueue);
 };
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 61653a0..f8a1bd7 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -205,8 +205,7 @@ static LIST_HEAD(scsiback_free_pages);
 static DEFINE_MUTEX(scsiback_mutex);
 static LIST_HEAD(scsiback_list);
 
-/* Local pointer to allocated TCM configfs fabric module */
-static struct target_fabric_configfs *scsiback_fabric_configfs;
+static const struct target_core_fabric_ops scsiback_ops;
 
 static void scsiback_get(struct vscsibk_info *info)
 {
@@ -1901,7 +1900,7 @@ scsiback_make_tpg(struct se_wwn *wwn,
 	tpg->tport = tport;
 	tpg->tport_tpgt = tpgt;
 
-	ret = core_tpg_register(&scsiback_fabric_configfs->tf_ops, wwn,
+	ret = core_tpg_register(&scsiback_ops, wwn,
 				&tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL);
 	if (ret < 0) {
 		kfree(tpg);
@@ -1943,7 +1942,9 @@ static int scsiback_check_false(struct se_portal_group *se_tpg)
 	return 0;
 }
 
-static struct target_core_fabric_ops scsiback_ops = {
+static const struct target_core_fabric_ops scsiback_ops = {
+	.module				= THIS_MODULE,
+	.name				= "xen-pvscsi",
 	.get_fabric_name		= scsiback_get_fabric_name,
 	.get_fabric_proto_ident		= scsiback_get_fabric_proto_ident,
 	.tpg_get_wwn			= scsiback_get_fabric_wwn,
@@ -1990,62 +1991,10 @@ static struct target_core_fabric_ops scsiback_ops = {
 	.fabric_make_nodeacl		= scsiback_make_nodeacl,
 	.fabric_drop_nodeacl		= scsiback_drop_nodeacl,
 #endif
-};
-
-static int scsiback_register_configfs(void)
-{
-	struct target_fabric_configfs *fabric;
-	int ret;
 
-	pr_debug("xen-pvscsi: fabric module %s on %s/%s on "UTS_RELEASE"\n",
-		 VSCSI_VERSION, utsname()->sysname, utsname()->machine);
-	/*
-	 * Register the top level struct config_item_type with TCM core
-	 */
-	fabric = target_fabric_configfs_init(THIS_MODULE, "xen-pvscsi");
-	if (IS_ERR(fabric))
-		return PTR_ERR(fabric);
-
-	/*
-	 * Setup fabric->tf_ops from our local scsiback_ops
-	 */
-	fabric->tf_ops = scsiback_ops;
-	/*
-	 * Setup default attribute lists for various fabric->tf_cit_tmpl
-	 */
-	fabric->tf_cit_tmpl.tfc_wwn_cit.ct_attrs = scsiback_wwn_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_base_cit.ct_attrs = scsiback_tpg_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_attrib_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_param_cit.ct_attrs = scsiback_param_attrs;
-	fabric->tf_cit_tmpl.tfc_tpg_np_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_base_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_attrib_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_auth_cit.ct_attrs = NULL;
-	fabric->tf_cit_tmpl.tfc_tpg_nacl_param_cit.ct_attrs = NULL;
-	/*
-	 * Register the fabric for use within TCM
-	 */
-	ret = target_fabric_configfs_register(fabric);
-	if (ret < 0) {
-		target_fabric_configfs_free(fabric);
-		return ret;
-	}
-	/*
-	 * Setup our local pointer to *fabric
-	 */
-	scsiback_fabric_configfs = fabric;
-	pr_debug("xen-pvscsi: Set fabric -> scsiback_fabric_configfs\n");
-	return 0;
-};
-
-static void scsiback_deregister_configfs(void)
-{
-	if (!scsiback_fabric_configfs)
-		return;
-
-	target_fabric_configfs_deregister(scsiback_fabric_configfs);
-	scsiback_fabric_configfs = NULL;
-	pr_debug("xen-pvscsi: Cleared scsiback_fabric_configfs\n");
+	.tfc_wwn_attrs			= scsiback_wwn_attrs,
+	.tfc_tpg_base_attrs		= scsiback_tpg_attrs,
+	.tfc_tpg_param_attrs		= scsiback_param_attrs,
 };
 
 static const struct xenbus_device_id scsiback_ids[] = {
@@ -2077,6 +2026,9 @@ static int __init scsiback_init(void)
 	if (!xen_domain())
 		return -ENODEV;
 
+	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)
@@ -2086,7 +2038,7 @@ static int __init scsiback_init(void)
 	if (ret)
 		goto out_cache_destroy;
 
-	ret = scsiback_register_configfs();
+	ret = target_register_template(&scsiback_ops);
 	if (ret)
 		goto out_unregister_xenbus;
 
@@ -2109,7 +2061,7 @@ static void __exit scsiback_exit(void)
 			BUG();
 		gnttab_free_pages(1, &page);
 	}
-	scsiback_deregister_configfs();
+	target_unregister_template(&scsiback_ops);
 	xenbus_unregister_driver(&scsiback_driver);
 	kmem_cache_destroy(scsiback_cachep);
 }
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 0f2066a..dae4689 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -519,7 +519,7 @@ struct se_cmd {
 	struct list_head	se_cmd_list;
 	struct completion	cmd_wait_comp;
 	struct kref		cmd_kref;
-	struct target_core_fabric_ops *se_tfo;
+	const struct target_core_fabric_ops *se_tfo;
 	sense_reason_t		(*execute_cmd)(struct se_cmd *);
 	sense_reason_t		(*execute_rw)(struct se_cmd *, struct scatterlist *,
 					      u32, enum dma_data_direction);
@@ -890,7 +890,7 @@ struct se_portal_group {
 	/* List of TCM sessions associated wth this TPG */
 	struct list_head	tpg_sess_list;
 	/* Pointer to $FABRIC_MOD dependent code */
-	struct target_core_fabric_ops *se_tpg_tfo;
+	const struct target_core_fabric_ops *se_tpg_tfo;
 	struct se_wwn		*se_tpg_wwn;
 	struct config_group	tpg_group;
 	struct config_group	*tpg_default_groups[7];
diff --git a/include/target/target_core_configfs.h b/include/target/target_core_configfs.h
index e080138..25bb04c 100644
--- a/include/target/target_core_configfs.h
+++ b/include/target/target_core_configfs.h
@@ -5,12 +5,6 @@
 #define TARGET_CORE_NAME_MAX_LEN	64
 #define TARGET_FABRIC_NAME_SIZE		32
 
-extern struct target_fabric_configfs *target_fabric_configfs_init(
-				struct module *, const char *);
-extern void target_fabric_configfs_free(struct target_fabric_configfs *);
-extern int target_fabric_configfs_register(struct target_fabric_configfs *);
-extern void target_fabric_configfs_deregister(struct target_fabric_configfs *);
-
 struct target_fabric_configfs_template {
 	struct config_item_type tfc_discovery_cit;
 	struct config_item_type	tfc_wwn_cit;
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index c93cfdf..17c7f5a 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -2,6 +2,8 @@
 #define TARGET_CORE_FABRIC_H
 
 struct target_core_fabric_ops {
+	struct module *module;
+	const char *name;
 	struct configfs_subsystem *tf_subsys;
 	char *(*get_fabric_name)(void);
 	u8 (*get_fabric_proto_ident)(struct se_portal_group *);
@@ -90,8 +92,23 @@ struct target_core_fabric_ops {
 	struct se_node_acl *(*fabric_make_nodeacl)(struct se_portal_group *,
 				struct config_group *, const char *);
 	void (*fabric_drop_nodeacl)(struct se_node_acl *);
+
+	struct configfs_attribute **tfc_discovery_attrs;
+	struct configfs_attribute **tfc_wwn_attrs;
+	struct configfs_attribute **tfc_tpg_base_attrs;
+	struct configfs_attribute **tfc_tpg_np_base_attrs;
+	struct configfs_attribute **tfc_tpg_attrib_attrs;
+	struct configfs_attribute **tfc_tpg_auth_attrs;
+	struct configfs_attribute **tfc_tpg_param_attrs;
+	struct configfs_attribute **tfc_tpg_nacl_base_attrs;
+	struct configfs_attribute **tfc_tpg_nacl_attrib_attrs;
+	struct configfs_attribute **tfc_tpg_nacl_auth_attrs;
+	struct configfs_attribute **tfc_tpg_nacl_param_attrs;
 };
 
+int target_register_template(const struct target_core_fabric_ops *fo);
+void target_unregister_template(const struct target_core_fabric_ops *fo);
+
 struct se_session *transport_init_session(enum target_prot_op);
 int transport_alloc_session_tags(struct se_session *, unsigned int,
 		unsigned int);
@@ -110,7 +127,8 @@ void	transport_deregister_session_configfs(struct se_session *);
 void	transport_deregister_session(struct se_session *);
 
 
-void	transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
+void	transport_init_se_cmd(struct se_cmd *,
+		const struct target_core_fabric_ops *,
 		struct se_session *, u32, int, int, unsigned char *);
 sense_reason_t transport_lookup_cmd_lun(struct se_cmd *, u32);
 sense_reason_t target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
@@ -162,8 +180,8 @@ int	core_tpg_set_initiator_node_queue_depth(struct se_portal_group *,
 		unsigned char *, u32, int);
 int	core_tpg_set_initiator_node_tag(struct se_portal_group *,
 		struct se_node_acl *, const char *);
-int	core_tpg_register(struct target_core_fabric_ops *, struct se_wwn *,
-		struct se_portal_group *, void *, int);
+int	core_tpg_register(const struct target_core_fabric_ops *,
+		struct se_wwn *, struct se_portal_group *, void *, int);
 int	core_tpg_deregister(struct se_portal_group *);
 
 /* SAS helpers */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux