1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2c66ac9dbSNicholas Bellinger /*******************************************************************************
3c66ac9dbSNicholas Bellinger * Filename: target_core_fabric_configfs.c
4c66ac9dbSNicholas Bellinger  *
5c66ac9dbSNicholas Bellinger  * This file contains generic fabric module configfs infrastructure for
6c66ac9dbSNicholas Bellinger  * TCM v4.x code
7c66ac9dbSNicholas Bellinger  *
84c76251eSNicholas Bellinger  * (c) Copyright 2010-2013 Datera, Inc.
9c66ac9dbSNicholas Bellinger  *
10fd9a11d7SNicholas Bellinger  * Nicholas A. Bellinger <nab@linux-iscsi.org>
11c66ac9dbSNicholas Bellinger *
12c66ac9dbSNicholas Bellinger  ****************************************************************************/
13c66ac9dbSNicholas Bellinger 
14e56ca6bcSChristophe JAILLET #include <linux/kstrtox.h>
15c66ac9dbSNicholas Bellinger #include <linux/module.h>
16c66ac9dbSNicholas Bellinger #include <linux/moduleparam.h>
17c66ac9dbSNicholas Bellinger #include <linux/utsname.h>
18c66ac9dbSNicholas Bellinger #include <linux/init.h>
19c66ac9dbSNicholas Bellinger #include <linux/fs.h>
20c66ac9dbSNicholas Bellinger #include <linux/namei.h>
21c66ac9dbSNicholas Bellinger #include <linux/slab.h>
22c66ac9dbSNicholas Bellinger #include <linux/types.h>
23c66ac9dbSNicholas Bellinger #include <linux/delay.h>
24c66ac9dbSNicholas Bellinger #include <linux/unistd.h>
25c66ac9dbSNicholas Bellinger #include <linux/string.h>
26c66ac9dbSNicholas Bellinger #include <linux/syscalls.h>
27c66ac9dbSNicholas Bellinger #include <linux/configfs.h>
28c66ac9dbSNicholas Bellinger 
29c66ac9dbSNicholas Bellinger #include <target/target_core_base.h>
30cb0f32e1SMike Christie #include <target/target_core_backend.h>
31c4795fb2SChristoph Hellwig #include <target/target_core_fabric.h>
32c66ac9dbSNicholas Bellinger 
33e26d99aeSChristoph Hellwig #include "target_core_internal.h"
34c66ac9dbSNicholas Bellinger #include "target_core_alua.h"
35c66ac9dbSNicholas Bellinger #include "target_core_pr.h"
36c66ac9dbSNicholas Bellinger 
37c66ac9dbSNicholas Bellinger #define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs)		\
38c66ac9dbSNicholas Bellinger static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
39c66ac9dbSNicholas Bellinger {									\
40968ebe75SChristoph Hellwig 	struct config_item_type *cit = &tf->tf_##_name##_cit;		\
41c66ac9dbSNicholas Bellinger 									\
42c66ac9dbSNicholas Bellinger 	cit->ct_item_ops = _item_ops;					\
43c66ac9dbSNicholas Bellinger 	cit->ct_group_ops = _group_ops;					\
44c66ac9dbSNicholas Bellinger 	cit->ct_attrs = _attrs;						\
450dc2e8d1SChristoph Hellwig 	cit->ct_owner = tf->tf_ops->module;				\
466708bb27SAndy Grover 	pr_debug("Setup generic %s\n", __stringify(_name));		\
47c66ac9dbSNicholas Bellinger }
48c66ac9dbSNicholas Bellinger 
499ac8928eSChristoph Hellwig #define TF_CIT_SETUP_DRV(_name, _item_ops, _group_ops)		\
509ac8928eSChristoph Hellwig static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
519ac8928eSChristoph Hellwig {									\
52968ebe75SChristoph Hellwig 	struct config_item_type *cit = &tf->tf_##_name##_cit;		\
53ef0caf8dSChristoph Hellwig 	struct configfs_attribute **attrs = tf->tf_ops->tfc_##_name##_attrs; \
549ac8928eSChristoph Hellwig 									\
559ac8928eSChristoph Hellwig 	cit->ct_item_ops = _item_ops;					\
569ac8928eSChristoph Hellwig 	cit->ct_group_ops = _group_ops;					\
579ac8928eSChristoph Hellwig 	cit->ct_attrs = attrs;						\
580dc2e8d1SChristoph Hellwig 	cit->ct_owner = tf->tf_ops->module;				\
599ac8928eSChristoph Hellwig 	pr_debug("Setup generic %s\n", __stringify(_name));		\
609ac8928eSChristoph Hellwig }
619ac8928eSChristoph Hellwig 
629ae0e9adSNicholas Bellinger static struct configfs_item_operations target_fabric_port_item_ops;
639ae0e9adSNicholas Bellinger 
64c66ac9dbSNicholas Bellinger /* Start of tfc_tpg_mappedlun_cit */
65c66ac9dbSNicholas Bellinger 
target_fabric_mappedlun_link(struct config_item * lun_acl_ci,struct config_item * lun_ci)66c66ac9dbSNicholas Bellinger static int target_fabric_mappedlun_link(
67c66ac9dbSNicholas Bellinger 	struct config_item *lun_acl_ci,
68c66ac9dbSNicholas Bellinger 	struct config_item *lun_ci)
69c66ac9dbSNicholas Bellinger {
70c66ac9dbSNicholas Bellinger 	struct se_dev_entry *deve;
719ae0e9adSNicholas Bellinger 	struct se_lun *lun;
72c66ac9dbSNicholas Bellinger 	struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),
73c66ac9dbSNicholas Bellinger 			struct se_lun_acl, se_lun_group);
74c66ac9dbSNicholas Bellinger 	struct se_portal_group *se_tpg;
75c66ac9dbSNicholas Bellinger 	struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s;
7603a68b44SAndy Grover 	bool lun_access_ro;
770ff87549SNicholas Bellinger 
789ae0e9adSNicholas Bellinger 	if (!lun_ci->ci_type ||
799ae0e9adSNicholas Bellinger 	    lun_ci->ci_type->ct_item_ops != &target_fabric_port_item_ops) {
809ae0e9adSNicholas Bellinger 		pr_err("Bad lun_ci, not a valid lun_ci pointer: %p\n", lun_ci);
810ff87549SNicholas Bellinger 		return -EFAULT;
820ff87549SNicholas Bellinger 	}
839ae0e9adSNicholas Bellinger 	lun = container_of(to_config_group(lun_ci), struct se_lun, lun_group);
849ae0e9adSNicholas Bellinger 
85c66ac9dbSNicholas Bellinger 	/*
86c66ac9dbSNicholas Bellinger 	 * Ensure that the source port exists
87c66ac9dbSNicholas Bellinger 	 */
88adf653f9SChristoph Hellwig 	if (!lun->lun_se_dev) {
89adf653f9SChristoph Hellwig 		pr_err("Source se_lun->lun_se_dev does not exist\n");
90c66ac9dbSNicholas Bellinger 		return -EINVAL;
91c66ac9dbSNicholas Bellinger 	}
9249cb77e2SNicholas Bellinger 	if (lun->lun_shutdown) {
9349cb77e2SNicholas Bellinger 		pr_err("Unable to create mappedlun symlink because"
9449cb77e2SNicholas Bellinger 			" lun->lun_shutdown=true\n");
9549cb77e2SNicholas Bellinger 		return -EINVAL;
9649cb77e2SNicholas Bellinger 	}
97adf653f9SChristoph Hellwig 	se_tpg = lun->lun_tpg;
98c66ac9dbSNicholas Bellinger 
99c66ac9dbSNicholas Bellinger 	nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item;
100c66ac9dbSNicholas Bellinger 	tpg_ci = &nacl_ci->ci_group->cg_item;
101c66ac9dbSNicholas Bellinger 	wwn_ci = &tpg_ci->ci_group->cg_item;
102c66ac9dbSNicholas Bellinger 	tpg_ci_s = &lun_ci->ci_parent->ci_group->cg_item;
103c66ac9dbSNicholas Bellinger 	wwn_ci_s = &tpg_ci_s->ci_group->cg_item;
104c66ac9dbSNicholas Bellinger 	/*
105c66ac9dbSNicholas Bellinger 	 * Make sure the SymLink is going to the same $FABRIC/$WWN/tpgt_$TPGT
106c66ac9dbSNicholas Bellinger 	 */
107c66ac9dbSNicholas Bellinger 	if (strcmp(config_item_name(wwn_ci), config_item_name(wwn_ci_s))) {
1086708bb27SAndy Grover 		pr_err("Illegal Initiator ACL SymLink outside of %s\n",
109c66ac9dbSNicholas Bellinger 			config_item_name(wwn_ci));
110c66ac9dbSNicholas Bellinger 		return -EINVAL;
111c66ac9dbSNicholas Bellinger 	}
112c66ac9dbSNicholas Bellinger 	if (strcmp(config_item_name(tpg_ci), config_item_name(tpg_ci_s))) {
1136708bb27SAndy Grover 		pr_err("Illegal Initiator ACL Symlink outside of %s"
114c66ac9dbSNicholas Bellinger 			" TPGT: %s\n", config_item_name(wwn_ci),
115c66ac9dbSNicholas Bellinger 			config_item_name(tpg_ci));
116c66ac9dbSNicholas Bellinger 		return -EINVAL;
117c66ac9dbSNicholas Bellinger 	}
118c66ac9dbSNicholas Bellinger 	/*
119c66ac9dbSNicholas Bellinger 	 * If this struct se_node_acl was dynamically generated with
12003a68b44SAndy Grover 	 * tpg_1/attrib/generate_node_acls=1, use the existing
12103a68b44SAndy Grover 	 * deve->lun_access_ro value, which will be true when
122c66ac9dbSNicholas Bellinger 	 * tpg_1/attrib/demo_mode_write_protect=1
123c66ac9dbSNicholas Bellinger 	 */
12429a05deeSNicholas Bellinger 	rcu_read_lock();
12529a05deeSNicholas Bellinger 	deve = target_nacl_find_deve(lacl->se_lun_nacl, lacl->mapped_lun);
12629a05deeSNicholas Bellinger 	if (deve)
12703a68b44SAndy Grover 		lun_access_ro = deve->lun_access_ro;
128c66ac9dbSNicholas Bellinger 	else
12903a68b44SAndy Grover 		lun_access_ro =
130e3d6f909SAndy Grover 			(se_tpg->se_tpg_tfo->tpg_check_prod_mode_write_protect(
13103a68b44SAndy Grover 				se_tpg)) ? true : false;
13229a05deeSNicholas Bellinger 	rcu_read_unlock();
133c66ac9dbSNicholas Bellinger 	/*
134c66ac9dbSNicholas Bellinger 	 * Determine the actual mapped LUN value user wants..
135c66ac9dbSNicholas Bellinger 	 *
136c66ac9dbSNicholas Bellinger 	 * This value is what the SCSI Initiator actually sees the
1376bb82612SNicholas Bellinger 	 * $FABRIC/$WWPN/$TPGT/lun/lun_* as on their SCSI Initiator Ports.
138c66ac9dbSNicholas Bellinger 	 */
13903a68b44SAndy Grover 	return core_dev_add_initiator_node_lun_acl(se_tpg, lacl, lun, lun_access_ro);
140c66ac9dbSNicholas Bellinger }
141c66ac9dbSNicholas Bellinger 
target_fabric_mappedlun_unlink(struct config_item * lun_acl_ci,struct config_item * lun_ci)142e16769d4SAndrzej Pietrasiewicz static void target_fabric_mappedlun_unlink(
143c66ac9dbSNicholas Bellinger 	struct config_item *lun_acl_ci,
144c66ac9dbSNicholas Bellinger 	struct config_item *lun_ci)
145c66ac9dbSNicholas Bellinger {
146c66ac9dbSNicholas Bellinger 	struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),
147c66ac9dbSNicholas Bellinger 			struct se_lun_acl, se_lun_group);
14829a05deeSNicholas Bellinger 	struct se_lun *lun = container_of(to_config_group(lun_ci),
14929a05deeSNicholas Bellinger 			struct se_lun, lun_group);
150c66ac9dbSNicholas Bellinger 
151e16769d4SAndrzej Pietrasiewicz 	core_dev_del_initiator_node_lun_acl(lun, lacl);
152c66ac9dbSNicholas Bellinger }
153c66ac9dbSNicholas Bellinger 
item_to_lun_acl(struct config_item * item)1542eafd729SChristoph Hellwig static struct se_lun_acl *item_to_lun_acl(struct config_item *item)
155c66ac9dbSNicholas Bellinger {
1562eafd729SChristoph Hellwig 	return container_of(to_config_group(item), struct se_lun_acl,
1572eafd729SChristoph Hellwig 			se_lun_group);
1582eafd729SChristoph Hellwig }
1592eafd729SChristoph Hellwig 
target_fabric_mappedlun_write_protect_show(struct config_item * item,char * page)1602eafd729SChristoph Hellwig static ssize_t target_fabric_mappedlun_write_protect_show(
1612eafd729SChristoph Hellwig 		struct config_item *item, char *page)
1622eafd729SChristoph Hellwig {
1632eafd729SChristoph Hellwig 	struct se_lun_acl *lacl = item_to_lun_acl(item);
164c66ac9dbSNicholas Bellinger 	struct se_node_acl *se_nacl = lacl->se_lun_nacl;
165c66ac9dbSNicholas Bellinger 	struct se_dev_entry *deve;
16629a05deeSNicholas Bellinger 	ssize_t len = 0;
167c66ac9dbSNicholas Bellinger 
16829a05deeSNicholas Bellinger 	rcu_read_lock();
16929a05deeSNicholas Bellinger 	deve = target_nacl_find_deve(se_nacl, lacl->mapped_lun);
17029a05deeSNicholas Bellinger 	if (deve) {
17103a68b44SAndy Grover 		len = sprintf(page, "%d\n", deve->lun_access_ro);
17229a05deeSNicholas Bellinger 	}
17329a05deeSNicholas Bellinger 	rcu_read_unlock();
174c66ac9dbSNicholas Bellinger 
175c66ac9dbSNicholas Bellinger 	return len;
176c66ac9dbSNicholas Bellinger }
177c66ac9dbSNicholas Bellinger 
target_fabric_mappedlun_write_protect_store(struct config_item * item,const char * page,size_t count)1782eafd729SChristoph Hellwig static ssize_t target_fabric_mappedlun_write_protect_store(
1792eafd729SChristoph Hellwig 		struct config_item *item, const char *page, size_t count)
180c66ac9dbSNicholas Bellinger {
1812eafd729SChristoph Hellwig 	struct se_lun_acl *lacl = item_to_lun_acl(item);
182c66ac9dbSNicholas Bellinger 	struct se_node_acl *se_nacl = lacl->se_lun_nacl;
183c66ac9dbSNicholas Bellinger 	struct se_portal_group *se_tpg = se_nacl->se_tpg;
18403a68b44SAndy Grover 	unsigned long wp;
18557103d7fSJingoo Han 	int ret;
186c66ac9dbSNicholas Bellinger 
18703a68b44SAndy Grover 	ret = kstrtoul(page, 0, &wp);
18857103d7fSJingoo Han 	if (ret)
18957103d7fSJingoo Han 		return ret;
190c66ac9dbSNicholas Bellinger 
19103a68b44SAndy Grover 	if ((wp != 1) && (wp != 0))
192c66ac9dbSNicholas Bellinger 		return -EINVAL;
193c66ac9dbSNicholas Bellinger 
19403a68b44SAndy Grover 	/* wp=1 means lun_access_ro=true */
19503a68b44SAndy Grover 	core_update_device_list_access(lacl->mapped_lun, wp, lacl->se_lun_nacl);
196c66ac9dbSNicholas Bellinger 
1976708bb27SAndy Grover 	pr_debug("%s_ConfigFS: Changed Initiator ACL: %s"
198f2d30680SHannes Reinecke 		" Mapped LUN: %llu Write Protect bit to %s\n",
19930c7ca93SDavid Disseldorp 		se_tpg->se_tpg_tfo->fabric_name,
20003a68b44SAndy Grover 		se_nacl->initiatorname, lacl->mapped_lun, (wp) ? "ON" : "OFF");
201c66ac9dbSNicholas Bellinger 
202c66ac9dbSNicholas Bellinger 	return count;
203c66ac9dbSNicholas Bellinger 
204c66ac9dbSNicholas Bellinger }
205c66ac9dbSNicholas Bellinger 
2062eafd729SChristoph Hellwig CONFIGFS_ATTR(target_fabric_mappedlun_, write_protect);
207c66ac9dbSNicholas Bellinger 
2082eafd729SChristoph Hellwig static struct configfs_attribute *target_fabric_mappedlun_attrs[] = {
2092eafd729SChristoph Hellwig 	&target_fabric_mappedlun_attr_write_protect,
2102eafd729SChristoph Hellwig 	NULL,
2112eafd729SChristoph Hellwig };
212c66ac9dbSNicholas Bellinger 
target_fabric_mappedlun_release(struct config_item * item)2131f6fe7cbSNicholas Bellinger static void target_fabric_mappedlun_release(struct config_item *item)
2141f6fe7cbSNicholas Bellinger {
2151f6fe7cbSNicholas Bellinger 	struct se_lun_acl *lacl = container_of(to_config_group(item),
2161f6fe7cbSNicholas Bellinger 				struct se_lun_acl, se_lun_group);
2171f6fe7cbSNicholas Bellinger 	struct se_portal_group *se_tpg = lacl->se_lun_nacl->se_tpg;
2181f6fe7cbSNicholas Bellinger 
2191f6fe7cbSNicholas Bellinger 	core_dev_free_initiator_node_lun_acl(se_tpg, lacl);
2201f6fe7cbSNicholas Bellinger }
2211f6fe7cbSNicholas Bellinger 
222c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_fabric_mappedlun_item_ops = {
2231f6fe7cbSNicholas Bellinger 	.release		= target_fabric_mappedlun_release,
224c66ac9dbSNicholas Bellinger 	.allow_link		= target_fabric_mappedlun_link,
225c66ac9dbSNicholas Bellinger 	.drop_link		= target_fabric_mappedlun_unlink,
226c66ac9dbSNicholas Bellinger };
227c66ac9dbSNicholas Bellinger 
228c66ac9dbSNicholas Bellinger TF_CIT_SETUP(tpg_mappedlun, &target_fabric_mappedlun_item_ops, NULL,
229c66ac9dbSNicholas Bellinger 		target_fabric_mappedlun_attrs);
230c66ac9dbSNicholas Bellinger 
231c66ac9dbSNicholas Bellinger /* End of tfc_tpg_mappedlun_cit */
232c66ac9dbSNicholas Bellinger 
23312d23384SNicholas Bellinger /* Start of tfc_tpg_mappedlun_port_cit */
23412d23384SNicholas Bellinger 
target_core_mappedlun_stat_mkdir(struct config_group * group,const char * name)23512d23384SNicholas Bellinger static struct config_group *target_core_mappedlun_stat_mkdir(
23612d23384SNicholas Bellinger 	struct config_group *group,
23712d23384SNicholas Bellinger 	const char *name)
23812d23384SNicholas Bellinger {
23912d23384SNicholas Bellinger 	return ERR_PTR(-ENOSYS);
24012d23384SNicholas Bellinger }
24112d23384SNicholas Bellinger 
target_core_mappedlun_stat_rmdir(struct config_group * group,struct config_item * item)24212d23384SNicholas Bellinger static void target_core_mappedlun_stat_rmdir(
24312d23384SNicholas Bellinger 	struct config_group *group,
24412d23384SNicholas Bellinger 	struct config_item *item)
24512d23384SNicholas Bellinger {
24612d23384SNicholas Bellinger 	return;
24712d23384SNicholas Bellinger }
24812d23384SNicholas Bellinger 
24912d23384SNicholas Bellinger static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = {
25012d23384SNicholas Bellinger 	.make_group		= target_core_mappedlun_stat_mkdir,
25112d23384SNicholas Bellinger 	.drop_item		= target_core_mappedlun_stat_rmdir,
25212d23384SNicholas Bellinger };
25312d23384SNicholas Bellinger 
25412d23384SNicholas Bellinger TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops,
25512d23384SNicholas Bellinger 		NULL);
25612d23384SNicholas Bellinger 
25712d23384SNicholas Bellinger /* End of tfc_tpg_mappedlun_port_cit */
25812d23384SNicholas Bellinger 
2592eafd729SChristoph Hellwig TF_CIT_SETUP_DRV(tpg_nacl_attrib, NULL, NULL);
2602eafd729SChristoph Hellwig TF_CIT_SETUP_DRV(tpg_nacl_auth, NULL, NULL);
2612eafd729SChristoph Hellwig TF_CIT_SETUP_DRV(tpg_nacl_param, NULL, NULL);
262c66ac9dbSNicholas Bellinger 
263c66ac9dbSNicholas Bellinger /* Start of tfc_tpg_nacl_base_cit */
264c66ac9dbSNicholas Bellinger 
target_fabric_make_mappedlun(struct config_group * group,const char * name)265c66ac9dbSNicholas Bellinger static struct config_group *target_fabric_make_mappedlun(
266c66ac9dbSNicholas Bellinger 	struct config_group *group,
267c66ac9dbSNicholas Bellinger 	const char *name)
268c66ac9dbSNicholas Bellinger {
269c66ac9dbSNicholas Bellinger 	struct se_node_acl *se_nacl = container_of(group,
270c66ac9dbSNicholas Bellinger 			struct se_node_acl, acl_group);
271c66ac9dbSNicholas Bellinger 	struct se_portal_group *se_tpg = se_nacl->se_tpg;
272c66ac9dbSNicholas Bellinger 	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
273da0abaeeSJoern Engel 	struct se_lun_acl *lacl = NULL;
274c66ac9dbSNicholas Bellinger 	char *buf;
275f2d30680SHannes Reinecke 	unsigned long long mapped_lun;
276c66ac9dbSNicholas Bellinger 	int ret = 0;
277c66ac9dbSNicholas Bellinger 
278c66ac9dbSNicholas Bellinger 	buf = kzalloc(strlen(name) + 1, GFP_KERNEL);
2796708bb27SAndy Grover 	if (!buf) {
2806708bb27SAndy Grover 		pr_err("Unable to allocate memory for name buf\n");
281c66ac9dbSNicholas Bellinger 		return ERR_PTR(-ENOMEM);
282c66ac9dbSNicholas Bellinger 	}
283c66ac9dbSNicholas Bellinger 	snprintf(buf, strlen(name) + 1, "%s", name);
284c66ac9dbSNicholas Bellinger 	/*
285c66ac9dbSNicholas Bellinger 	 * Make sure user is creating iscsi/$IQN/$TPGT/acls/$INITIATOR/lun_$ID.
286c66ac9dbSNicholas Bellinger 	 */
287c66ac9dbSNicholas Bellinger 	if (strstr(buf, "lun_") != buf) {
2886708bb27SAndy Grover 		pr_err("Unable to locate \"lun_\" from buf: %s"
289c66ac9dbSNicholas Bellinger 			" name: %s\n", buf, name);
290c66ac9dbSNicholas Bellinger 		ret = -EINVAL;
291c66ac9dbSNicholas Bellinger 		goto out;
292c66ac9dbSNicholas Bellinger 	}
293c66ac9dbSNicholas Bellinger 	/*
294c66ac9dbSNicholas Bellinger 	 * Determine the Mapped LUN value.  This is what the SCSI Initiator
295c66ac9dbSNicholas Bellinger 	 * Port will actually see.
296c66ac9dbSNicholas Bellinger 	 */
297f2d30680SHannes Reinecke 	ret = kstrtoull(buf + 4, 0, &mapped_lun);
29857103d7fSJingoo Han 	if (ret)
29957103d7fSJingoo Han 		goto out;
300c66ac9dbSNicholas Bellinger 
301fcf29481SNicholas Bellinger 	lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl,
302fcf29481SNicholas Bellinger 			mapped_lun, &ret);
3036708bb27SAndy Grover 	if (!lacl) {
30412d23384SNicholas Bellinger 		ret = -EINVAL;
305c66ac9dbSNicholas Bellinger 		goto out;
30612d23384SNicholas Bellinger 	}
30712d23384SNicholas Bellinger 
308c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&lacl->se_lun_group, name,
309968ebe75SChristoph Hellwig 			&tf->tf_tpg_mappedlun_cit);
3101ae1602dSChristoph Hellwig 
31112d23384SNicholas Bellinger 	config_group_init_type_name(&lacl->ml_stat_grps.stat_group,
312968ebe75SChristoph Hellwig 			"statistics", &tf->tf_tpg_mappedlun_stat_cit);
3131ae1602dSChristoph Hellwig 	configfs_add_default_group(&lacl->ml_stat_grps.stat_group,
3141ae1602dSChristoph Hellwig 			&lacl->se_lun_group);
31512d23384SNicholas Bellinger 
31612d23384SNicholas Bellinger 	target_stat_setup_mappedlun_default_groups(lacl);
317c66ac9dbSNicholas Bellinger 
318c66ac9dbSNicholas Bellinger 	kfree(buf);
319c66ac9dbSNicholas Bellinger 	return &lacl->se_lun_group;
320c66ac9dbSNicholas Bellinger out:
321da0abaeeSJoern Engel 	kfree(lacl);
322c66ac9dbSNicholas Bellinger 	kfree(buf);
323c66ac9dbSNicholas Bellinger 	return ERR_PTR(ret);
324c66ac9dbSNicholas Bellinger }
325c66ac9dbSNicholas Bellinger 
target_fabric_drop_mappedlun(struct config_group * group,struct config_item * item)326c66ac9dbSNicholas Bellinger static void target_fabric_drop_mappedlun(
327c66ac9dbSNicholas Bellinger 	struct config_group *group,
328c66ac9dbSNicholas Bellinger 	struct config_item *item)
329c66ac9dbSNicholas Bellinger {
33012d23384SNicholas Bellinger 	struct se_lun_acl *lacl = container_of(to_config_group(item),
33112d23384SNicholas Bellinger 			struct se_lun_acl, se_lun_group);
33212d23384SNicholas Bellinger 
3331ae1602dSChristoph Hellwig 	configfs_remove_default_groups(&lacl->ml_stat_grps.stat_group);
3341ae1602dSChristoph Hellwig 	configfs_remove_default_groups(&lacl->se_lun_group);
33512d23384SNicholas Bellinger 
336c66ac9dbSNicholas Bellinger 	config_item_put(item);
3371f6fe7cbSNicholas Bellinger }
3381f6fe7cbSNicholas Bellinger 
target_fabric_nacl_base_release(struct config_item * item)3391f6fe7cbSNicholas Bellinger static void target_fabric_nacl_base_release(struct config_item *item)
3401f6fe7cbSNicholas Bellinger {
3411f6fe7cbSNicholas Bellinger 	struct se_node_acl *se_nacl = container_of(to_config_group(item),
3421f6fe7cbSNicholas Bellinger 			struct se_node_acl, acl_group);
3431f6fe7cbSNicholas Bellinger 
344ce7043fdSChristoph Hellwig 	configfs_remove_default_groups(&se_nacl->acl_fabric_stat_group);
345c7d6a803SChristoph Hellwig 	core_tpg_del_initiator_node_acl(se_nacl);
346c66ac9dbSNicholas Bellinger }
347c66ac9dbSNicholas Bellinger 
348c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_fabric_nacl_base_item_ops = {
3491f6fe7cbSNicholas Bellinger 	.release		= target_fabric_nacl_base_release,
350c66ac9dbSNicholas Bellinger };
351c66ac9dbSNicholas Bellinger 
352c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_fabric_nacl_base_group_ops = {
353c66ac9dbSNicholas Bellinger 	.make_group		= target_fabric_make_mappedlun,
354c66ac9dbSNicholas Bellinger 	.drop_item		= target_fabric_drop_mappedlun,
355c66ac9dbSNicholas Bellinger };
356c66ac9dbSNicholas Bellinger 
3579ac8928eSChristoph Hellwig TF_CIT_SETUP_DRV(tpg_nacl_base, &target_fabric_nacl_base_item_ops,
3589ac8928eSChristoph Hellwig 		&target_fabric_nacl_base_group_ops);
359c66ac9dbSNicholas Bellinger 
360c66ac9dbSNicholas Bellinger /* End of tfc_tpg_nacl_base_cit */
361c66ac9dbSNicholas Bellinger 
36212d23384SNicholas Bellinger /* Start of tfc_node_fabric_stats_cit */
36312d23384SNicholas Bellinger /*
36412d23384SNicholas Bellinger  * This is used as a placeholder for struct se_node_acl->acl_fabric_stat_group
36512d23384SNicholas Bellinger  * to allow fabrics access to ->acl_fabric_stat_group->default_groups[]
36612d23384SNicholas Bellinger  */
36712d23384SNicholas Bellinger TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL);
36812d23384SNicholas Bellinger 
36912d23384SNicholas Bellinger /* End of tfc_wwn_fabric_stats_cit */
37012d23384SNicholas Bellinger 
371c66ac9dbSNicholas Bellinger /* Start of tfc_tpg_nacl_cit */
372c66ac9dbSNicholas Bellinger 
target_fabric_make_nodeacl(struct config_group * group,const char * name)373c66ac9dbSNicholas Bellinger static struct config_group *target_fabric_make_nodeacl(
374c66ac9dbSNicholas Bellinger 	struct config_group *group,
375c66ac9dbSNicholas Bellinger 	const char *name)
376c66ac9dbSNicholas Bellinger {
377c66ac9dbSNicholas Bellinger 	struct se_portal_group *se_tpg = container_of(group,
378c66ac9dbSNicholas Bellinger 			struct se_portal_group, tpg_acl_group);
379c66ac9dbSNicholas Bellinger 	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
380c66ac9dbSNicholas Bellinger 	struct se_node_acl *se_nacl;
381c66ac9dbSNicholas Bellinger 
382c7d6a803SChristoph Hellwig 	se_nacl = core_tpg_add_initiator_node_acl(se_tpg, name);
383c66ac9dbSNicholas Bellinger 	if (IS_ERR(se_nacl))
384e1750ba2SThomas Meyer 		return ERR_CAST(se_nacl);
385c66ac9dbSNicholas Bellinger 
386c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_nacl->acl_group, name,
387968ebe75SChristoph Hellwig 			&tf->tf_tpg_nacl_base_cit);
3881ae1602dSChristoph Hellwig 
389c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_nacl->acl_attrib_group, "attrib",
390968ebe75SChristoph Hellwig 			&tf->tf_tpg_nacl_attrib_cit);
3911ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_nacl->acl_attrib_group,
3921ae1602dSChristoph Hellwig 			&se_nacl->acl_group);
3931ae1602dSChristoph Hellwig 
394c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_nacl->acl_auth_group, "auth",
395968ebe75SChristoph Hellwig 			&tf->tf_tpg_nacl_auth_cit);
3961ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_nacl->acl_auth_group,
3971ae1602dSChristoph Hellwig 			&se_nacl->acl_group);
3981ae1602dSChristoph Hellwig 
399c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_nacl->acl_param_group, "param",
400968ebe75SChristoph Hellwig 			&tf->tf_tpg_nacl_param_cit);
4011ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_nacl->acl_param_group,
4021ae1602dSChristoph Hellwig 			&se_nacl->acl_group);
4031ae1602dSChristoph Hellwig 
40412d23384SNicholas Bellinger 	config_group_init_type_name(&se_nacl->acl_fabric_stat_group,
405968ebe75SChristoph Hellwig 			"fabric_statistics", &tf->tf_tpg_nacl_stat_cit);
4061ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_nacl->acl_fabric_stat_group,
4071ae1602dSChristoph Hellwig 			&se_nacl->acl_group);
408c66ac9dbSNicholas Bellinger 
409e6e202edSChristoph Hellwig 	if (tf->tf_ops->fabric_init_nodeacl) {
410e6e202edSChristoph Hellwig 		int ret = tf->tf_ops->fabric_init_nodeacl(se_nacl, name);
411e6e202edSChristoph Hellwig 		if (ret) {
412e6e202edSChristoph Hellwig 			configfs_remove_default_groups(&se_nacl->acl_fabric_stat_group);
413e6e202edSChristoph Hellwig 			core_tpg_del_initiator_node_acl(se_nacl);
414e6e202edSChristoph Hellwig 			return ERR_PTR(ret);
415e6e202edSChristoph Hellwig 		}
416e6e202edSChristoph Hellwig 	}
417e6e202edSChristoph Hellwig 
418c66ac9dbSNicholas Bellinger 	return &se_nacl->acl_group;
419c66ac9dbSNicholas Bellinger }
420c66ac9dbSNicholas Bellinger 
target_fabric_drop_nodeacl(struct config_group * group,struct config_item * item)421c66ac9dbSNicholas Bellinger static void target_fabric_drop_nodeacl(
422c66ac9dbSNicholas Bellinger 	struct config_group *group,
423c66ac9dbSNicholas Bellinger 	struct config_item *item)
424c66ac9dbSNicholas Bellinger {
425c66ac9dbSNicholas Bellinger 	struct se_node_acl *se_nacl = container_of(to_config_group(item),
426c66ac9dbSNicholas Bellinger 			struct se_node_acl, acl_group);
427c66ac9dbSNicholas Bellinger 
4281ae1602dSChristoph Hellwig 	configfs_remove_default_groups(&se_nacl->acl_group);
4291ae1602dSChristoph Hellwig 
4301f6fe7cbSNicholas Bellinger 	/*
4311f6fe7cbSNicholas Bellinger 	 * struct se_node_acl free is done in target_fabric_nacl_base_release()
4321f6fe7cbSNicholas Bellinger 	 */
433c66ac9dbSNicholas Bellinger 	config_item_put(item);
434c66ac9dbSNicholas Bellinger }
435c66ac9dbSNicholas Bellinger 
436c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_fabric_nacl_group_ops = {
437c66ac9dbSNicholas Bellinger 	.make_group	= target_fabric_make_nodeacl,
438c66ac9dbSNicholas Bellinger 	.drop_item	= target_fabric_drop_nodeacl,
439c66ac9dbSNicholas Bellinger };
440c66ac9dbSNicholas Bellinger 
441c66ac9dbSNicholas Bellinger TF_CIT_SETUP(tpg_nacl, NULL, &target_fabric_nacl_group_ops, NULL);
442c66ac9dbSNicholas Bellinger 
443c66ac9dbSNicholas Bellinger /* End of tfc_tpg_nacl_cit */
444c66ac9dbSNicholas Bellinger 
445c66ac9dbSNicholas Bellinger /* Start of tfc_tpg_np_base_cit */
446c66ac9dbSNicholas Bellinger 
target_fabric_np_base_release(struct config_item * item)4471f6fe7cbSNicholas Bellinger static void target_fabric_np_base_release(struct config_item *item)
4481f6fe7cbSNicholas Bellinger {
4491f6fe7cbSNicholas Bellinger 	struct se_tpg_np *se_tpg_np = container_of(to_config_group(item),
4501f6fe7cbSNicholas Bellinger 				struct se_tpg_np, tpg_np_group);
4511f6fe7cbSNicholas Bellinger 	struct se_portal_group *se_tpg = se_tpg_np->tpg_np_parent;
4521f6fe7cbSNicholas Bellinger 	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
4531f6fe7cbSNicholas Bellinger 
454ef0caf8dSChristoph Hellwig 	tf->tf_ops->fabric_drop_np(se_tpg_np);
4551f6fe7cbSNicholas Bellinger }
4561f6fe7cbSNicholas Bellinger 
457c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_fabric_np_base_item_ops = {
4581f6fe7cbSNicholas Bellinger 	.release		= target_fabric_np_base_release,
459c66ac9dbSNicholas Bellinger };
460c66ac9dbSNicholas Bellinger 
4619ac8928eSChristoph Hellwig TF_CIT_SETUP_DRV(tpg_np_base, &target_fabric_np_base_item_ops, NULL);
462c66ac9dbSNicholas Bellinger 
463c66ac9dbSNicholas Bellinger /* End of tfc_tpg_np_base_cit */
464c66ac9dbSNicholas Bellinger 
465c66ac9dbSNicholas Bellinger /* Start of tfc_tpg_np_cit */
466c66ac9dbSNicholas Bellinger 
target_fabric_make_np(struct config_group * group,const char * name)467c66ac9dbSNicholas Bellinger static struct config_group *target_fabric_make_np(
468c66ac9dbSNicholas Bellinger 	struct config_group *group,
469c66ac9dbSNicholas Bellinger 	const char *name)
470c66ac9dbSNicholas Bellinger {
471c66ac9dbSNicholas Bellinger 	struct se_portal_group *se_tpg = container_of(group,
472c66ac9dbSNicholas Bellinger 				struct se_portal_group, tpg_np_group);
473c66ac9dbSNicholas Bellinger 	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
474c66ac9dbSNicholas Bellinger 	struct se_tpg_np *se_tpg_np;
475c66ac9dbSNicholas Bellinger 
476ef0caf8dSChristoph Hellwig 	if (!tf->tf_ops->fabric_make_np) {
4776708bb27SAndy Grover 		pr_err("tf->tf_ops.fabric_make_np is NULL\n");
478c66ac9dbSNicholas Bellinger 		return ERR_PTR(-ENOSYS);
479c66ac9dbSNicholas Bellinger 	}
480c66ac9dbSNicholas Bellinger 
481ef0caf8dSChristoph Hellwig 	se_tpg_np = tf->tf_ops->fabric_make_np(se_tpg, group, name);
4826708bb27SAndy Grover 	if (!se_tpg_np || IS_ERR(se_tpg_np))
483c66ac9dbSNicholas Bellinger 		return ERR_PTR(-EINVAL);
484c66ac9dbSNicholas Bellinger 
4851f6fe7cbSNicholas Bellinger 	se_tpg_np->tpg_np_parent = se_tpg;
486c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_tpg_np->tpg_np_group, name,
487968ebe75SChristoph Hellwig 			&tf->tf_tpg_np_base_cit);
488c66ac9dbSNicholas Bellinger 
489c66ac9dbSNicholas Bellinger 	return &se_tpg_np->tpg_np_group;
490c66ac9dbSNicholas Bellinger }
491c66ac9dbSNicholas Bellinger 
target_fabric_drop_np(struct config_group * group,struct config_item * item)492c66ac9dbSNicholas Bellinger static void target_fabric_drop_np(
493c66ac9dbSNicholas Bellinger 	struct config_group *group,
494c66ac9dbSNicholas Bellinger 	struct config_item *item)
495c66ac9dbSNicholas Bellinger {
4961f6fe7cbSNicholas Bellinger 	/*
4971f6fe7cbSNicholas Bellinger 	 * struct se_tpg_np is released via target_fabric_np_base_release()
4981f6fe7cbSNicholas Bellinger 	 */
499c66ac9dbSNicholas Bellinger 	config_item_put(item);
500c66ac9dbSNicholas Bellinger }
501c66ac9dbSNicholas Bellinger 
502c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_fabric_np_group_ops = {
503c66ac9dbSNicholas Bellinger 	.make_group	= &target_fabric_make_np,
504c66ac9dbSNicholas Bellinger 	.drop_item	= &target_fabric_drop_np,
505c66ac9dbSNicholas Bellinger };
506c66ac9dbSNicholas Bellinger 
507c66ac9dbSNicholas Bellinger TF_CIT_SETUP(tpg_np, NULL, &target_fabric_np_group_ops, NULL);
508c66ac9dbSNicholas Bellinger 
509c66ac9dbSNicholas Bellinger /* End of tfc_tpg_np_cit */
510c66ac9dbSNicholas Bellinger 
511c66ac9dbSNicholas Bellinger /* Start of tfc_tpg_port_cit */
512c66ac9dbSNicholas Bellinger 
item_to_lun(struct config_item * item)5132eafd729SChristoph Hellwig static struct se_lun *item_to_lun(struct config_item *item)
5142eafd729SChristoph Hellwig {
5152eafd729SChristoph Hellwig 	return container_of(to_config_group(item), struct se_lun,
5162eafd729SChristoph Hellwig 			lun_group);
5172eafd729SChristoph Hellwig }
518c66ac9dbSNicholas Bellinger 
target_fabric_port_alua_tg_pt_gp_show(struct config_item * item,char * page)5192eafd729SChristoph Hellwig static ssize_t target_fabric_port_alua_tg_pt_gp_show(struct config_item *item,
520c66ac9dbSNicholas Bellinger 		char *page)
521c66ac9dbSNicholas Bellinger {
5222eafd729SChristoph Hellwig 	struct se_lun *lun = item_to_lun(item);
5232eafd729SChristoph Hellwig 
5249c6603e1SDan Carpenter 	if (!lun->lun_se_dev)
525c66ac9dbSNicholas Bellinger 		return -ENODEV;
526c66ac9dbSNicholas Bellinger 
527adf653f9SChristoph Hellwig 	return core_alua_show_tg_pt_gp_info(lun, page);
528c66ac9dbSNicholas Bellinger }
529c66ac9dbSNicholas Bellinger 
target_fabric_port_alua_tg_pt_gp_store(struct config_item * item,const char * page,size_t count)5302eafd729SChristoph Hellwig static ssize_t target_fabric_port_alua_tg_pt_gp_store(struct config_item *item,
5312eafd729SChristoph Hellwig 		const char *page, size_t count)
532c66ac9dbSNicholas Bellinger {
5332eafd729SChristoph Hellwig 	struct se_lun *lun = item_to_lun(item);
5342eafd729SChristoph Hellwig 
5359c6603e1SDan Carpenter 	if (!lun->lun_se_dev)
536c66ac9dbSNicholas Bellinger 		return -ENODEV;
537c66ac9dbSNicholas Bellinger 
538adf653f9SChristoph Hellwig 	return core_alua_store_tg_pt_gp_info(lun, page, count);
539c66ac9dbSNicholas Bellinger }
540c66ac9dbSNicholas Bellinger 
target_fabric_port_alua_tg_pt_offline_show(struct config_item * item,char * page)5412eafd729SChristoph Hellwig static ssize_t target_fabric_port_alua_tg_pt_offline_show(
5422eafd729SChristoph Hellwig 		struct config_item *item, char *page)
543c66ac9dbSNicholas Bellinger {
5442eafd729SChristoph Hellwig 	struct se_lun *lun = item_to_lun(item);
5452eafd729SChristoph Hellwig 
5469c6603e1SDan Carpenter 	if (!lun->lun_se_dev)
547c66ac9dbSNicholas Bellinger 		return -ENODEV;
548c66ac9dbSNicholas Bellinger 
549c66ac9dbSNicholas Bellinger 	return core_alua_show_offline_bit(lun, page);
550c66ac9dbSNicholas Bellinger }
551c66ac9dbSNicholas Bellinger 
target_fabric_port_alua_tg_pt_offline_store(struct config_item * item,const char * page,size_t count)5522eafd729SChristoph Hellwig static ssize_t target_fabric_port_alua_tg_pt_offline_store(
5532eafd729SChristoph Hellwig 		struct config_item *item, const char *page, size_t count)
554c66ac9dbSNicholas Bellinger {
5552eafd729SChristoph Hellwig 	struct se_lun *lun = item_to_lun(item);
5562eafd729SChristoph Hellwig 
5579c6603e1SDan Carpenter 	if (!lun->lun_se_dev)
558c66ac9dbSNicholas Bellinger 		return -ENODEV;
559c66ac9dbSNicholas Bellinger 
560c66ac9dbSNicholas Bellinger 	return core_alua_store_offline_bit(lun, page, count);
561c66ac9dbSNicholas Bellinger }
562c66ac9dbSNicholas Bellinger 
target_fabric_port_alua_tg_pt_status_show(struct config_item * item,char * page)5632eafd729SChristoph Hellwig static ssize_t target_fabric_port_alua_tg_pt_status_show(
5642eafd729SChristoph Hellwig 		struct config_item *item, char *page)
565c66ac9dbSNicholas Bellinger {
5662eafd729SChristoph Hellwig 	struct se_lun *lun = item_to_lun(item);
5672eafd729SChristoph Hellwig 
5689c6603e1SDan Carpenter 	if (!lun->lun_se_dev)
569c66ac9dbSNicholas Bellinger 		return -ENODEV;
570c66ac9dbSNicholas Bellinger 
571c66ac9dbSNicholas Bellinger 	return core_alua_show_secondary_status(lun, page);
572c66ac9dbSNicholas Bellinger }
573c66ac9dbSNicholas Bellinger 
target_fabric_port_alua_tg_pt_status_store(struct config_item * item,const char * page,size_t count)5742eafd729SChristoph Hellwig static ssize_t target_fabric_port_alua_tg_pt_status_store(
5752eafd729SChristoph Hellwig 		struct config_item *item, const char *page, size_t count)
576c66ac9dbSNicholas Bellinger {
5772eafd729SChristoph Hellwig 	struct se_lun *lun = item_to_lun(item);
5782eafd729SChristoph Hellwig 
5799c6603e1SDan Carpenter 	if (!lun->lun_se_dev)
580c66ac9dbSNicholas Bellinger 		return -ENODEV;
581c66ac9dbSNicholas Bellinger 
582c66ac9dbSNicholas Bellinger 	return core_alua_store_secondary_status(lun, page, count);
583c66ac9dbSNicholas Bellinger }
584c66ac9dbSNicholas Bellinger 
target_fabric_port_alua_tg_pt_write_md_show(struct config_item * item,char * page)5852eafd729SChristoph Hellwig static ssize_t target_fabric_port_alua_tg_pt_write_md_show(
5862eafd729SChristoph Hellwig 		struct config_item *item, char *page)
587c66ac9dbSNicholas Bellinger {
5882eafd729SChristoph Hellwig 	struct se_lun *lun = item_to_lun(item);
5892eafd729SChristoph Hellwig 
5909c6603e1SDan Carpenter 	if (!lun->lun_se_dev)
591c66ac9dbSNicholas Bellinger 		return -ENODEV;
592c66ac9dbSNicholas Bellinger 
593c66ac9dbSNicholas Bellinger 	return core_alua_show_secondary_write_metadata(lun, page);
594c66ac9dbSNicholas Bellinger }
595c66ac9dbSNicholas Bellinger 
target_fabric_port_alua_tg_pt_write_md_store(struct config_item * item,const char * page,size_t count)5962eafd729SChristoph Hellwig static ssize_t target_fabric_port_alua_tg_pt_write_md_store(
5972eafd729SChristoph Hellwig 		struct config_item *item, const char *page, size_t count)
598c66ac9dbSNicholas Bellinger {
5992eafd729SChristoph Hellwig 	struct se_lun *lun = item_to_lun(item);
6002eafd729SChristoph Hellwig 
6019c6603e1SDan Carpenter 	if (!lun->lun_se_dev)
602c66ac9dbSNicholas Bellinger 		return -ENODEV;
603c66ac9dbSNicholas Bellinger 
604c66ac9dbSNicholas Bellinger 	return core_alua_store_secondary_write_metadata(lun, page, count);
605c66ac9dbSNicholas Bellinger }
606c66ac9dbSNicholas Bellinger 
6072eafd729SChristoph Hellwig CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_gp);
6082eafd729SChristoph Hellwig CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_offline);
6092eafd729SChristoph Hellwig CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_status);
6102eafd729SChristoph Hellwig CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_write_md);
611c66ac9dbSNicholas Bellinger 
612c66ac9dbSNicholas Bellinger static struct configfs_attribute *target_fabric_port_attrs[] = {
6132eafd729SChristoph Hellwig 	&target_fabric_port_attr_alua_tg_pt_gp,
6142eafd729SChristoph Hellwig 	&target_fabric_port_attr_alua_tg_pt_offline,
6152eafd729SChristoph Hellwig 	&target_fabric_port_attr_alua_tg_pt_status,
6162eafd729SChristoph Hellwig 	&target_fabric_port_attr_alua_tg_pt_write_md,
617c66ac9dbSNicholas Bellinger 	NULL,
618c66ac9dbSNicholas Bellinger };
619c66ac9dbSNicholas Bellinger 
target_fabric_port_link(struct config_item * lun_ci,struct config_item * se_dev_ci)620c66ac9dbSNicholas Bellinger static int target_fabric_port_link(
621c66ac9dbSNicholas Bellinger 	struct config_item *lun_ci,
622c66ac9dbSNicholas Bellinger 	struct config_item *se_dev_ci)
623c66ac9dbSNicholas Bellinger {
624c66ac9dbSNicholas Bellinger 	struct config_item *tpg_ci;
625c66ac9dbSNicholas Bellinger 	struct se_lun *lun = container_of(to_config_group(lun_ci),
626c66ac9dbSNicholas Bellinger 				struct se_lun, lun_group);
627c66ac9dbSNicholas Bellinger 	struct se_portal_group *se_tpg;
628c17cd249SNicholas Bellinger 	struct se_device *dev;
629c66ac9dbSNicholas Bellinger 	struct target_fabric_configfs *tf;
630c66ac9dbSNicholas Bellinger 	int ret;
631c66ac9dbSNicholas Bellinger 
632c17cd249SNicholas Bellinger 	if (!se_dev_ci->ci_type ||
633c17cd249SNicholas Bellinger 	    se_dev_ci->ci_type->ct_item_ops != &target_core_dev_item_ops) {
634c17cd249SNicholas Bellinger 		pr_err("Bad se_dev_ci, not a valid se_dev_ci pointer: %p\n", se_dev_ci);
6350ff87549SNicholas Bellinger 		return -EFAULT;
6360ff87549SNicholas Bellinger 	}
637c17cd249SNicholas Bellinger 	dev = container_of(to_config_group(se_dev_ci), struct se_device, dev_group);
6380ff87549SNicholas Bellinger 
639cb0f32e1SMike Christie 	if (!target_dev_configured(dev)) {
640faa06ab9SNicholas Bellinger 		pr_err("se_device not configured yet, cannot port link\n");
641faa06ab9SNicholas Bellinger 		return -ENODEV;
642faa06ab9SNicholas Bellinger 	}
643faa06ab9SNicholas Bellinger 
644c66ac9dbSNicholas Bellinger 	tpg_ci = &lun_ci->ci_parent->ci_group->cg_item;
645c66ac9dbSNicholas Bellinger 	se_tpg = container_of(to_config_group(tpg_ci),
646c66ac9dbSNicholas Bellinger 				struct se_portal_group, tpg_group);
647c66ac9dbSNicholas Bellinger 	tf = se_tpg->se_tpg_wwn->wwn_tf;
648c66ac9dbSNicholas Bellinger 
649c66ac9dbSNicholas Bellinger 	if (lun->lun_se_dev !=  NULL) {
6506708bb27SAndy Grover 		pr_err("Port Symlink already exists\n");
651c66ac9dbSNicholas Bellinger 		return -EEXIST;
652c66ac9dbSNicholas Bellinger 	}
653c66ac9dbSNicholas Bellinger 
6546bb82612SNicholas Bellinger 	ret = core_dev_add_lun(se_tpg, dev, lun);
6556bb82612SNicholas Bellinger 	if (ret) {
6566bb82612SNicholas Bellinger 		pr_err("core_dev_add_lun() failed: %d\n", ret);
657c66ac9dbSNicholas Bellinger 		goto out;
658c66ac9dbSNicholas Bellinger 	}
659c66ac9dbSNicholas Bellinger 
660ef0caf8dSChristoph Hellwig 	if (tf->tf_ops->fabric_post_link) {
661c66ac9dbSNicholas Bellinger 		/*
662c66ac9dbSNicholas Bellinger 		 * Call the optional fabric_post_link() to allow a
663c66ac9dbSNicholas Bellinger 		 * fabric module to setup any additional state once
664c66ac9dbSNicholas Bellinger 		 * core_dev_add_lun() has been called..
665c66ac9dbSNicholas Bellinger 		 */
666ef0caf8dSChristoph Hellwig 		tf->tf_ops->fabric_post_link(se_tpg, lun);
667c66ac9dbSNicholas Bellinger 	}
668c66ac9dbSNicholas Bellinger 
669c66ac9dbSNicholas Bellinger 	return 0;
670c66ac9dbSNicholas Bellinger out:
671c66ac9dbSNicholas Bellinger 	return ret;
672c66ac9dbSNicholas Bellinger }
673c66ac9dbSNicholas Bellinger 
target_fabric_port_unlink(struct config_item * lun_ci,struct config_item * se_dev_ci)674e16769d4SAndrzej Pietrasiewicz static void target_fabric_port_unlink(
675c66ac9dbSNicholas Bellinger 	struct config_item *lun_ci,
676c66ac9dbSNicholas Bellinger 	struct config_item *se_dev_ci)
677c66ac9dbSNicholas Bellinger {
678c66ac9dbSNicholas Bellinger 	struct se_lun *lun = container_of(to_config_group(lun_ci),
679c66ac9dbSNicholas Bellinger 				struct se_lun, lun_group);
680adf653f9SChristoph Hellwig 	struct se_portal_group *se_tpg = lun->lun_tpg;
681c66ac9dbSNicholas Bellinger 	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
682c66ac9dbSNicholas Bellinger 
683ef0caf8dSChristoph Hellwig 	if (tf->tf_ops->fabric_pre_unlink) {
684c66ac9dbSNicholas Bellinger 		/*
685c66ac9dbSNicholas Bellinger 		 * Call the optional fabric_pre_unlink() to allow a
686c66ac9dbSNicholas Bellinger 		 * fabric module to release any additional stat before
687c66ac9dbSNicholas Bellinger 		 * core_dev_del_lun() is called.
688c66ac9dbSNicholas Bellinger 		*/
689ef0caf8dSChristoph Hellwig 		tf->tf_ops->fabric_pre_unlink(se_tpg, lun);
690c66ac9dbSNicholas Bellinger 	}
691c66ac9dbSNicholas Bellinger 
692cd9d7cbaSAndy Grover 	core_dev_del_lun(se_tpg, lun);
693c66ac9dbSNicholas Bellinger }
694c66ac9dbSNicholas Bellinger 
target_fabric_port_release(struct config_item * item)6956bb82612SNicholas Bellinger static void target_fabric_port_release(struct config_item *item)
6966bb82612SNicholas Bellinger {
6976bb82612SNicholas Bellinger 	struct se_lun *lun = container_of(to_config_group(item),
6986bb82612SNicholas Bellinger 					  struct se_lun, lun_group);
6996bb82612SNicholas Bellinger 
7006bb82612SNicholas Bellinger 	kfree_rcu(lun, rcu_head);
7016bb82612SNicholas Bellinger }
7026bb82612SNicholas Bellinger 
703c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_fabric_port_item_ops = {
7046bb82612SNicholas Bellinger 	.release		= target_fabric_port_release,
705c66ac9dbSNicholas Bellinger 	.allow_link		= target_fabric_port_link,
706c66ac9dbSNicholas Bellinger 	.drop_link		= target_fabric_port_unlink,
707c66ac9dbSNicholas Bellinger };
708c66ac9dbSNicholas Bellinger 
709c66ac9dbSNicholas Bellinger TF_CIT_SETUP(tpg_port, &target_fabric_port_item_ops, NULL, target_fabric_port_attrs);
710c66ac9dbSNicholas Bellinger 
711c66ac9dbSNicholas Bellinger /* End of tfc_tpg_port_cit */
712c66ac9dbSNicholas Bellinger 
71312d23384SNicholas Bellinger /* Start of tfc_tpg_port_stat_cit */
71412d23384SNicholas Bellinger 
target_core_port_stat_mkdir(struct config_group * group,const char * name)71512d23384SNicholas Bellinger static struct config_group *target_core_port_stat_mkdir(
71612d23384SNicholas Bellinger 	struct config_group *group,
71712d23384SNicholas Bellinger 	const char *name)
71812d23384SNicholas Bellinger {
71912d23384SNicholas Bellinger 	return ERR_PTR(-ENOSYS);
72012d23384SNicholas Bellinger }
72112d23384SNicholas Bellinger 
target_core_port_stat_rmdir(struct config_group * group,struct config_item * item)72212d23384SNicholas Bellinger static void target_core_port_stat_rmdir(
72312d23384SNicholas Bellinger 	struct config_group *group,
72412d23384SNicholas Bellinger 	struct config_item *item)
72512d23384SNicholas Bellinger {
72612d23384SNicholas Bellinger 	return;
72712d23384SNicholas Bellinger }
72812d23384SNicholas Bellinger 
72912d23384SNicholas Bellinger static struct configfs_group_operations target_fabric_port_stat_group_ops = {
73012d23384SNicholas Bellinger 	.make_group		= target_core_port_stat_mkdir,
73112d23384SNicholas Bellinger 	.drop_item		= target_core_port_stat_rmdir,
73212d23384SNicholas Bellinger };
73312d23384SNicholas Bellinger 
73412d23384SNicholas Bellinger TF_CIT_SETUP(tpg_port_stat, NULL, &target_fabric_port_stat_group_ops, NULL);
73512d23384SNicholas Bellinger 
73612d23384SNicholas Bellinger /* End of tfc_tpg_port_stat_cit */
73712d23384SNicholas Bellinger 
738c66ac9dbSNicholas Bellinger /* Start of tfc_tpg_lun_cit */
739c66ac9dbSNicholas Bellinger 
target_fabric_make_lun(struct config_group * group,const char * name)740c66ac9dbSNicholas Bellinger static struct config_group *target_fabric_make_lun(
741c66ac9dbSNicholas Bellinger 	struct config_group *group,
742c66ac9dbSNicholas Bellinger 	const char *name)
743c66ac9dbSNicholas Bellinger {
744c66ac9dbSNicholas Bellinger 	struct se_lun *lun;
745c66ac9dbSNicholas Bellinger 	struct se_portal_group *se_tpg = container_of(group,
746c66ac9dbSNicholas Bellinger 			struct se_portal_group, tpg_lun_group);
747c66ac9dbSNicholas Bellinger 	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
748f2d30680SHannes Reinecke 	unsigned long long unpacked_lun;
74912d23384SNicholas Bellinger 	int errno;
750c66ac9dbSNicholas Bellinger 
751c66ac9dbSNicholas Bellinger 	if (strstr(name, "lun_") != name) {
7526708bb27SAndy Grover 		pr_err("Unable to locate \'_\" in"
753c66ac9dbSNicholas Bellinger 				" \"lun_$LUN_NUMBER\"\n");
754c66ac9dbSNicholas Bellinger 		return ERR_PTR(-EINVAL);
755c66ac9dbSNicholas Bellinger 	}
756f2d30680SHannes Reinecke 	errno = kstrtoull(name + 4, 0, &unpacked_lun);
75757103d7fSJingoo Han 	if (errno)
75857103d7fSJingoo Han 		return ERR_PTR(errno);
759c66ac9dbSNicholas Bellinger 
7606bb82612SNicholas Bellinger 	lun = core_tpg_alloc_lun(se_tpg, unpacked_lun);
7616bb82612SNicholas Bellinger 	if (IS_ERR(lun))
7626bb82612SNicholas Bellinger 		return ERR_CAST(lun);
763c66ac9dbSNicholas Bellinger 
764c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&lun->lun_group, name,
765968ebe75SChristoph Hellwig 			&tf->tf_tpg_port_cit);
7661ae1602dSChristoph Hellwig 
76712d23384SNicholas Bellinger 	config_group_init_type_name(&lun->port_stat_grps.stat_group,
768968ebe75SChristoph Hellwig 			"statistics", &tf->tf_tpg_port_stat_cit);
7691ae1602dSChristoph Hellwig 	configfs_add_default_group(&lun->port_stat_grps.stat_group,
7701ae1602dSChristoph Hellwig 			&lun->lun_group);
77112d23384SNicholas Bellinger 
77212d23384SNicholas Bellinger 	target_stat_setup_port_default_groups(lun);
773c66ac9dbSNicholas Bellinger 
774c66ac9dbSNicholas Bellinger 	return &lun->lun_group;
775c66ac9dbSNicholas Bellinger }
776c66ac9dbSNicholas Bellinger 
target_fabric_drop_lun(struct config_group * group,struct config_item * item)777c66ac9dbSNicholas Bellinger static void target_fabric_drop_lun(
778c66ac9dbSNicholas Bellinger 	struct config_group *group,
779c66ac9dbSNicholas Bellinger 	struct config_item *item)
780c66ac9dbSNicholas Bellinger {
78112d23384SNicholas Bellinger 	struct se_lun *lun = container_of(to_config_group(item),
78212d23384SNicholas Bellinger 				struct se_lun, lun_group);
78312d23384SNicholas Bellinger 
7841ae1602dSChristoph Hellwig 	configfs_remove_default_groups(&lun->port_stat_grps.stat_group);
7851ae1602dSChristoph Hellwig 	configfs_remove_default_groups(&lun->lun_group);
78612d23384SNicholas Bellinger 
787c66ac9dbSNicholas Bellinger 	config_item_put(item);
788c66ac9dbSNicholas Bellinger }
789c66ac9dbSNicholas Bellinger 
790c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_fabric_lun_group_ops = {
791c66ac9dbSNicholas Bellinger 	.make_group	= &target_fabric_make_lun,
792c66ac9dbSNicholas Bellinger 	.drop_item	= &target_fabric_drop_lun,
793c66ac9dbSNicholas Bellinger };
794c66ac9dbSNicholas Bellinger 
795c66ac9dbSNicholas Bellinger TF_CIT_SETUP(tpg_lun, NULL, &target_fabric_lun_group_ops, NULL);
796c66ac9dbSNicholas Bellinger 
797c66ac9dbSNicholas Bellinger /* End of tfc_tpg_lun_cit */
798c66ac9dbSNicholas Bellinger 
7992eafd729SChristoph Hellwig TF_CIT_SETUP_DRV(tpg_attrib, NULL, NULL);
8002eafd729SChristoph Hellwig TF_CIT_SETUP_DRV(tpg_auth, NULL, NULL);
8012eafd729SChristoph Hellwig TF_CIT_SETUP_DRV(tpg_param, NULL, NULL);
802c66ac9dbSNicholas Bellinger 
803c66ac9dbSNicholas Bellinger /* Start of tfc_tpg_base_cit */
804c66ac9dbSNicholas Bellinger 
target_fabric_tpg_release(struct config_item * item)8051f6fe7cbSNicholas Bellinger static void target_fabric_tpg_release(struct config_item *item)
8061f6fe7cbSNicholas Bellinger {
8071f6fe7cbSNicholas Bellinger 	struct se_portal_group *se_tpg = container_of(to_config_group(item),
8081f6fe7cbSNicholas Bellinger 			struct se_portal_group, tpg_group);
8091f6fe7cbSNicholas Bellinger 	struct se_wwn *wwn = se_tpg->se_tpg_wwn;
8101f6fe7cbSNicholas Bellinger 	struct target_fabric_configfs *tf = wwn->wwn_tf;
8111f6fe7cbSNicholas Bellinger 
812ef0caf8dSChristoph Hellwig 	tf->tf_ops->fabric_drop_tpg(se_tpg);
8131f6fe7cbSNicholas Bellinger }
8141f6fe7cbSNicholas Bellinger 
815c66ac9dbSNicholas Bellinger static struct configfs_item_operations target_fabric_tpg_base_item_ops = {
8161f6fe7cbSNicholas Bellinger 	.release		= target_fabric_tpg_release,
817c66ac9dbSNicholas Bellinger };
818c66ac9dbSNicholas Bellinger 
target_fabric_tpg_base_enable_show(struct config_item * item,char * page)81980ed33c8SDmitry Bogdanov static ssize_t target_fabric_tpg_base_enable_show(struct config_item *item,
82080ed33c8SDmitry Bogdanov 						  char *page)
82180ed33c8SDmitry Bogdanov {
82280ed33c8SDmitry Bogdanov 	return sysfs_emit(page, "%d\n", to_tpg(item)->enabled);
82380ed33c8SDmitry Bogdanov }
824c66ac9dbSNicholas Bellinger 
target_fabric_tpg_base_enable_store(struct config_item * item,const char * page,size_t count)82580ed33c8SDmitry Bogdanov static ssize_t target_fabric_tpg_base_enable_store(struct config_item *item,
82680ed33c8SDmitry Bogdanov 						   const char *page,
82780ed33c8SDmitry Bogdanov 						   size_t count)
82880ed33c8SDmitry Bogdanov {
82980ed33c8SDmitry Bogdanov 	struct se_portal_group *se_tpg = to_tpg(item);
83080ed33c8SDmitry Bogdanov 	int ret;
83180ed33c8SDmitry Bogdanov 	bool op;
83280ed33c8SDmitry Bogdanov 
833e56ca6bcSChristophe JAILLET 	ret = kstrtobool(page, &op);
83480ed33c8SDmitry Bogdanov 	if (ret)
83580ed33c8SDmitry Bogdanov 		return ret;
83680ed33c8SDmitry Bogdanov 
83780ed33c8SDmitry Bogdanov 	if (se_tpg->enabled == op)
83880ed33c8SDmitry Bogdanov 		return count;
8393f4b9cb4SDmitry Bogdanov 	if (op)
8403f4b9cb4SDmitry Bogdanov 		ret = target_tpg_enable(se_tpg);
8413f4b9cb4SDmitry Bogdanov 	else
8423f4b9cb4SDmitry Bogdanov 		ret = target_tpg_disable(se_tpg);
84380ed33c8SDmitry Bogdanov 	if (ret)
84480ed33c8SDmitry Bogdanov 		return ret;
84580ed33c8SDmitry Bogdanov 	return count;
84680ed33c8SDmitry Bogdanov }
target_fabric_tpg_base_rtpi_show(struct config_item * item,char * page)84731177b74SDmitry Bogdanov static ssize_t target_fabric_tpg_base_rtpi_show(struct config_item *item, char *page)
84831177b74SDmitry Bogdanov {
84931177b74SDmitry Bogdanov 	struct se_portal_group *se_tpg = to_tpg(item);
85031177b74SDmitry Bogdanov 
85131177b74SDmitry Bogdanov 	return sysfs_emit(page, "%#x\n", se_tpg->tpg_rtpi);
85231177b74SDmitry Bogdanov }
85331177b74SDmitry Bogdanov 
target_fabric_tpg_base_rtpi_store(struct config_item * item,const char * page,size_t count)85431177b74SDmitry Bogdanov static ssize_t target_fabric_tpg_base_rtpi_store(struct config_item *item,
85531177b74SDmitry Bogdanov 				   const char *page, size_t count)
85631177b74SDmitry Bogdanov {
85731177b74SDmitry Bogdanov 	struct se_portal_group *se_tpg = to_tpg(item);
85831177b74SDmitry Bogdanov 	u16 val;
85931177b74SDmitry Bogdanov 	int ret;
86031177b74SDmitry Bogdanov 
86131177b74SDmitry Bogdanov 	ret = kstrtou16(page, 0, &val);
86231177b74SDmitry Bogdanov 	if (ret < 0)
86331177b74SDmitry Bogdanov 		return ret;
86431177b74SDmitry Bogdanov 	if (val == 0)
86531177b74SDmitry Bogdanov 		return -EINVAL;
86631177b74SDmitry Bogdanov 
86731177b74SDmitry Bogdanov 	if (se_tpg->enabled) {
86831177b74SDmitry Bogdanov 		pr_info("%s_TPG[%hu] - Can not change RTPI on enabled TPG",
86931177b74SDmitry Bogdanov 			se_tpg->se_tpg_tfo->fabric_name,
87031177b74SDmitry Bogdanov 			se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
87131177b74SDmitry Bogdanov 		return -EINVAL;
87231177b74SDmitry Bogdanov 	}
87331177b74SDmitry Bogdanov 
87431177b74SDmitry Bogdanov 	se_tpg->tpg_rtpi = val;
87531177b74SDmitry Bogdanov 	se_tpg->rtpi_manual = true;
87631177b74SDmitry Bogdanov 
87731177b74SDmitry Bogdanov 	return count;
87831177b74SDmitry Bogdanov }
87980ed33c8SDmitry Bogdanov 
88080ed33c8SDmitry Bogdanov CONFIGFS_ATTR(target_fabric_tpg_base_, enable);
88131177b74SDmitry Bogdanov CONFIGFS_ATTR(target_fabric_tpg_base_, rtpi);
88280ed33c8SDmitry Bogdanov 
88380ed33c8SDmitry Bogdanov static int
target_fabric_setup_tpg_base_cit(struct target_fabric_configfs * tf)88480ed33c8SDmitry Bogdanov target_fabric_setup_tpg_base_cit(struct target_fabric_configfs *tf)
88580ed33c8SDmitry Bogdanov {
88680ed33c8SDmitry Bogdanov 	struct config_item_type *cit = &tf->tf_tpg_base_cit;
88780ed33c8SDmitry Bogdanov 	struct configfs_attribute **attrs = NULL;
888*a0fde512SMaurizio Lombardi 	size_t nr_attrs = 0;
88980ed33c8SDmitry Bogdanov 	int i = 0;
89080ed33c8SDmitry Bogdanov 
89180ed33c8SDmitry Bogdanov 	if (tf->tf_ops->tfc_tpg_base_attrs)
89280ed33c8SDmitry Bogdanov 		while (tf->tf_ops->tfc_tpg_base_attrs[nr_attrs] != NULL)
89380ed33c8SDmitry Bogdanov 			nr_attrs++;
89480ed33c8SDmitry Bogdanov 
89580ed33c8SDmitry Bogdanov 	if (tf->tf_ops->fabric_enable_tpg)
89680ed33c8SDmitry Bogdanov 		nr_attrs++;
89780ed33c8SDmitry Bogdanov 
898*a0fde512SMaurizio Lombardi 	/* + 1 for target_fabric_tpg_base_attr_rtpi */
899*a0fde512SMaurizio Lombardi 	nr_attrs++;
90080ed33c8SDmitry Bogdanov 
90180ed33c8SDmitry Bogdanov 	/* + 1 for final NULL in the array */
90280ed33c8SDmitry Bogdanov 	attrs = kcalloc(nr_attrs + 1, sizeof(*attrs), GFP_KERNEL);
90380ed33c8SDmitry Bogdanov 	if (!attrs)
90480ed33c8SDmitry Bogdanov 		return -ENOMEM;
90580ed33c8SDmitry Bogdanov 
90680ed33c8SDmitry Bogdanov 	if (tf->tf_ops->tfc_tpg_base_attrs)
90780ed33c8SDmitry Bogdanov 		for (; tf->tf_ops->tfc_tpg_base_attrs[i] != NULL; i++)
90880ed33c8SDmitry Bogdanov 			attrs[i] = tf->tf_ops->tfc_tpg_base_attrs[i];
90980ed33c8SDmitry Bogdanov 
91080ed33c8SDmitry Bogdanov 	if (tf->tf_ops->fabric_enable_tpg)
91131177b74SDmitry Bogdanov 		attrs[i++] = &target_fabric_tpg_base_attr_enable;
91231177b74SDmitry Bogdanov 
91331177b74SDmitry Bogdanov 	attrs[i++] = &target_fabric_tpg_base_attr_rtpi;
91480ed33c8SDmitry Bogdanov 
91580ed33c8SDmitry Bogdanov 	cit->ct_item_ops = &target_fabric_tpg_base_item_ops;
91680ed33c8SDmitry Bogdanov 	cit->ct_attrs = attrs;
91780ed33c8SDmitry Bogdanov 	cit->ct_owner = tf->tf_ops->module;
91880ed33c8SDmitry Bogdanov 	pr_debug("Setup generic tpg_base\n");
91980ed33c8SDmitry Bogdanov 
92080ed33c8SDmitry Bogdanov 	return 0;
92180ed33c8SDmitry Bogdanov }
922c66ac9dbSNicholas Bellinger /* End of tfc_tpg_base_cit */
923c66ac9dbSNicholas Bellinger 
924c66ac9dbSNicholas Bellinger /* Start of tfc_tpg_cit */
925c66ac9dbSNicholas Bellinger 
target_fabric_make_tpg(struct config_group * group,const char * name)926c66ac9dbSNicholas Bellinger static struct config_group *target_fabric_make_tpg(
927c66ac9dbSNicholas Bellinger 	struct config_group *group,
928c66ac9dbSNicholas Bellinger 	const char *name)
929c66ac9dbSNicholas Bellinger {
930c66ac9dbSNicholas Bellinger 	struct se_wwn *wwn = container_of(group, struct se_wwn, wwn_group);
931c66ac9dbSNicholas Bellinger 	struct target_fabric_configfs *tf = wwn->wwn_tf;
932c66ac9dbSNicholas Bellinger 	struct se_portal_group *se_tpg;
933c66ac9dbSNicholas Bellinger 
934ef0caf8dSChristoph Hellwig 	if (!tf->tf_ops->fabric_make_tpg) {
935ef0caf8dSChristoph Hellwig 		pr_err("tf->tf_ops->fabric_make_tpg is NULL\n");
936c66ac9dbSNicholas Bellinger 		return ERR_PTR(-ENOSYS);
937c66ac9dbSNicholas Bellinger 	}
938c66ac9dbSNicholas Bellinger 
939aa090eabSBart Van Assche 	se_tpg = tf->tf_ops->fabric_make_tpg(wwn, name);
9406708bb27SAndy Grover 	if (!se_tpg || IS_ERR(se_tpg))
941c66ac9dbSNicholas Bellinger 		return ERR_PTR(-EINVAL);
942c66ac9dbSNicholas Bellinger 
943c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_tpg->tpg_group, name,
944968ebe75SChristoph Hellwig 			&tf->tf_tpg_base_cit);
9451ae1602dSChristoph Hellwig 
946c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_tpg->tpg_lun_group, "lun",
947968ebe75SChristoph Hellwig 			&tf->tf_tpg_lun_cit);
9481ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_tpg->tpg_lun_group,
9491ae1602dSChristoph Hellwig 			&se_tpg->tpg_group);
9501ae1602dSChristoph Hellwig 
951c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_tpg->tpg_np_group, "np",
952968ebe75SChristoph Hellwig 			&tf->tf_tpg_np_cit);
9531ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_tpg->tpg_np_group,
9541ae1602dSChristoph Hellwig 			&se_tpg->tpg_group);
9551ae1602dSChristoph Hellwig 
956c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_tpg->tpg_acl_group, "acls",
957968ebe75SChristoph Hellwig 			&tf->tf_tpg_nacl_cit);
9581ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_tpg->tpg_acl_group,
9591ae1602dSChristoph Hellwig 			&se_tpg->tpg_group);
9601ae1602dSChristoph Hellwig 
961c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib",
962968ebe75SChristoph Hellwig 			&tf->tf_tpg_attrib_cit);
9631ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_tpg->tpg_attrib_group,
9641ae1602dSChristoph Hellwig 			&se_tpg->tpg_group);
9651ae1602dSChristoph Hellwig 
966e4b512e7SNicholas Bellinger 	config_group_init_type_name(&se_tpg->tpg_auth_group, "auth",
967968ebe75SChristoph Hellwig 			&tf->tf_tpg_auth_cit);
9681ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_tpg->tpg_auth_group,
9691ae1602dSChristoph Hellwig 			&se_tpg->tpg_group);
9701ae1602dSChristoph Hellwig 
971c66ac9dbSNicholas Bellinger 	config_group_init_type_name(&se_tpg->tpg_param_group, "param",
972968ebe75SChristoph Hellwig 			&tf->tf_tpg_param_cit);
9731ae1602dSChristoph Hellwig 	configfs_add_default_group(&se_tpg->tpg_param_group,
9741ae1602dSChristoph Hellwig 			&se_tpg->tpg_group);
975c66ac9dbSNicholas Bellinger 
976c66ac9dbSNicholas Bellinger 	return &se_tpg->tpg_group;
977c66ac9dbSNicholas Bellinger }
978c66ac9dbSNicholas Bellinger 
target_fabric_drop_tpg(struct config_group * group,struct config_item * item)979c66ac9dbSNicholas Bellinger static void target_fabric_drop_tpg(
980c66ac9dbSNicholas Bellinger 	struct config_group *group,
981c66ac9dbSNicholas Bellinger 	struct config_item *item)
982c66ac9dbSNicholas Bellinger {
983c66ac9dbSNicholas Bellinger 	struct se_portal_group *se_tpg = container_of(to_config_group(item),
984c66ac9dbSNicholas Bellinger 				struct se_portal_group, tpg_group);
985c66ac9dbSNicholas Bellinger 
9861ae1602dSChristoph Hellwig 	configfs_remove_default_groups(&se_tpg->tpg_group);
987c66ac9dbSNicholas Bellinger 	config_item_put(item);
988c66ac9dbSNicholas Bellinger }
989c66ac9dbSNicholas Bellinger 
target_fabric_release_wwn(struct config_item * item)9901f6fe7cbSNicholas Bellinger static void target_fabric_release_wwn(struct config_item *item)
9911f6fe7cbSNicholas Bellinger {
9921f6fe7cbSNicholas Bellinger 	struct se_wwn *wwn = container_of(to_config_group(item),
9931f6fe7cbSNicholas Bellinger 				struct se_wwn, wwn_group);
9941f6fe7cbSNicholas Bellinger 	struct target_fabric_configfs *tf = wwn->wwn_tf;
9951f6fe7cbSNicholas Bellinger 
996839559e1SChristoph Hellwig 	configfs_remove_default_groups(&wwn->fabric_stat_group);
99739ae3eddSMike Christie 	configfs_remove_default_groups(&wwn->param_group);
998ef0caf8dSChristoph Hellwig 	tf->tf_ops->fabric_drop_wwn(wwn);
9991f6fe7cbSNicholas Bellinger }
10001f6fe7cbSNicholas Bellinger 
10011f6fe7cbSNicholas Bellinger static struct configfs_item_operations target_fabric_tpg_item_ops = {
10021f6fe7cbSNicholas Bellinger 	.release	= target_fabric_release_wwn,
10031f6fe7cbSNicholas Bellinger };
10041f6fe7cbSNicholas Bellinger 
1005c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_fabric_tpg_group_ops = {
1006c66ac9dbSNicholas Bellinger 	.make_group	= target_fabric_make_tpg,
1007c66ac9dbSNicholas Bellinger 	.drop_item	= target_fabric_drop_tpg,
1008c66ac9dbSNicholas Bellinger };
1009c66ac9dbSNicholas Bellinger 
10101f6fe7cbSNicholas Bellinger TF_CIT_SETUP(tpg, &target_fabric_tpg_item_ops, &target_fabric_tpg_group_ops,
10111f6fe7cbSNicholas Bellinger 		NULL);
1012c66ac9dbSNicholas Bellinger 
1013c66ac9dbSNicholas Bellinger /* End of tfc_tpg_cit */
1014c66ac9dbSNicholas Bellinger 
101512d23384SNicholas Bellinger /* Start of tfc_wwn_fabric_stats_cit */
101612d23384SNicholas Bellinger /*
101712d23384SNicholas Bellinger  * This is used as a placeholder for struct se_wwn->fabric_stat_group
101812d23384SNicholas Bellinger  * to allow fabrics access to ->fabric_stat_group->default_groups[]
101912d23384SNicholas Bellinger  */
102012d23384SNicholas Bellinger TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL);
102112d23384SNicholas Bellinger 
102212d23384SNicholas Bellinger /* End of tfc_wwn_fabric_stats_cit */
102312d23384SNicholas Bellinger 
102439ae3eddSMike Christie static ssize_t
target_fabric_wwn_cmd_completion_affinity_show(struct config_item * item,char * page)102539ae3eddSMike Christie target_fabric_wwn_cmd_completion_affinity_show(struct config_item *item,
102639ae3eddSMike Christie 					       char *page)
102739ae3eddSMike Christie {
102839ae3eddSMike Christie 	struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,
102939ae3eddSMike Christie 					  param_group);
103039ae3eddSMike Christie 	return sprintf(page, "%d\n",
103139ae3eddSMike Christie 		       wwn->cmd_compl_affinity == WORK_CPU_UNBOUND ?
103239ae3eddSMike Christie 		       SE_COMPL_AFFINITY_CURR_CPU : wwn->cmd_compl_affinity);
103339ae3eddSMike Christie }
103439ae3eddSMike Christie 
103539ae3eddSMike Christie static ssize_t
target_fabric_wwn_cmd_completion_affinity_store(struct config_item * item,const char * page,size_t count)103639ae3eddSMike Christie target_fabric_wwn_cmd_completion_affinity_store(struct config_item *item,
103739ae3eddSMike Christie 						const char *page, size_t count)
103839ae3eddSMike Christie {
103939ae3eddSMike Christie 	struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,
104039ae3eddSMike Christie 					  param_group);
104139ae3eddSMike Christie 	int compl_val;
104239ae3eddSMike Christie 
104339ae3eddSMike Christie 	if (kstrtoint(page, 0, &compl_val))
104439ae3eddSMike Christie 		return -EINVAL;
104539ae3eddSMike Christie 
104639ae3eddSMike Christie 	switch (compl_val) {
104739ae3eddSMike Christie 	case SE_COMPL_AFFINITY_CPUID:
104839ae3eddSMike Christie 		wwn->cmd_compl_affinity = compl_val;
104939ae3eddSMike Christie 		break;
105039ae3eddSMike Christie 	case SE_COMPL_AFFINITY_CURR_CPU:
105139ae3eddSMike Christie 		wwn->cmd_compl_affinity = WORK_CPU_UNBOUND;
105239ae3eddSMike Christie 		break;
105339ae3eddSMike Christie 	default:
105439ae3eddSMike Christie 		if (compl_val < 0 || compl_val >= nr_cpu_ids ||
105539ae3eddSMike Christie 		    !cpu_online(compl_val)) {
105639ae3eddSMike Christie 			pr_err("Command completion value must be between %d and %d or an online CPU.\n",
105739ae3eddSMike Christie 			       SE_COMPL_AFFINITY_CPUID,
105839ae3eddSMike Christie 			       SE_COMPL_AFFINITY_CURR_CPU);
105939ae3eddSMike Christie 			return -EINVAL;
106039ae3eddSMike Christie 		}
106139ae3eddSMike Christie 		wwn->cmd_compl_affinity = compl_val;
106239ae3eddSMike Christie 	}
106339ae3eddSMike Christie 
106439ae3eddSMike Christie 	return count;
106539ae3eddSMike Christie }
106639ae3eddSMike Christie CONFIGFS_ATTR(target_fabric_wwn_, cmd_completion_affinity);
106739ae3eddSMike Christie 
106839ae3eddSMike Christie static struct configfs_attribute *target_fabric_wwn_param_attrs[] = {
106939ae3eddSMike Christie 	&target_fabric_wwn_attr_cmd_completion_affinity,
107039ae3eddSMike Christie 	NULL,
107139ae3eddSMike Christie };
107239ae3eddSMike Christie 
107339ae3eddSMike Christie TF_CIT_SETUP(wwn_param, NULL, NULL, target_fabric_wwn_param_attrs);
107439ae3eddSMike Christie 
1075c66ac9dbSNicholas Bellinger /* Start of tfc_wwn_cit */
1076c66ac9dbSNicholas Bellinger 
target_fabric_make_wwn(struct config_group * group,const char * name)1077c66ac9dbSNicholas Bellinger static struct config_group *target_fabric_make_wwn(
1078c66ac9dbSNicholas Bellinger 	struct config_group *group,
1079c66ac9dbSNicholas Bellinger 	const char *name)
1080c66ac9dbSNicholas Bellinger {
1081c66ac9dbSNicholas Bellinger 	struct target_fabric_configfs *tf = container_of(group,
1082c66ac9dbSNicholas Bellinger 				struct target_fabric_configfs, tf_group);
1083c66ac9dbSNicholas Bellinger 	struct se_wwn *wwn;
1084c66ac9dbSNicholas Bellinger 
1085ef0caf8dSChristoph Hellwig 	if (!tf->tf_ops->fabric_make_wwn) {
10866708bb27SAndy Grover 		pr_err("tf->tf_ops.fabric_make_wwn is NULL\n");
1087c66ac9dbSNicholas Bellinger 		return ERR_PTR(-ENOSYS);
1088c66ac9dbSNicholas Bellinger 	}
1089c66ac9dbSNicholas Bellinger 
1090ef0caf8dSChristoph Hellwig 	wwn = tf->tf_ops->fabric_make_wwn(tf, group, name);
10916708bb27SAndy Grover 	if (!wwn || IS_ERR(wwn))
1092c66ac9dbSNicholas Bellinger 		return ERR_PTR(-EINVAL);
1093c66ac9dbSNicholas Bellinger 
109439ae3eddSMike Christie 	wwn->cmd_compl_affinity = SE_COMPL_AFFINITY_CPUID;
1095c66ac9dbSNicholas Bellinger 	wwn->wwn_tf = tf;
109612d23384SNicholas Bellinger 
1097968ebe75SChristoph Hellwig 	config_group_init_type_name(&wwn->wwn_group, name, &tf->tf_tpg_cit);
10981ae1602dSChristoph Hellwig 
109912d23384SNicholas Bellinger 	config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics",
1100968ebe75SChristoph Hellwig 			&tf->tf_wwn_fabric_stats_cit);
11011ae1602dSChristoph Hellwig 	configfs_add_default_group(&wwn->fabric_stat_group, &wwn->wwn_group);
1102c66ac9dbSNicholas Bellinger 
110339ae3eddSMike Christie 	config_group_init_type_name(&wwn->param_group, "param",
110439ae3eddSMike Christie 			&tf->tf_wwn_param_cit);
110539ae3eddSMike Christie 	configfs_add_default_group(&wwn->param_group, &wwn->wwn_group);
110639ae3eddSMike Christie 
1107839559e1SChristoph Hellwig 	if (tf->tf_ops->add_wwn_groups)
1108839559e1SChristoph Hellwig 		tf->tf_ops->add_wwn_groups(wwn);
1109c66ac9dbSNicholas Bellinger 	return &wwn->wwn_group;
1110c66ac9dbSNicholas Bellinger }
1111c66ac9dbSNicholas Bellinger 
target_fabric_drop_wwn(struct config_group * group,struct config_item * item)1112c66ac9dbSNicholas Bellinger static void target_fabric_drop_wwn(
1113c66ac9dbSNicholas Bellinger 	struct config_group *group,
1114c66ac9dbSNicholas Bellinger 	struct config_item *item)
1115c66ac9dbSNicholas Bellinger {
111612d23384SNicholas Bellinger 	struct se_wwn *wwn = container_of(to_config_group(item),
111712d23384SNicholas Bellinger 				struct se_wwn, wwn_group);
111812d23384SNicholas Bellinger 
11191ae1602dSChristoph Hellwig 	configfs_remove_default_groups(&wwn->wwn_group);
1120c66ac9dbSNicholas Bellinger 	config_item_put(item);
1121c66ac9dbSNicholas Bellinger }
1122c66ac9dbSNicholas Bellinger 
1123c66ac9dbSNicholas Bellinger static struct configfs_group_operations target_fabric_wwn_group_ops = {
1124c66ac9dbSNicholas Bellinger 	.make_group	= target_fabric_make_wwn,
1125c66ac9dbSNicholas Bellinger 	.drop_item	= target_fabric_drop_wwn,
1126c66ac9dbSNicholas Bellinger };
1127c66ac9dbSNicholas Bellinger 
11282eafd729SChristoph Hellwig TF_CIT_SETUP_DRV(wwn, NULL, &target_fabric_wwn_group_ops);
11292eafd729SChristoph Hellwig TF_CIT_SETUP_DRV(discovery, NULL, NULL);
1130c66ac9dbSNicholas Bellinger 
target_fabric_setup_cits(struct target_fabric_configfs * tf)1131c66ac9dbSNicholas Bellinger int target_fabric_setup_cits(struct target_fabric_configfs *tf)
1132c66ac9dbSNicholas Bellinger {
113380ed33c8SDmitry Bogdanov 	int ret;
113480ed33c8SDmitry Bogdanov 
1135c66ac9dbSNicholas Bellinger 	target_fabric_setup_discovery_cit(tf);
1136c66ac9dbSNicholas Bellinger 	target_fabric_setup_wwn_cit(tf);
113712d23384SNicholas Bellinger 	target_fabric_setup_wwn_fabric_stats_cit(tf);
113839ae3eddSMike Christie 	target_fabric_setup_wwn_param_cit(tf);
1139c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_cit(tf);
114080ed33c8SDmitry Bogdanov 
114180ed33c8SDmitry Bogdanov 	ret = target_fabric_setup_tpg_base_cit(tf);
114280ed33c8SDmitry Bogdanov 	if (ret)
114380ed33c8SDmitry Bogdanov 		return ret;
114480ed33c8SDmitry Bogdanov 
1145c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_port_cit(tf);
114612d23384SNicholas Bellinger 	target_fabric_setup_tpg_port_stat_cit(tf);
1147c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_lun_cit(tf);
1148c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_np_cit(tf);
1149c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_np_base_cit(tf);
1150c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_attrib_cit(tf);
1151e4b512e7SNicholas Bellinger 	target_fabric_setup_tpg_auth_cit(tf);
1152c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_param_cit(tf);
1153c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_nacl_cit(tf);
1154c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_nacl_base_cit(tf);
1155c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_nacl_attrib_cit(tf);
1156c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_nacl_auth_cit(tf);
1157c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_nacl_param_cit(tf);
115812d23384SNicholas Bellinger 	target_fabric_setup_tpg_nacl_stat_cit(tf);
1159c66ac9dbSNicholas Bellinger 	target_fabric_setup_tpg_mappedlun_cit(tf);
116012d23384SNicholas Bellinger 	target_fabric_setup_tpg_mappedlun_stat_cit(tf);
1161c66ac9dbSNicholas Bellinger 
1162c66ac9dbSNicholas Bellinger 	return 0;
1163c66ac9dbSNicholas Bellinger }
1164