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@sandisk.com>.

(v2: Add a new TF_CIT_SETUP_DRV macro so that the core configfs code
can declare attributes as either core only or for drivers)

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
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 @@
 	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 @@
 	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 @@
 	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 @@
 	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"