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