brintos

brintos / linux-shallow public Read only

0
0
Text · 32.0 KiB · 7156a4d Raw
1188 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*******************************************************************************3* Filename: target_core_fabric_configfs.c4 *5 * This file contains generic fabric module configfs infrastructure for6 * TCM v4.x code7 *8 * (c) Copyright 2010-2013 Datera, Inc.9 *10 * Nicholas A. Bellinger <nab@linux-iscsi.org>11*12 ****************************************************************************/13 14#include <linux/kstrtox.h>15#include <linux/module.h>16#include <linux/moduleparam.h>17#include <linux/utsname.h>18#include <linux/init.h>19#include <linux/fs.h>20#include <linux/namei.h>21#include <linux/slab.h>22#include <linux/types.h>23#include <linux/delay.h>24#include <linux/unistd.h>25#include <linux/string.h>26#include <linux/syscalls.h>27#include <linux/configfs.h>28 29#include <target/target_core_base.h>30#include <target/target_core_backend.h>31#include <target/target_core_fabric.h>32 33#include "target_core_internal.h"34#include "target_core_alua.h"35#include "target_core_pr.h"36 37#define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs)		\38static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \39{									\40	struct config_item_type *cit = &tf->tf_##_name##_cit;		\41									\42	cit->ct_item_ops = _item_ops;					\43	cit->ct_group_ops = _group_ops;					\44	cit->ct_attrs = _attrs;						\45	cit->ct_owner = tf->tf_ops->module;				\46	pr_debug("Setup generic %s\n", __stringify(_name));		\47}48 49#define TF_CIT_SETUP_DRV(_name, _item_ops, _group_ops)		\50static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \51{									\52	struct config_item_type *cit = &tf->tf_##_name##_cit;		\53	struct configfs_attribute **attrs = tf->tf_ops->tfc_##_name##_attrs; \54									\55	cit->ct_item_ops = _item_ops;					\56	cit->ct_group_ops = _group_ops;					\57	cit->ct_attrs = attrs;						\58	cit->ct_owner = tf->tf_ops->module;				\59	pr_debug("Setup generic %s\n", __stringify(_name));		\60}61 62static struct configfs_item_operations target_fabric_port_item_ops;63 64/* Start of tfc_tpg_mappedlun_cit */65 66static int target_fabric_mappedlun_link(67	struct config_item *lun_acl_ci,68	struct config_item *lun_ci)69{70	struct se_dev_entry *deve;71	struct se_lun *lun;72	struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),73			struct se_lun_acl, se_lun_group);74	struct se_portal_group *se_tpg;75	struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s;76	bool lun_access_ro;77 78	if (!lun_ci->ci_type ||79	    lun_ci->ci_type->ct_item_ops != &target_fabric_port_item_ops) {80		pr_err("Bad lun_ci, not a valid lun_ci pointer: %p\n", lun_ci);81		return -EFAULT;82	}83	lun = container_of(to_config_group(lun_ci), struct se_lun, lun_group);84 85	/*86	 * Ensure that the source port exists87	 */88	if (!lun->lun_se_dev) {89		pr_err("Source se_lun->lun_se_dev does not exist\n");90		return -EINVAL;91	}92	if (lun->lun_shutdown) {93		pr_err("Unable to create mappedlun symlink because"94			" lun->lun_shutdown=true\n");95		return -EINVAL;96	}97	se_tpg = lun->lun_tpg;98 99	nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item;100	tpg_ci = &nacl_ci->ci_group->cg_item;101	wwn_ci = &tpg_ci->ci_group->cg_item;102	tpg_ci_s = &lun_ci->ci_parent->ci_group->cg_item;103	wwn_ci_s = &tpg_ci_s->ci_group->cg_item;104	/*105	 * Make sure the SymLink is going to the same $FABRIC/$WWN/tpgt_$TPGT106	 */107	if (strcmp(config_item_name(wwn_ci), config_item_name(wwn_ci_s))) {108		pr_err("Illegal Initiator ACL SymLink outside of %s\n",109			config_item_name(wwn_ci));110		return -EINVAL;111	}112	if (strcmp(config_item_name(tpg_ci), config_item_name(tpg_ci_s))) {113		pr_err("Illegal Initiator ACL Symlink outside of %s"114			" TPGT: %s\n", config_item_name(wwn_ci),115			config_item_name(tpg_ci));116		return -EINVAL;117	}118	/*119	 * If this struct se_node_acl was dynamically generated with120	 * tpg_1/attrib/generate_node_acls=1, use the existing121	 * deve->lun_access_ro value, which will be true when122	 * tpg_1/attrib/demo_mode_write_protect=1123	 */124	rcu_read_lock();125	deve = target_nacl_find_deve(lacl->se_lun_nacl, lacl->mapped_lun);126	if (deve)127		lun_access_ro = deve->lun_access_ro;128	else129		lun_access_ro =130			(se_tpg->se_tpg_tfo->tpg_check_prod_mode_write_protect(131				se_tpg)) ? true : false;132	rcu_read_unlock();133	/*134	 * Determine the actual mapped LUN value user wants..135	 *136	 * This value is what the SCSI Initiator actually sees the137	 * $FABRIC/$WWPN/$TPGT/lun/lun_* as on their SCSI Initiator Ports.138	 */139	return core_dev_add_initiator_node_lun_acl(se_tpg, lacl, lun, lun_access_ro);140}141 142static void target_fabric_mappedlun_unlink(143	struct config_item *lun_acl_ci,144	struct config_item *lun_ci)145{146	struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),147			struct se_lun_acl, se_lun_group);148	struct se_lun *lun = container_of(to_config_group(lun_ci),149			struct se_lun, lun_group);150 151	core_dev_del_initiator_node_lun_acl(lun, lacl);152}153 154static struct se_lun_acl *item_to_lun_acl(struct config_item *item)155{156	return container_of(to_config_group(item), struct se_lun_acl,157			se_lun_group);158}159 160static ssize_t target_fabric_mappedlun_write_protect_show(161		struct config_item *item, char *page)162{163	struct se_lun_acl *lacl = item_to_lun_acl(item);164	struct se_node_acl *se_nacl = lacl->se_lun_nacl;165	struct se_dev_entry *deve;166	ssize_t len = 0;167 168	rcu_read_lock();169	deve = target_nacl_find_deve(se_nacl, lacl->mapped_lun);170	if (deve) {171		len = sprintf(page, "%d\n", deve->lun_access_ro);172	}173	rcu_read_unlock();174 175	return len;176}177 178static ssize_t target_fabric_mappedlun_write_protect_store(179		struct config_item *item, const char *page, size_t count)180{181	struct se_lun_acl *lacl = item_to_lun_acl(item);182	struct se_node_acl *se_nacl = lacl->se_lun_nacl;183	struct se_portal_group *se_tpg = se_nacl->se_tpg;184	unsigned long wp;185	int ret;186 187	ret = kstrtoul(page, 0, &wp);188	if (ret)189		return ret;190 191	if ((wp != 1) && (wp != 0))192		return -EINVAL;193 194	/* wp=1 means lun_access_ro=true */195	core_update_device_list_access(lacl->mapped_lun, wp, lacl->se_lun_nacl);196 197	pr_debug("%s_ConfigFS: Changed Initiator ACL: %s"198		" Mapped LUN: %llu Write Protect bit to %s\n",199		se_tpg->se_tpg_tfo->fabric_name,200		se_nacl->initiatorname, lacl->mapped_lun, (wp) ? "ON" : "OFF");201 202	return count;203 204}205 206CONFIGFS_ATTR(target_fabric_mappedlun_, write_protect);207 208static struct configfs_attribute *target_fabric_mappedlun_attrs[] = {209	&target_fabric_mappedlun_attr_write_protect,210	NULL,211};212 213static void target_fabric_mappedlun_release(struct config_item *item)214{215	struct se_lun_acl *lacl = container_of(to_config_group(item),216				struct se_lun_acl, se_lun_group);217	struct se_portal_group *se_tpg = lacl->se_lun_nacl->se_tpg;218 219	core_dev_free_initiator_node_lun_acl(se_tpg, lacl);220}221 222static struct configfs_item_operations target_fabric_mappedlun_item_ops = {223	.release		= target_fabric_mappedlun_release,224	.allow_link		= target_fabric_mappedlun_link,225	.drop_link		= target_fabric_mappedlun_unlink,226};227 228TF_CIT_SETUP(tpg_mappedlun, &target_fabric_mappedlun_item_ops, NULL,229		target_fabric_mappedlun_attrs);230 231/* End of tfc_tpg_mappedlun_cit */232 233/* Start of tfc_tpg_mappedlun_port_cit */234 235static struct config_group *target_core_mappedlun_stat_mkdir(236	struct config_group *group,237	const char *name)238{239	return ERR_PTR(-ENOSYS);240}241 242static void target_core_mappedlun_stat_rmdir(243	struct config_group *group,244	struct config_item *item)245{246	return;247}248 249static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = {250	.make_group		= target_core_mappedlun_stat_mkdir,251	.drop_item		= target_core_mappedlun_stat_rmdir,252};253 254TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops,255		NULL);256 257/* End of tfc_tpg_mappedlun_port_cit */258 259TF_CIT_SETUP_DRV(tpg_nacl_attrib, NULL, NULL);260TF_CIT_SETUP_DRV(tpg_nacl_auth, NULL, NULL);261TF_CIT_SETUP_DRV(tpg_nacl_param, NULL, NULL);262 263/* Start of tfc_tpg_nacl_base_cit */264 265static struct config_group *target_fabric_make_mappedlun(266	struct config_group *group,267	const char *name)268{269	struct se_node_acl *se_nacl = container_of(group,270			struct se_node_acl, acl_group);271	struct se_portal_group *se_tpg = se_nacl->se_tpg;272	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;273	struct se_lun_acl *lacl = NULL;274	char *buf;275	unsigned long long mapped_lun;276	int ret = 0;277 278	buf = kzalloc(strlen(name) + 1, GFP_KERNEL);279	if (!buf) {280		pr_err("Unable to allocate memory for name buf\n");281		return ERR_PTR(-ENOMEM);282	}283	snprintf(buf, strlen(name) + 1, "%s", name);284	/*285	 * Make sure user is creating iscsi/$IQN/$TPGT/acls/$INITIATOR/lun_$ID.286	 */287	if (strstr(buf, "lun_") != buf) {288		pr_err("Unable to locate \"lun_\" from buf: %s"289			" name: %s\n", buf, name);290		ret = -EINVAL;291		goto out;292	}293	/*294	 * Determine the Mapped LUN value.  This is what the SCSI Initiator295	 * Port will actually see.296	 */297	ret = kstrtoull(buf + 4, 0, &mapped_lun);298	if (ret)299		goto out;300 301	lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl,302			mapped_lun, &ret);303	if (!lacl) {304		ret = -EINVAL;305		goto out;306	}307 308	config_group_init_type_name(&lacl->se_lun_group, name,309			&tf->tf_tpg_mappedlun_cit);310 311	config_group_init_type_name(&lacl->ml_stat_grps.stat_group,312			"statistics", &tf->tf_tpg_mappedlun_stat_cit);313	configfs_add_default_group(&lacl->ml_stat_grps.stat_group,314			&lacl->se_lun_group);315 316	target_stat_setup_mappedlun_default_groups(lacl);317 318	kfree(buf);319	return &lacl->se_lun_group;320out:321	kfree(lacl);322	kfree(buf);323	return ERR_PTR(ret);324}325 326static void target_fabric_drop_mappedlun(327	struct config_group *group,328	struct config_item *item)329{330	struct se_lun_acl *lacl = container_of(to_config_group(item),331			struct se_lun_acl, se_lun_group);332 333	configfs_remove_default_groups(&lacl->ml_stat_grps.stat_group);334	configfs_remove_default_groups(&lacl->se_lun_group);335 336	config_item_put(item);337}338 339static void target_fabric_nacl_base_release(struct config_item *item)340{341	struct se_node_acl *se_nacl = container_of(to_config_group(item),342			struct se_node_acl, acl_group);343 344	configfs_remove_default_groups(&se_nacl->acl_fabric_stat_group);345	core_tpg_del_initiator_node_acl(se_nacl);346}347 348static struct configfs_item_operations target_fabric_nacl_base_item_ops = {349	.release		= target_fabric_nacl_base_release,350};351 352static struct configfs_group_operations target_fabric_nacl_base_group_ops = {353	.make_group		= target_fabric_make_mappedlun,354	.drop_item		= target_fabric_drop_mappedlun,355};356 357TF_CIT_SETUP_DRV(tpg_nacl_base, &target_fabric_nacl_base_item_ops,358		&target_fabric_nacl_base_group_ops);359 360/* End of tfc_tpg_nacl_base_cit */361 362/* Start of tfc_node_fabric_stats_cit */363/*364 * This is used as a placeholder for struct se_node_acl->acl_fabric_stat_group365 * to allow fabrics access to ->acl_fabric_stat_group->default_groups[]366 */367TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL);368 369/* End of tfc_wwn_fabric_stats_cit */370 371/* Start of tfc_tpg_nacl_cit */372 373static struct config_group *target_fabric_make_nodeacl(374	struct config_group *group,375	const char *name)376{377	struct se_portal_group *se_tpg = container_of(group,378			struct se_portal_group, tpg_acl_group);379	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;380	struct se_node_acl *se_nacl;381 382	se_nacl = core_tpg_add_initiator_node_acl(se_tpg, name);383	if (IS_ERR(se_nacl))384		return ERR_CAST(se_nacl);385 386	config_group_init_type_name(&se_nacl->acl_group, name,387			&tf->tf_tpg_nacl_base_cit);388 389	config_group_init_type_name(&se_nacl->acl_attrib_group, "attrib",390			&tf->tf_tpg_nacl_attrib_cit);391	configfs_add_default_group(&se_nacl->acl_attrib_group,392			&se_nacl->acl_group);393 394	config_group_init_type_name(&se_nacl->acl_auth_group, "auth",395			&tf->tf_tpg_nacl_auth_cit);396	configfs_add_default_group(&se_nacl->acl_auth_group,397			&se_nacl->acl_group);398 399	config_group_init_type_name(&se_nacl->acl_param_group, "param",400			&tf->tf_tpg_nacl_param_cit);401	configfs_add_default_group(&se_nacl->acl_param_group,402			&se_nacl->acl_group);403 404	config_group_init_type_name(&se_nacl->acl_fabric_stat_group,405			"fabric_statistics", &tf->tf_tpg_nacl_stat_cit);406	configfs_add_default_group(&se_nacl->acl_fabric_stat_group,407			&se_nacl->acl_group);408 409	if (tf->tf_ops->fabric_init_nodeacl) {410		int ret = tf->tf_ops->fabric_init_nodeacl(se_nacl, name);411		if (ret) {412			configfs_remove_default_groups(&se_nacl->acl_fabric_stat_group);413			core_tpg_del_initiator_node_acl(se_nacl);414			return ERR_PTR(ret);415		}416	}417 418	return &se_nacl->acl_group;419}420 421static void target_fabric_drop_nodeacl(422	struct config_group *group,423	struct config_item *item)424{425	struct se_node_acl *se_nacl = container_of(to_config_group(item),426			struct se_node_acl, acl_group);427 428	configfs_remove_default_groups(&se_nacl->acl_group);429 430	/*431	 * struct se_node_acl free is done in target_fabric_nacl_base_release()432	 */433	config_item_put(item);434}435 436static struct configfs_group_operations target_fabric_nacl_group_ops = {437	.make_group	= target_fabric_make_nodeacl,438	.drop_item	= target_fabric_drop_nodeacl,439};440 441TF_CIT_SETUP(tpg_nacl, NULL, &target_fabric_nacl_group_ops, NULL);442 443/* End of tfc_tpg_nacl_cit */444 445/* Start of tfc_tpg_np_base_cit */446 447static void target_fabric_np_base_release(struct config_item *item)448{449	struct se_tpg_np *se_tpg_np = container_of(to_config_group(item),450				struct se_tpg_np, tpg_np_group);451	struct se_portal_group *se_tpg = se_tpg_np->tpg_np_parent;452	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;453 454	tf->tf_ops->fabric_drop_np(se_tpg_np);455}456 457static struct configfs_item_operations target_fabric_np_base_item_ops = {458	.release		= target_fabric_np_base_release,459};460 461TF_CIT_SETUP_DRV(tpg_np_base, &target_fabric_np_base_item_ops, NULL);462 463/* End of tfc_tpg_np_base_cit */464 465/* Start of tfc_tpg_np_cit */466 467static struct config_group *target_fabric_make_np(468	struct config_group *group,469	const char *name)470{471	struct se_portal_group *se_tpg = container_of(group,472				struct se_portal_group, tpg_np_group);473	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;474	struct se_tpg_np *se_tpg_np;475 476	if (!tf->tf_ops->fabric_make_np) {477		pr_err("tf->tf_ops.fabric_make_np is NULL\n");478		return ERR_PTR(-ENOSYS);479	}480 481	se_tpg_np = tf->tf_ops->fabric_make_np(se_tpg, group, name);482	if (!se_tpg_np || IS_ERR(se_tpg_np))483		return ERR_PTR(-EINVAL);484 485	se_tpg_np->tpg_np_parent = se_tpg;486	config_group_init_type_name(&se_tpg_np->tpg_np_group, name,487			&tf->tf_tpg_np_base_cit);488 489	return &se_tpg_np->tpg_np_group;490}491 492static void target_fabric_drop_np(493	struct config_group *group,494	struct config_item *item)495{496	/*497	 * struct se_tpg_np is released via target_fabric_np_base_release()498	 */499	config_item_put(item);500}501 502static struct configfs_group_operations target_fabric_np_group_ops = {503	.make_group	= &target_fabric_make_np,504	.drop_item	= &target_fabric_drop_np,505};506 507TF_CIT_SETUP(tpg_np, NULL, &target_fabric_np_group_ops, NULL);508 509/* End of tfc_tpg_np_cit */510 511/* Start of tfc_tpg_port_cit */512 513static struct se_lun *item_to_lun(struct config_item *item)514{515	return container_of(to_config_group(item), struct se_lun,516			lun_group);517}518 519static ssize_t target_fabric_port_alua_tg_pt_gp_show(struct config_item *item,520		char *page)521{522	struct se_lun *lun = item_to_lun(item);523 524	if (!lun->lun_se_dev)525		return -ENODEV;526 527	return core_alua_show_tg_pt_gp_info(lun, page);528}529 530static ssize_t target_fabric_port_alua_tg_pt_gp_store(struct config_item *item,531		const char *page, size_t count)532{533	struct se_lun *lun = item_to_lun(item);534 535	if (!lun->lun_se_dev)536		return -ENODEV;537 538	return core_alua_store_tg_pt_gp_info(lun, page, count);539}540 541static ssize_t target_fabric_port_alua_tg_pt_offline_show(542		struct config_item *item, char *page)543{544	struct se_lun *lun = item_to_lun(item);545 546	if (!lun->lun_se_dev)547		return -ENODEV;548 549	return core_alua_show_offline_bit(lun, page);550}551 552static ssize_t target_fabric_port_alua_tg_pt_offline_store(553		struct config_item *item, const char *page, size_t count)554{555	struct se_lun *lun = item_to_lun(item);556 557	if (!lun->lun_se_dev)558		return -ENODEV;559 560	return core_alua_store_offline_bit(lun, page, count);561}562 563static ssize_t target_fabric_port_alua_tg_pt_status_show(564		struct config_item *item, char *page)565{566	struct se_lun *lun = item_to_lun(item);567 568	if (!lun->lun_se_dev)569		return -ENODEV;570 571	return core_alua_show_secondary_status(lun, page);572}573 574static ssize_t target_fabric_port_alua_tg_pt_status_store(575		struct config_item *item, const char *page, size_t count)576{577	struct se_lun *lun = item_to_lun(item);578 579	if (!lun->lun_se_dev)580		return -ENODEV;581 582	return core_alua_store_secondary_status(lun, page, count);583}584 585static ssize_t target_fabric_port_alua_tg_pt_write_md_show(586		struct config_item *item, char *page)587{588	struct se_lun *lun = item_to_lun(item);589 590	if (!lun->lun_se_dev)591		return -ENODEV;592 593	return core_alua_show_secondary_write_metadata(lun, page);594}595 596static ssize_t target_fabric_port_alua_tg_pt_write_md_store(597		struct config_item *item, const char *page, size_t count)598{599	struct se_lun *lun = item_to_lun(item);600 601	if (!lun->lun_se_dev)602		return -ENODEV;603 604	return core_alua_store_secondary_write_metadata(lun, page, count);605}606 607CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_gp);608CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_offline);609CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_status);610CONFIGFS_ATTR(target_fabric_port_, alua_tg_pt_write_md);611 612static struct configfs_attribute *target_fabric_port_attrs[] = {613	&target_fabric_port_attr_alua_tg_pt_gp,614	&target_fabric_port_attr_alua_tg_pt_offline,615	&target_fabric_port_attr_alua_tg_pt_status,616	&target_fabric_port_attr_alua_tg_pt_write_md,617	NULL,618};619 620static int target_fabric_port_link(621	struct config_item *lun_ci,622	struct config_item *se_dev_ci)623{624	struct config_item *tpg_ci;625	struct se_lun *lun = container_of(to_config_group(lun_ci),626				struct se_lun, lun_group);627	struct se_portal_group *se_tpg;628	struct se_device *dev;629	struct target_fabric_configfs *tf;630	int ret;631 632	if (!se_dev_ci->ci_type ||633	    se_dev_ci->ci_type->ct_item_ops != &target_core_dev_item_ops) {634		pr_err("Bad se_dev_ci, not a valid se_dev_ci pointer: %p\n", se_dev_ci);635		return -EFAULT;636	}637	dev = container_of(to_config_group(se_dev_ci), struct se_device, dev_group);638 639	if (!target_dev_configured(dev)) {640		pr_err("se_device not configured yet, cannot port link\n");641		return -ENODEV;642	}643 644	tpg_ci = &lun_ci->ci_parent->ci_group->cg_item;645	se_tpg = container_of(to_config_group(tpg_ci),646				struct se_portal_group, tpg_group);647	tf = se_tpg->se_tpg_wwn->wwn_tf;648 649	if (lun->lun_se_dev !=  NULL) {650		pr_err("Port Symlink already exists\n");651		return -EEXIST;652	}653 654	ret = core_dev_add_lun(se_tpg, dev, lun);655	if (ret) {656		pr_err("core_dev_add_lun() failed: %d\n", ret);657		goto out;658	}659 660	if (tf->tf_ops->fabric_post_link) {661		/*662		 * Call the optional fabric_post_link() to allow a663		 * fabric module to setup any additional state once664		 * core_dev_add_lun() has been called..665		 */666		tf->tf_ops->fabric_post_link(se_tpg, lun);667	}668 669	return 0;670out:671	return ret;672}673 674static void target_fabric_port_unlink(675	struct config_item *lun_ci,676	struct config_item *se_dev_ci)677{678	struct se_lun *lun = container_of(to_config_group(lun_ci),679				struct se_lun, lun_group);680	struct se_portal_group *se_tpg = lun->lun_tpg;681	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;682 683	if (tf->tf_ops->fabric_pre_unlink) {684		/*685		 * Call the optional fabric_pre_unlink() to allow a686		 * fabric module to release any additional stat before687		 * core_dev_del_lun() is called.688		*/689		tf->tf_ops->fabric_pre_unlink(se_tpg, lun);690	}691 692	core_dev_del_lun(se_tpg, lun);693}694 695static void target_fabric_port_release(struct config_item *item)696{697	struct se_lun *lun = container_of(to_config_group(item),698					  struct se_lun, lun_group);699 700	kfree_rcu(lun, rcu_head);701}702 703static struct configfs_item_operations target_fabric_port_item_ops = {704	.release		= target_fabric_port_release,705	.allow_link		= target_fabric_port_link,706	.drop_link		= target_fabric_port_unlink,707};708 709TF_CIT_SETUP(tpg_port, &target_fabric_port_item_ops, NULL, target_fabric_port_attrs);710 711/* End of tfc_tpg_port_cit */712 713/* Start of tfc_tpg_port_stat_cit */714 715static struct config_group *target_core_port_stat_mkdir(716	struct config_group *group,717	const char *name)718{719	return ERR_PTR(-ENOSYS);720}721 722static void target_core_port_stat_rmdir(723	struct config_group *group,724	struct config_item *item)725{726	return;727}728 729static struct configfs_group_operations target_fabric_port_stat_group_ops = {730	.make_group		= target_core_port_stat_mkdir,731	.drop_item		= target_core_port_stat_rmdir,732};733 734TF_CIT_SETUP(tpg_port_stat, NULL, &target_fabric_port_stat_group_ops, NULL);735 736/* End of tfc_tpg_port_stat_cit */737 738/* Start of tfc_tpg_lun_cit */739 740static struct config_group *target_fabric_make_lun(741	struct config_group *group,742	const char *name)743{744	struct se_lun *lun;745	struct se_portal_group *se_tpg = container_of(group,746			struct se_portal_group, tpg_lun_group);747	struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;748	unsigned long long unpacked_lun;749	int errno;750 751	if (strstr(name, "lun_") != name) {752		pr_err("Unable to locate \'_\" in"753				" \"lun_$LUN_NUMBER\"\n");754		return ERR_PTR(-EINVAL);755	}756	errno = kstrtoull(name + 4, 0, &unpacked_lun);757	if (errno)758		return ERR_PTR(errno);759 760	lun = core_tpg_alloc_lun(se_tpg, unpacked_lun);761	if (IS_ERR(lun))762		return ERR_CAST(lun);763 764	config_group_init_type_name(&lun->lun_group, name,765			&tf->tf_tpg_port_cit);766 767	config_group_init_type_name(&lun->port_stat_grps.stat_group,768			"statistics", &tf->tf_tpg_port_stat_cit);769	configfs_add_default_group(&lun->port_stat_grps.stat_group,770			&lun->lun_group);771 772	target_stat_setup_port_default_groups(lun);773 774	return &lun->lun_group;775}776 777static void target_fabric_drop_lun(778	struct config_group *group,779	struct config_item *item)780{781	struct se_lun *lun = container_of(to_config_group(item),782				struct se_lun, lun_group);783 784	configfs_remove_default_groups(&lun->port_stat_grps.stat_group);785	configfs_remove_default_groups(&lun->lun_group);786 787	config_item_put(item);788}789 790static struct configfs_group_operations target_fabric_lun_group_ops = {791	.make_group	= &target_fabric_make_lun,792	.drop_item	= &target_fabric_drop_lun,793};794 795TF_CIT_SETUP(tpg_lun, NULL, &target_fabric_lun_group_ops, NULL);796 797/* End of tfc_tpg_lun_cit */798 799TF_CIT_SETUP_DRV(tpg_attrib, NULL, NULL);800TF_CIT_SETUP_DRV(tpg_auth, NULL, NULL);801TF_CIT_SETUP_DRV(tpg_param, NULL, NULL);802 803/* Start of tfc_tpg_base_cit */804 805static void target_fabric_tpg_release(struct config_item *item)806{807	struct se_portal_group *se_tpg = container_of(to_config_group(item),808			struct se_portal_group, tpg_group);809	struct se_wwn *wwn = se_tpg->se_tpg_wwn;810	struct target_fabric_configfs *tf = wwn->wwn_tf;811 812	tf->tf_ops->fabric_drop_tpg(se_tpg);813}814 815static struct configfs_item_operations target_fabric_tpg_base_item_ops = {816	.release		= target_fabric_tpg_release,817};818 819static ssize_t target_fabric_tpg_base_enable_show(struct config_item *item,820						  char *page)821{822	return sysfs_emit(page, "%d\n", to_tpg(item)->enabled);823}824 825static ssize_t target_fabric_tpg_base_enable_store(struct config_item *item,826						   const char *page,827						   size_t count)828{829	struct se_portal_group *se_tpg = to_tpg(item);830	int ret;831	bool op;832 833	ret = kstrtobool(page, &op);834	if (ret)835		return ret;836 837	if (se_tpg->enabled == op)838		return count;839	if (op)840		ret = target_tpg_enable(se_tpg);841	else842		ret = target_tpg_disable(se_tpg);843	if (ret)844		return ret;845	return count;846}847static ssize_t target_fabric_tpg_base_rtpi_show(struct config_item *item, char *page)848{849	struct se_portal_group *se_tpg = to_tpg(item);850 851	return sysfs_emit(page, "%#x\n", se_tpg->tpg_rtpi);852}853 854static ssize_t target_fabric_tpg_base_rtpi_store(struct config_item *item,855				   const char *page, size_t count)856{857	struct se_portal_group *se_tpg = to_tpg(item);858	u16 val;859	int ret;860 861	ret = kstrtou16(page, 0, &val);862	if (ret < 0)863		return ret;864	if (val == 0)865		return -EINVAL;866 867	if (se_tpg->enabled) {868		pr_info("%s_TPG[%hu] - Can not change RTPI on enabled TPG",869			se_tpg->se_tpg_tfo->fabric_name,870			se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));871		return -EINVAL;872	}873 874	se_tpg->tpg_rtpi = val;875	se_tpg->rtpi_manual = true;876 877	return count;878}879 880CONFIGFS_ATTR(target_fabric_tpg_base_, enable);881CONFIGFS_ATTR(target_fabric_tpg_base_, rtpi);882 883static int884target_fabric_setup_tpg_base_cit(struct target_fabric_configfs *tf)885{886	struct config_item_type *cit = &tf->tf_tpg_base_cit;887	struct configfs_attribute **attrs = NULL;888	size_t nr_attrs = 0;889	int i = 0;890 891	if (tf->tf_ops->tfc_tpg_base_attrs)892		while (tf->tf_ops->tfc_tpg_base_attrs[nr_attrs] != NULL)893			nr_attrs++;894 895	if (tf->tf_ops->fabric_enable_tpg)896		nr_attrs++;897 898	/* + 1 for target_fabric_tpg_base_attr_rtpi */899	nr_attrs++;900 901	/* + 1 for final NULL in the array */902	attrs = kcalloc(nr_attrs + 1, sizeof(*attrs), GFP_KERNEL);903	if (!attrs)904		return -ENOMEM;905 906	if (tf->tf_ops->tfc_tpg_base_attrs)907		for (; tf->tf_ops->tfc_tpg_base_attrs[i] != NULL; i++)908			attrs[i] = tf->tf_ops->tfc_tpg_base_attrs[i];909 910	if (tf->tf_ops->fabric_enable_tpg)911		attrs[i++] = &target_fabric_tpg_base_attr_enable;912 913	attrs[i++] = &target_fabric_tpg_base_attr_rtpi;914 915	cit->ct_item_ops = &target_fabric_tpg_base_item_ops;916	cit->ct_attrs = attrs;917	cit->ct_owner = tf->tf_ops->module;918	pr_debug("Setup generic tpg_base\n");919 920	return 0;921}922/* End of tfc_tpg_base_cit */923 924/* Start of tfc_tpg_cit */925 926static struct config_group *target_fabric_make_tpg(927	struct config_group *group,928	const char *name)929{930	struct se_wwn *wwn = container_of(group, struct se_wwn, wwn_group);931	struct target_fabric_configfs *tf = wwn->wwn_tf;932	struct se_portal_group *se_tpg;933 934	if (!tf->tf_ops->fabric_make_tpg) {935		pr_err("tf->tf_ops->fabric_make_tpg is NULL\n");936		return ERR_PTR(-ENOSYS);937	}938 939	se_tpg = tf->tf_ops->fabric_make_tpg(wwn, name);940	if (!se_tpg || IS_ERR(se_tpg))941		return ERR_PTR(-EINVAL);942 943	config_group_init_type_name(&se_tpg->tpg_group, name,944			&tf->tf_tpg_base_cit);945 946	config_group_init_type_name(&se_tpg->tpg_lun_group, "lun",947			&tf->tf_tpg_lun_cit);948	configfs_add_default_group(&se_tpg->tpg_lun_group,949			&se_tpg->tpg_group);950 951	config_group_init_type_name(&se_tpg->tpg_np_group, "np",952			&tf->tf_tpg_np_cit);953	configfs_add_default_group(&se_tpg->tpg_np_group,954			&se_tpg->tpg_group);955 956	config_group_init_type_name(&se_tpg->tpg_acl_group, "acls",957			&tf->tf_tpg_nacl_cit);958	configfs_add_default_group(&se_tpg->tpg_acl_group,959			&se_tpg->tpg_group);960 961	config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib",962			&tf->tf_tpg_attrib_cit);963	configfs_add_default_group(&se_tpg->tpg_attrib_group,964			&se_tpg->tpg_group);965 966	config_group_init_type_name(&se_tpg->tpg_auth_group, "auth",967			&tf->tf_tpg_auth_cit);968	configfs_add_default_group(&se_tpg->tpg_auth_group,969			&se_tpg->tpg_group);970 971	config_group_init_type_name(&se_tpg->tpg_param_group, "param",972			&tf->tf_tpg_param_cit);973	configfs_add_default_group(&se_tpg->tpg_param_group,974			&se_tpg->tpg_group);975 976	return &se_tpg->tpg_group;977}978 979static void target_fabric_drop_tpg(980	struct config_group *group,981	struct config_item *item)982{983	struct se_portal_group *se_tpg = container_of(to_config_group(item),984				struct se_portal_group, tpg_group);985 986	configfs_remove_default_groups(&se_tpg->tpg_group);987	config_item_put(item);988}989 990static void target_fabric_release_wwn(struct config_item *item)991{992	struct se_wwn *wwn = container_of(to_config_group(item),993				struct se_wwn, wwn_group);994	struct target_fabric_configfs *tf = wwn->wwn_tf;995 996	configfs_remove_default_groups(&wwn->fabric_stat_group);997	configfs_remove_default_groups(&wwn->param_group);998	tf->tf_ops->fabric_drop_wwn(wwn);999}1000 1001static struct configfs_item_operations target_fabric_tpg_item_ops = {1002	.release	= target_fabric_release_wwn,1003};1004 1005static struct configfs_group_operations target_fabric_tpg_group_ops = {1006	.make_group	= target_fabric_make_tpg,1007	.drop_item	= target_fabric_drop_tpg,1008};1009 1010TF_CIT_SETUP(tpg, &target_fabric_tpg_item_ops, &target_fabric_tpg_group_ops,1011		NULL);1012 1013/* End of tfc_tpg_cit */1014 1015/* Start of tfc_wwn_fabric_stats_cit */1016/*1017 * This is used as a placeholder for struct se_wwn->fabric_stat_group1018 * to allow fabrics access to ->fabric_stat_group->default_groups[]1019 */1020TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL);1021 1022/* End of tfc_wwn_fabric_stats_cit */1023 1024static ssize_t1025target_fabric_wwn_cmd_completion_affinity_show(struct config_item *item,1026					       char *page)1027{1028	struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,1029					  param_group);1030	return sprintf(page, "%d\n",1031		       wwn->cmd_compl_affinity == WORK_CPU_UNBOUND ?1032		       SE_COMPL_AFFINITY_CURR_CPU : wwn->cmd_compl_affinity);1033}1034 1035static ssize_t1036target_fabric_wwn_cmd_completion_affinity_store(struct config_item *item,1037						const char *page, size_t count)1038{1039	struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,1040					  param_group);1041	int compl_val;1042 1043	if (kstrtoint(page, 0, &compl_val))1044		return -EINVAL;1045 1046	switch (compl_val) {1047	case SE_COMPL_AFFINITY_CPUID:1048		wwn->cmd_compl_affinity = compl_val;1049		break;1050	case SE_COMPL_AFFINITY_CURR_CPU:1051		wwn->cmd_compl_affinity = WORK_CPU_UNBOUND;1052		break;1053	default:1054		if (compl_val < 0 || compl_val >= nr_cpu_ids ||1055		    !cpu_online(compl_val)) {1056			pr_err("Command completion value must be between %d and %d or an online CPU.\n",1057			       SE_COMPL_AFFINITY_CPUID,1058			       SE_COMPL_AFFINITY_CURR_CPU);1059			return -EINVAL;1060		}1061		wwn->cmd_compl_affinity = compl_val;1062	}1063 1064	return count;1065}1066CONFIGFS_ATTR(target_fabric_wwn_, cmd_completion_affinity);1067 1068static ssize_t1069target_fabric_wwn_default_submit_type_show(struct config_item *item,1070					   char *page)1071{1072	struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,1073					  param_group);1074	return sysfs_emit(page, "%u\n",1075			  wwn->wwn_tf->tf_ops->default_submit_type);1076}1077CONFIGFS_ATTR_RO(target_fabric_wwn_, default_submit_type);1078 1079static ssize_t1080target_fabric_wwn_direct_submit_supported_show(struct config_item *item,1081					       char *page)1082{1083	struct se_wwn *wwn = container_of(to_config_group(item), struct se_wwn,1084					  param_group);1085	return sysfs_emit(page, "%u\n",1086			  wwn->wwn_tf->tf_ops->direct_submit_supp);1087}1088CONFIGFS_ATTR_RO(target_fabric_wwn_, direct_submit_supported);1089 1090static struct configfs_attribute *target_fabric_wwn_param_attrs[] = {1091	&target_fabric_wwn_attr_cmd_completion_affinity,1092	&target_fabric_wwn_attr_default_submit_type,1093	&target_fabric_wwn_attr_direct_submit_supported,1094	NULL,1095};1096 1097TF_CIT_SETUP(wwn_param, NULL, NULL, target_fabric_wwn_param_attrs);1098 1099/* Start of tfc_wwn_cit */1100 1101static struct config_group *target_fabric_make_wwn(1102	struct config_group *group,1103	const char *name)1104{1105	struct target_fabric_configfs *tf = container_of(group,1106				struct target_fabric_configfs, tf_group);1107	struct se_wwn *wwn;1108 1109	if (!tf->tf_ops->fabric_make_wwn) {1110		pr_err("tf->tf_ops.fabric_make_wwn is NULL\n");1111		return ERR_PTR(-ENOSYS);1112	}1113 1114	wwn = tf->tf_ops->fabric_make_wwn(tf, group, name);1115	if (!wwn || IS_ERR(wwn))1116		return ERR_PTR(-EINVAL);1117 1118	wwn->cmd_compl_affinity = SE_COMPL_AFFINITY_CPUID;1119	wwn->wwn_tf = tf;1120 1121	config_group_init_type_name(&wwn->wwn_group, name, &tf->tf_tpg_cit);1122 1123	config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics",1124			&tf->tf_wwn_fabric_stats_cit);1125	configfs_add_default_group(&wwn->fabric_stat_group, &wwn->wwn_group);1126 1127	config_group_init_type_name(&wwn->param_group, "param",1128			&tf->tf_wwn_param_cit);1129	configfs_add_default_group(&wwn->param_group, &wwn->wwn_group);1130 1131	if (tf->tf_ops->add_wwn_groups)1132		tf->tf_ops->add_wwn_groups(wwn);1133	return &wwn->wwn_group;1134}1135 1136static void target_fabric_drop_wwn(1137	struct config_group *group,1138	struct config_item *item)1139{1140	struct se_wwn *wwn = container_of(to_config_group(item),1141				struct se_wwn, wwn_group);1142 1143	configfs_remove_default_groups(&wwn->wwn_group);1144	config_item_put(item);1145}1146 1147static struct configfs_group_operations target_fabric_wwn_group_ops = {1148	.make_group	= target_fabric_make_wwn,1149	.drop_item	= target_fabric_drop_wwn,1150};1151 1152TF_CIT_SETUP_DRV(wwn, NULL, &target_fabric_wwn_group_ops);1153TF_CIT_SETUP_DRV(discovery, NULL, NULL);1154 1155int target_fabric_setup_cits(struct target_fabric_configfs *tf)1156{1157	int ret;1158 1159	target_fabric_setup_discovery_cit(tf);1160	target_fabric_setup_wwn_cit(tf);1161	target_fabric_setup_wwn_fabric_stats_cit(tf);1162	target_fabric_setup_wwn_param_cit(tf);1163	target_fabric_setup_tpg_cit(tf);1164 1165	ret = target_fabric_setup_tpg_base_cit(tf);1166	if (ret)1167		return ret;1168 1169	target_fabric_setup_tpg_port_cit(tf);1170	target_fabric_setup_tpg_port_stat_cit(tf);1171	target_fabric_setup_tpg_lun_cit(tf);1172	target_fabric_setup_tpg_np_cit(tf);1173	target_fabric_setup_tpg_np_base_cit(tf);1174	target_fabric_setup_tpg_attrib_cit(tf);1175	target_fabric_setup_tpg_auth_cit(tf);1176	target_fabric_setup_tpg_param_cit(tf);1177	target_fabric_setup_tpg_nacl_cit(tf);1178	target_fabric_setup_tpg_nacl_base_cit(tf);1179	target_fabric_setup_tpg_nacl_attrib_cit(tf);1180	target_fabric_setup_tpg_nacl_auth_cit(tf);1181	target_fabric_setup_tpg_nacl_param_cit(tf);1182	target_fabric_setup_tpg_nacl_stat_cit(tf);1183	target_fabric_setup_tpg_mappedlun_cit(tf);1184	target_fabric_setup_tpg_mappedlun_stat_cit(tf);1185 1186	return 0;1187}1188