linux/drivers/target/target_core_fabric_configfs.c
<<
>>
Prefs
   1/*******************************************************************************
   2* Filename: target_core_fabric_configfs.c
   3 *
   4 * This file contains generic fabric module configfs infrastructure for
   5 * TCM v4.x code
   6 *
   7 * (c) Copyright 2010-2012 RisingTide Systems LLC.
   8 *
   9 * Nicholas A. Bellinger <nab@linux-iscsi.org>
  10*
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License as published by
  13 * the Free Software Foundation; either version 2 of the License, or
  14 * (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 ****************************************************************************/
  21
  22#include <linux/module.h>
  23#include <linux/moduleparam.h>
  24#include <linux/utsname.h>
  25#include <linux/init.h>
  26#include <linux/fs.h>
  27#include <linux/namei.h>
  28#include <linux/slab.h>
  29#include <linux/types.h>
  30#include <linux/delay.h>
  31#include <linux/unistd.h>
  32#include <linux/string.h>
  33#include <linux/syscalls.h>
  34#include <linux/configfs.h>
  35
  36#include <target/target_core_base.h>
  37#include <target/target_core_fabric.h>
  38#include <target/target_core_fabric_configfs.h>
  39#include <target/target_core_configfs.h>
  40#include <target/configfs_macros.h>
  41
  42#include "target_core_internal.h"
  43#include "target_core_alua.h"
  44#include "target_core_pr.h"
  45
  46#define TF_CIT_SETUP(_name, _item_ops, _group_ops, _attrs)              \
  47static void target_fabric_setup_##_name##_cit(struct target_fabric_configfs *tf) \
  48{                                                                       \
  49        struct target_fabric_configfs_template *tfc = &tf->tf_cit_tmpl; \
  50        struct config_item_type *cit = &tfc->tfc_##_name##_cit;         \
  51                                                                        \
  52        cit->ct_item_ops = _item_ops;                                   \
  53        cit->ct_group_ops = _group_ops;                                 \
  54        cit->ct_attrs = _attrs;                                         \
  55        cit->ct_owner = tf->tf_module;                                  \
  56        pr_debug("Setup generic %s\n", __stringify(_name));             \
  57}
  58
  59/* Start of tfc_tpg_mappedlun_cit */
  60
  61static int target_fabric_mappedlun_link(
  62        struct config_item *lun_acl_ci,
  63        struct config_item *lun_ci)
  64{
  65        struct se_dev_entry *deve;
  66        struct se_lun *lun = container_of(to_config_group(lun_ci),
  67                        struct se_lun, lun_group);
  68        struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),
  69                        struct se_lun_acl, se_lun_group);
  70        struct se_portal_group *se_tpg;
  71        struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s;
  72        int ret = 0, lun_access;
  73
  74        if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) {
  75                pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:"
  76                        " %p to struct lun: %p\n", lun_ci, lun);
  77                return -EFAULT;
  78        }
  79        /*
  80         * Ensure that the source port exists
  81         */
  82        if (!lun->lun_sep || !lun->lun_sep->sep_tpg) {
  83                pr_err("Source se_lun->lun_sep or lun->lun_sep->sep"
  84                                "_tpg does not exist\n");
  85                return -EINVAL;
  86        }
  87        se_tpg = lun->lun_sep->sep_tpg;
  88
  89        nacl_ci = &lun_acl_ci->ci_parent->ci_group->cg_item;
  90        tpg_ci = &nacl_ci->ci_group->cg_item;
  91        wwn_ci = &tpg_ci->ci_group->cg_item;
  92        tpg_ci_s = &lun_ci->ci_parent->ci_group->cg_item;
  93        wwn_ci_s = &tpg_ci_s->ci_group->cg_item;
  94        /*
  95         * Make sure the SymLink is going to the same $FABRIC/$WWN/tpgt_$TPGT
  96         */
  97        if (strcmp(config_item_name(wwn_ci), config_item_name(wwn_ci_s))) {
  98                pr_err("Illegal Initiator ACL SymLink outside of %s\n",
  99                        config_item_name(wwn_ci));
 100                return -EINVAL;
 101        }
 102        if (strcmp(config_item_name(tpg_ci), config_item_name(tpg_ci_s))) {
 103                pr_err("Illegal Initiator ACL Symlink outside of %s"
 104                        " TPGT: %s\n", config_item_name(wwn_ci),
 105                        config_item_name(tpg_ci));
 106                return -EINVAL;
 107        }
 108        /*
 109         * If this struct se_node_acl was dynamically generated with
 110         * tpg_1/attrib/generate_node_acls=1, use the existing deve->lun_flags,
 111         * which be will write protected (READ-ONLY) when
 112         * tpg_1/attrib/demo_mode_write_protect=1
 113         */
 114        spin_lock_irq(&lacl->se_lun_nacl->device_list_lock);
 115        deve = lacl->se_lun_nacl->device_list[lacl->mapped_lun];
 116        if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)
 117                lun_access = deve->lun_flags;
 118        else
 119                lun_access =
 120                        (se_tpg->se_tpg_tfo->tpg_check_prod_mode_write_protect(
 121                                se_tpg)) ? TRANSPORT_LUNFLAGS_READ_ONLY :
 122                                           TRANSPORT_LUNFLAGS_READ_WRITE;
 123        spin_unlock_irq(&lacl->se_lun_nacl->device_list_lock);
 124        /*
 125         * Determine the actual mapped LUN value user wants..
 126         *
 127         * This value is what the SCSI Initiator actually sees the
 128         * iscsi/$IQN/$TPGT/lun/lun_* as on their SCSI Initiator Ports.
 129         */
 130        ret = core_dev_add_initiator_node_lun_acl(se_tpg, lacl,
 131                        lun->unpacked_lun, lun_access);
 132
 133        return (ret < 0) ? -EINVAL : 0;
 134}
 135
 136static int target_fabric_mappedlun_unlink(
 137        struct config_item *lun_acl_ci,
 138        struct config_item *lun_ci)
 139{
 140        struct se_lun *lun;
 141        struct se_lun_acl *lacl = container_of(to_config_group(lun_acl_ci),
 142                        struct se_lun_acl, se_lun_group);
 143        struct se_node_acl *nacl = lacl->se_lun_nacl;
 144        struct se_dev_entry *deve = nacl->device_list[lacl->mapped_lun];
 145        struct se_portal_group *se_tpg;
 146        /*
 147         * Determine if the underlying MappedLUN has already been released..
 148         */
 149        if (!deve->se_lun)
 150                return 0;
 151
 152        lun = container_of(to_config_group(lun_ci), struct se_lun, lun_group);
 153        se_tpg = lun->lun_sep->sep_tpg;
 154
 155        core_dev_del_initiator_node_lun_acl(se_tpg, lun, lacl);
 156        return 0;
 157}
 158
 159CONFIGFS_EATTR_STRUCT(target_fabric_mappedlun, se_lun_acl);
 160#define TCM_MAPPEDLUN_ATTR(_name, _mode)                                \
 161static struct target_fabric_mappedlun_attribute target_fabric_mappedlun_##_name = \
 162        __CONFIGFS_EATTR(_name, _mode,                                  \
 163        target_fabric_mappedlun_show_##_name,                           \
 164        target_fabric_mappedlun_store_##_name);
 165
 166static ssize_t target_fabric_mappedlun_show_write_protect(
 167        struct se_lun_acl *lacl,
 168        char *page)
 169{
 170        struct se_node_acl *se_nacl = lacl->se_lun_nacl;
 171        struct se_dev_entry *deve;
 172        ssize_t len;
 173
 174        spin_lock_irq(&se_nacl->device_list_lock);
 175        deve = se_nacl->device_list[lacl->mapped_lun];
 176        len = sprintf(page, "%d\n",
 177                        (deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) ?
 178                        1 : 0);
 179        spin_unlock_irq(&se_nacl->device_list_lock);
 180
 181        return len;
 182}
 183
 184static ssize_t target_fabric_mappedlun_store_write_protect(
 185        struct se_lun_acl *lacl,
 186        const char *page,
 187        size_t count)
 188{
 189        struct se_node_acl *se_nacl = lacl->se_lun_nacl;
 190        struct se_portal_group *se_tpg = se_nacl->se_tpg;
 191        unsigned long op;
 192
 193        if (strict_strtoul(page, 0, &op))
 194                return -EINVAL;
 195
 196        if ((op != 1) && (op != 0))
 197                return -EINVAL;
 198
 199        core_update_device_list_access(lacl->mapped_lun, (op) ?
 200                        TRANSPORT_LUNFLAGS_READ_ONLY :
 201                        TRANSPORT_LUNFLAGS_READ_WRITE,
 202                        lacl->se_lun_nacl);
 203
 204        pr_debug("%s_ConfigFS: Changed Initiator ACL: %s"
 205                " Mapped LUN: %u Write Protect bit to %s\n",
 206                se_tpg->se_tpg_tfo->get_fabric_name(),
 207                lacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF");
 208
 209        return count;
 210
 211}
 212
 213TCM_MAPPEDLUN_ATTR(write_protect, S_IRUGO | S_IWUSR);
 214
 215CONFIGFS_EATTR_OPS(target_fabric_mappedlun, se_lun_acl, se_lun_group);
 216
 217static void target_fabric_mappedlun_release(struct config_item *item)
 218{
 219        struct se_lun_acl *lacl = container_of(to_config_group(item),
 220                                struct se_lun_acl, se_lun_group);
 221        struct se_portal_group *se_tpg = lacl->se_lun_nacl->se_tpg;
 222
 223        core_dev_free_initiator_node_lun_acl(se_tpg, lacl);
 224}
 225
 226static struct configfs_attribute *target_fabric_mappedlun_attrs[] = {
 227        &target_fabric_mappedlun_write_protect.attr,
 228        NULL,
 229};
 230
 231static struct configfs_item_operations target_fabric_mappedlun_item_ops = {
 232        .release                = target_fabric_mappedlun_release,
 233        .show_attribute         = target_fabric_mappedlun_attr_show,
 234        .store_attribute        = target_fabric_mappedlun_attr_store,
 235        .allow_link             = target_fabric_mappedlun_link,
 236        .drop_link              = target_fabric_mappedlun_unlink,
 237};
 238
 239TF_CIT_SETUP(tpg_mappedlun, &target_fabric_mappedlun_item_ops, NULL,
 240                target_fabric_mappedlun_attrs);
 241
 242/* End of tfc_tpg_mappedlun_cit */
 243
 244/* Start of tfc_tpg_mappedlun_port_cit */
 245
 246static struct config_group *target_core_mappedlun_stat_mkdir(
 247        struct config_group *group,
 248        const char *name)
 249{
 250        return ERR_PTR(-ENOSYS);
 251}
 252
 253static void target_core_mappedlun_stat_rmdir(
 254        struct config_group *group,
 255        struct config_item *item)
 256{
 257        return;
 258}
 259
 260static struct configfs_group_operations target_fabric_mappedlun_stat_group_ops = {
 261        .make_group             = target_core_mappedlun_stat_mkdir,
 262        .drop_item              = target_core_mappedlun_stat_rmdir,
 263};
 264
 265TF_CIT_SETUP(tpg_mappedlun_stat, NULL, &target_fabric_mappedlun_stat_group_ops,
 266                NULL);
 267
 268/* End of tfc_tpg_mappedlun_port_cit */
 269
 270/* Start of tfc_tpg_nacl_attrib_cit */
 271
 272CONFIGFS_EATTR_OPS(target_fabric_nacl_attrib, se_node_acl, acl_attrib_group);
 273
 274static struct configfs_item_operations target_fabric_nacl_attrib_item_ops = {
 275        .show_attribute         = target_fabric_nacl_attrib_attr_show,
 276        .store_attribute        = target_fabric_nacl_attrib_attr_store,
 277};
 278
 279TF_CIT_SETUP(tpg_nacl_attrib, &target_fabric_nacl_attrib_item_ops, NULL, NULL);
 280
 281/* End of tfc_tpg_nacl_attrib_cit */
 282
 283/* Start of tfc_tpg_nacl_auth_cit */
 284
 285CONFIGFS_EATTR_OPS(target_fabric_nacl_auth, se_node_acl, acl_auth_group);
 286
 287static struct configfs_item_operations target_fabric_nacl_auth_item_ops = {
 288        .show_attribute         = target_fabric_nacl_auth_attr_show,
 289        .store_attribute        = target_fabric_nacl_auth_attr_store,
 290};
 291
 292TF_CIT_SETUP(tpg_nacl_auth, &target_fabric_nacl_auth_item_ops, NULL, NULL);
 293
 294/* End of tfc_tpg_nacl_auth_cit */
 295
 296/* Start of tfc_tpg_nacl_param_cit */
 297
 298CONFIGFS_EATTR_OPS(target_fabric_nacl_param, se_node_acl, acl_param_group);
 299
 300static struct configfs_item_operations target_fabric_nacl_param_item_ops = {
 301        .show_attribute         = target_fabric_nacl_param_attr_show,
 302        .store_attribute        = target_fabric_nacl_param_attr_store,
 303};
 304
 305TF_CIT_SETUP(tpg_nacl_param, &target_fabric_nacl_param_item_ops, NULL, NULL);
 306
 307/* End of tfc_tpg_nacl_param_cit */
 308
 309/* Start of tfc_tpg_nacl_base_cit */
 310
 311CONFIGFS_EATTR_OPS(target_fabric_nacl_base, se_node_acl, acl_group);
 312
 313static struct config_group *target_fabric_make_mappedlun(
 314        struct config_group *group,
 315        const char *name)
 316{
 317        struct se_node_acl *se_nacl = container_of(group,
 318                        struct se_node_acl, acl_group);
 319        struct se_portal_group *se_tpg = se_nacl->se_tpg;
 320        struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
 321        struct se_lun_acl *lacl;
 322        struct config_item *acl_ci;
 323        struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
 324        char *buf;
 325        unsigned long mapped_lun;
 326        int ret = 0;
 327
 328        acl_ci = &group->cg_item;
 329        if (!acl_ci) {
 330                pr_err("Unable to locatel acl_ci\n");
 331                return NULL;
 332        }
 333
 334        buf = kzalloc(strlen(name) + 1, GFP_KERNEL);
 335        if (!buf) {
 336                pr_err("Unable to allocate memory for name buf\n");
 337                return ERR_PTR(-ENOMEM);
 338        }
 339        snprintf(buf, strlen(name) + 1, "%s", name);
 340        /*
 341         * Make sure user is creating iscsi/$IQN/$TPGT/acls/$INITIATOR/lun_$ID.
 342         */
 343        if (strstr(buf, "lun_") != buf) {
 344                pr_err("Unable to locate \"lun_\" from buf: %s"
 345                        " name: %s\n", buf, name);
 346                ret = -EINVAL;
 347                goto out;
 348        }
 349        /*
 350         * Determine the Mapped LUN value.  This is what the SCSI Initiator
 351         * Port will actually see.
 352         */
 353        if (strict_strtoul(buf + 4, 0, &mapped_lun) || mapped_lun > UINT_MAX) {
 354                ret = -EINVAL;
 355                goto out;
 356        }
 357
 358        lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun,
 359                        config_item_name(acl_ci), &ret);
 360        if (!lacl) {
 361                ret = -EINVAL;
 362                goto out;
 363        }
 364
 365        lacl_cg = &lacl->se_lun_group;
 366        lacl_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
 367                                GFP_KERNEL);
 368        if (!lacl_cg->default_groups) {
 369                pr_err("Unable to allocate lacl_cg->default_groups\n");
 370                ret = -ENOMEM;
 371                goto out;
 372        }
 373
 374        config_group_init_type_name(&lacl->se_lun_group, name,
 375                        &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_cit);
 376        config_group_init_type_name(&lacl->ml_stat_grps.stat_group,
 377                        "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_mappedlun_stat_cit);
 378        lacl_cg->default_groups[0] = &lacl->ml_stat_grps.stat_group;
 379        lacl_cg->default_groups[1] = NULL;
 380
 381        ml_stat_grp = &lacl->ml_stat_grps.stat_group;
 382        ml_stat_grp->default_groups = kmalloc(sizeof(struct config_group *) * 3,
 383                                GFP_KERNEL);
 384        if (!ml_stat_grp->default_groups) {
 385                pr_err("Unable to allocate ml_stat_grp->default_groups\n");
 386                ret = -ENOMEM;
 387                goto out;
 388        }
 389        target_stat_setup_mappedlun_default_groups(lacl);
 390
 391        kfree(buf);
 392        return &lacl->se_lun_group;
 393out:
 394        if (lacl_cg)
 395                kfree(lacl_cg->default_groups);
 396        kfree(buf);
 397        return ERR_PTR(ret);
 398}
 399
 400static void target_fabric_drop_mappedlun(
 401        struct config_group *group,
 402        struct config_item *item)
 403{
 404        struct se_lun_acl *lacl = container_of(to_config_group(item),
 405                        struct se_lun_acl, se_lun_group);
 406        struct config_item *df_item;
 407        struct config_group *lacl_cg = NULL, *ml_stat_grp = NULL;
 408        int i;
 409
 410        ml_stat_grp = &lacl->ml_stat_grps.stat_group;
 411        for (i = 0; ml_stat_grp->default_groups[i]; i++) {
 412                df_item = &ml_stat_grp->default_groups[i]->cg_item;
 413                ml_stat_grp->default_groups[i] = NULL;
 414                config_item_put(df_item);
 415        }
 416        kfree(ml_stat_grp->default_groups);
 417
 418        lacl_cg = &lacl->se_lun_group;
 419        for (i = 0; lacl_cg->default_groups[i]; i++) {
 420                df_item = &lacl_cg->default_groups[i]->cg_item;
 421                lacl_cg->default_groups[i] = NULL;
 422                config_item_put(df_item);
 423        }
 424        kfree(lacl_cg->default_groups);
 425
 426        config_item_put(item);
 427}
 428
 429static void target_fabric_nacl_base_release(struct config_item *item)
 430{
 431        struct se_node_acl *se_nacl = container_of(to_config_group(item),
 432                        struct se_node_acl, acl_group);
 433        struct se_portal_group *se_tpg = se_nacl->se_tpg;
 434        struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
 435
 436        tf->tf_ops.fabric_drop_nodeacl(se_nacl);
 437}
 438
 439static struct configfs_item_operations target_fabric_nacl_base_item_ops = {
 440        .release                = target_fabric_nacl_base_release,
 441        .show_attribute         = target_fabric_nacl_base_attr_show,
 442        .store_attribute        = target_fabric_nacl_base_attr_store,
 443};
 444
 445static struct configfs_group_operations target_fabric_nacl_base_group_ops = {
 446        .make_group             = target_fabric_make_mappedlun,
 447        .drop_item              = target_fabric_drop_mappedlun,
 448};
 449
 450TF_CIT_SETUP(tpg_nacl_base, &target_fabric_nacl_base_item_ops,
 451                &target_fabric_nacl_base_group_ops, NULL);
 452
 453/* End of tfc_tpg_nacl_base_cit */
 454
 455/* Start of tfc_node_fabric_stats_cit */
 456/*
 457 * This is used as a placeholder for struct se_node_acl->acl_fabric_stat_group
 458 * to allow fabrics access to ->acl_fabric_stat_group->default_groups[]
 459 */
 460TF_CIT_SETUP(tpg_nacl_stat, NULL, NULL, NULL);
 461
 462/* End of tfc_wwn_fabric_stats_cit */
 463
 464/* Start of tfc_tpg_nacl_cit */
 465
 466static struct config_group *target_fabric_make_nodeacl(
 467        struct config_group *group,
 468        const char *name)
 469{
 470        struct se_portal_group *se_tpg = container_of(group,
 471                        struct se_portal_group, tpg_acl_group);
 472        struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
 473        struct se_node_acl *se_nacl;
 474        struct config_group *nacl_cg;
 475
 476        if (!tf->tf_ops.fabric_make_nodeacl) {
 477                pr_err("tf->tf_ops.fabric_make_nodeacl is NULL\n");
 478                return ERR_PTR(-ENOSYS);
 479        }
 480
 481        se_nacl = tf->tf_ops.fabric_make_nodeacl(se_tpg, group, name);
 482        if (IS_ERR(se_nacl))
 483                return ERR_CAST(se_nacl);
 484
 485        nacl_cg = &se_nacl->acl_group;
 486        nacl_cg->default_groups = se_nacl->acl_default_groups;
 487        nacl_cg->default_groups[0] = &se_nacl->acl_attrib_group;
 488        nacl_cg->default_groups[1] = &se_nacl->acl_auth_group;
 489        nacl_cg->default_groups[2] = &se_nacl->acl_param_group;
 490        nacl_cg->default_groups[3] = &se_nacl->acl_fabric_stat_group;
 491        nacl_cg->default_groups[4] = NULL;
 492
 493        config_group_init_type_name(&se_nacl->acl_group, name,
 494                        &TF_CIT_TMPL(tf)->tfc_tpg_nacl_base_cit);
 495        config_group_init_type_name(&se_nacl->acl_attrib_group, "attrib",
 496                        &TF_CIT_TMPL(tf)->tfc_tpg_nacl_attrib_cit);
 497        config_group_init_type_name(&se_nacl->acl_auth_group, "auth",
 498                        &TF_CIT_TMPL(tf)->tfc_tpg_nacl_auth_cit);
 499        config_group_init_type_name(&se_nacl->acl_param_group, "param",
 500                        &TF_CIT_TMPL(tf)->tfc_tpg_nacl_param_cit);
 501        config_group_init_type_name(&se_nacl->acl_fabric_stat_group,
 502                        "fabric_statistics",
 503                        &TF_CIT_TMPL(tf)->tfc_tpg_nacl_stat_cit);
 504
 505        return &se_nacl->acl_group;
 506}
 507
 508static void target_fabric_drop_nodeacl(
 509        struct config_group *group,
 510        struct config_item *item)
 511{
 512        struct se_node_acl *se_nacl = container_of(to_config_group(item),
 513                        struct se_node_acl, acl_group);
 514        struct config_item *df_item;
 515        struct config_group *nacl_cg;
 516        int i;
 517
 518        nacl_cg = &se_nacl->acl_group;
 519        for (i = 0; nacl_cg->default_groups[i]; i++) {
 520                df_item = &nacl_cg->default_groups[i]->cg_item;
 521                nacl_cg->default_groups[i] = NULL;
 522                config_item_put(df_item);
 523        }
 524        /*
 525         * struct se_node_acl free is done in target_fabric_nacl_base_release()
 526         */
 527        config_item_put(item);
 528}
 529
 530static struct configfs_group_operations target_fabric_nacl_group_ops = {
 531        .make_group     = target_fabric_make_nodeacl,
 532        .drop_item      = target_fabric_drop_nodeacl,
 533};
 534
 535TF_CIT_SETUP(tpg_nacl, NULL, &target_fabric_nacl_group_ops, NULL);
 536
 537/* End of tfc_tpg_nacl_cit */
 538
 539/* Start of tfc_tpg_np_base_cit */
 540
 541CONFIGFS_EATTR_OPS(target_fabric_np_base, se_tpg_np, tpg_np_group);
 542
 543static void target_fabric_np_base_release(struct config_item *item)
 544{
 545        struct se_tpg_np *se_tpg_np = container_of(to_config_group(item),
 546                                struct se_tpg_np, tpg_np_group);
 547        struct se_portal_group *se_tpg = se_tpg_np->tpg_np_parent;
 548        struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
 549
 550        tf->tf_ops.fabric_drop_np(se_tpg_np);
 551}
 552
 553static struct configfs_item_operations target_fabric_np_base_item_ops = {
 554        .release                = target_fabric_np_base_release,
 555        .show_attribute         = target_fabric_np_base_attr_show,
 556        .store_attribute        = target_fabric_np_base_attr_store,
 557};
 558
 559TF_CIT_SETUP(tpg_np_base, &target_fabric_np_base_item_ops, NULL, NULL);
 560
 561/* End of tfc_tpg_np_base_cit */
 562
 563/* Start of tfc_tpg_np_cit */
 564
 565static struct config_group *target_fabric_make_np(
 566        struct config_group *group,
 567        const char *name)
 568{
 569        struct se_portal_group *se_tpg = container_of(group,
 570                                struct se_portal_group, tpg_np_group);
 571        struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
 572        struct se_tpg_np *se_tpg_np;
 573
 574        if (!tf->tf_ops.fabric_make_np) {
 575                pr_err("tf->tf_ops.fabric_make_np is NULL\n");
 576                return ERR_PTR(-ENOSYS);
 577        }
 578
 579        se_tpg_np = tf->tf_ops.fabric_make_np(se_tpg, group, name);
 580        if (!se_tpg_np || IS_ERR(se_tpg_np))
 581                return ERR_PTR(-EINVAL);
 582
 583        se_tpg_np->tpg_np_parent = se_tpg;
 584        config_group_init_type_name(&se_tpg_np->tpg_np_group, name,
 585                        &TF_CIT_TMPL(tf)->tfc_tpg_np_base_cit);
 586
 587        return &se_tpg_np->tpg_np_group;
 588}
 589
 590static void target_fabric_drop_np(
 591        struct config_group *group,
 592        struct config_item *item)
 593{
 594        /*
 595         * struct se_tpg_np is released via target_fabric_np_base_release()
 596         */
 597        config_item_put(item);
 598}
 599
 600static struct configfs_group_operations target_fabric_np_group_ops = {
 601        .make_group     = &target_fabric_make_np,
 602        .drop_item      = &target_fabric_drop_np,
 603};
 604
 605TF_CIT_SETUP(tpg_np, NULL, &target_fabric_np_group_ops, NULL);
 606
 607/* End of tfc_tpg_np_cit */
 608
 609/* Start of tfc_tpg_port_cit */
 610
 611CONFIGFS_EATTR_STRUCT(target_fabric_port, se_lun);
 612#define TCM_PORT_ATTR(_name, _mode)                                     \
 613static struct target_fabric_port_attribute target_fabric_port_##_name = \
 614        __CONFIGFS_EATTR(_name, _mode,                                  \
 615        target_fabric_port_show_attr_##_name,                           \
 616        target_fabric_port_store_attr_##_name);
 617
 618#define TCM_PORT_ATTOR_RO(_name)                                        \
 619        __CONFIGFS_EATTR_RO(_name,                                      \
 620        target_fabric_port_show_attr_##_name);
 621
 622/*
 623 * alua_tg_pt_gp
 624 */
 625static ssize_t target_fabric_port_show_attr_alua_tg_pt_gp(
 626        struct se_lun *lun,
 627        char *page)
 628{
 629        if (!lun || !lun->lun_sep)
 630                return -ENODEV;
 631
 632        return core_alua_show_tg_pt_gp_info(lun->lun_sep, page);
 633}
 634
 635static ssize_t target_fabric_port_store_attr_alua_tg_pt_gp(
 636        struct se_lun *lun,
 637        const char *page,
 638        size_t count)
 639{
 640        if (!lun || !lun->lun_sep)
 641                return -ENODEV;
 642
 643        return core_alua_store_tg_pt_gp_info(lun->lun_sep, page, count);
 644}
 645
 646TCM_PORT_ATTR(alua_tg_pt_gp, S_IRUGO | S_IWUSR);
 647
 648/*
 649 * alua_tg_pt_offline
 650 */
 651static ssize_t target_fabric_port_show_attr_alua_tg_pt_offline(
 652        struct se_lun *lun,
 653        char *page)
 654{
 655        if (!lun || !lun->lun_sep)
 656                return -ENODEV;
 657
 658        return core_alua_show_offline_bit(lun, page);
 659}
 660
 661static ssize_t target_fabric_port_store_attr_alua_tg_pt_offline(
 662        struct se_lun *lun,
 663        const char *page,
 664        size_t count)
 665{
 666        if (!lun || !lun->lun_sep)
 667                return -ENODEV;
 668
 669        return core_alua_store_offline_bit(lun, page, count);
 670}
 671
 672TCM_PORT_ATTR(alua_tg_pt_offline, S_IRUGO | S_IWUSR);
 673
 674/*
 675 * alua_tg_pt_status
 676 */
 677static ssize_t target_fabric_port_show_attr_alua_tg_pt_status(
 678        struct se_lun *lun,
 679        char *page)
 680{
 681        if (!lun || !lun->lun_sep)
 682                return -ENODEV;
 683
 684        return core_alua_show_secondary_status(lun, page);
 685}
 686
 687static ssize_t target_fabric_port_store_attr_alua_tg_pt_status(
 688        struct se_lun *lun,
 689        const char *page,
 690        size_t count)
 691{
 692        if (!lun || !lun->lun_sep)
 693                return -ENODEV;
 694
 695        return core_alua_store_secondary_status(lun, page, count);
 696}
 697
 698TCM_PORT_ATTR(alua_tg_pt_status, S_IRUGO | S_IWUSR);
 699
 700/*
 701 * alua_tg_pt_write_md
 702 */
 703static ssize_t target_fabric_port_show_attr_alua_tg_pt_write_md(
 704        struct se_lun *lun,
 705        char *page)
 706{
 707        if (!lun || !lun->lun_sep)
 708                return -ENODEV;
 709
 710        return core_alua_show_secondary_write_metadata(lun, page);
 711}
 712
 713static ssize_t target_fabric_port_store_attr_alua_tg_pt_write_md(
 714        struct se_lun *lun,
 715        const char *page,
 716        size_t count)
 717{
 718        if (!lun || !lun->lun_sep)
 719                return -ENODEV;
 720
 721        return core_alua_store_secondary_write_metadata(lun, page, count);
 722}
 723
 724TCM_PORT_ATTR(alua_tg_pt_write_md, S_IRUGO | S_IWUSR);
 725
 726
 727static struct configfs_attribute *target_fabric_port_attrs[] = {
 728        &target_fabric_port_alua_tg_pt_gp.attr,
 729        &target_fabric_port_alua_tg_pt_offline.attr,
 730        &target_fabric_port_alua_tg_pt_status.attr,
 731        &target_fabric_port_alua_tg_pt_write_md.attr,
 732        NULL,
 733};
 734
 735CONFIGFS_EATTR_OPS(target_fabric_port, se_lun, lun_group);
 736
 737static int target_fabric_port_link(
 738        struct config_item *lun_ci,
 739        struct config_item *se_dev_ci)
 740{
 741        struct config_item *tpg_ci;
 742        struct se_lun *lun = container_of(to_config_group(lun_ci),
 743                                struct se_lun, lun_group);
 744        struct se_lun *lun_p;
 745        struct se_portal_group *se_tpg;
 746        struct se_device *dev =
 747                container_of(to_config_group(se_dev_ci), struct se_device, dev_group);
 748        struct target_fabric_configfs *tf;
 749        int ret;
 750
 751        if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) {
 752                pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:"
 753                        " %p to struct se_device: %p\n", se_dev_ci, dev);
 754                return -EFAULT;
 755        }
 756
 757        if (!(dev->dev_flags & DF_CONFIGURED)) {
 758                pr_err("se_device not configured yet, cannot port link\n");
 759                return -ENODEV;
 760        }
 761
 762        tpg_ci = &lun_ci->ci_parent->ci_group->cg_item;
 763        se_tpg = container_of(to_config_group(tpg_ci),
 764                                struct se_portal_group, tpg_group);
 765        tf = se_tpg->se_tpg_wwn->wwn_tf;
 766
 767        if (lun->lun_se_dev !=  NULL) {
 768                pr_err("Port Symlink already exists\n");
 769                return -EEXIST;
 770        }
 771
 772        lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun);
 773        if (IS_ERR(lun_p)) {
 774                pr_err("core_dev_add_lun() failed\n");
 775                ret = PTR_ERR(lun_p);
 776                goto out;
 777        }
 778
 779        if (tf->tf_ops.fabric_post_link) {
 780                /*
 781                 * Call the optional fabric_post_link() to allow a
 782                 * fabric module to setup any additional state once
 783                 * core_dev_add_lun() has been called..
 784                 */
 785                tf->tf_ops.fabric_post_link(se_tpg, lun);
 786        }
 787
 788        return 0;
 789out:
 790        return ret;
 791}
 792
 793static int target_fabric_port_unlink(
 794        struct config_item *lun_ci,
 795        struct config_item *se_dev_ci)
 796{
 797        struct se_lun *lun = container_of(to_config_group(lun_ci),
 798                                struct se_lun, lun_group);
 799        struct se_portal_group *se_tpg = lun->lun_sep->sep_tpg;
 800        struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
 801
 802        if (tf->tf_ops.fabric_pre_unlink) {
 803                /*
 804                 * Call the optional fabric_pre_unlink() to allow a
 805                 * fabric module to release any additional stat before
 806                 * core_dev_del_lun() is called.
 807                */
 808                tf->tf_ops.fabric_pre_unlink(se_tpg, lun);
 809        }
 810
 811        core_dev_del_lun(se_tpg, lun->unpacked_lun);
 812        return 0;
 813}
 814
 815static struct configfs_item_operations target_fabric_port_item_ops = {
 816        .show_attribute         = target_fabric_port_attr_show,
 817        .store_attribute        = target_fabric_port_attr_store,
 818        .allow_link             = target_fabric_port_link,
 819        .drop_link              = target_fabric_port_unlink,
 820};
 821
 822TF_CIT_SETUP(tpg_port, &target_fabric_port_item_ops, NULL, target_fabric_port_attrs);
 823
 824/* End of tfc_tpg_port_cit */
 825
 826/* Start of tfc_tpg_port_stat_cit */
 827
 828static struct config_group *target_core_port_stat_mkdir(
 829        struct config_group *group,
 830        const char *name)
 831{
 832        return ERR_PTR(-ENOSYS);
 833}
 834
 835static void target_core_port_stat_rmdir(
 836        struct config_group *group,
 837        struct config_item *item)
 838{
 839        return;
 840}
 841
 842static struct configfs_group_operations target_fabric_port_stat_group_ops = {
 843        .make_group             = target_core_port_stat_mkdir,
 844        .drop_item              = target_core_port_stat_rmdir,
 845};
 846
 847TF_CIT_SETUP(tpg_port_stat, NULL, &target_fabric_port_stat_group_ops, NULL);
 848
 849/* End of tfc_tpg_port_stat_cit */
 850
 851/* Start of tfc_tpg_lun_cit */
 852
 853static struct config_group *target_fabric_make_lun(
 854        struct config_group *group,
 855        const char *name)
 856{
 857        struct se_lun *lun;
 858        struct se_portal_group *se_tpg = container_of(group,
 859                        struct se_portal_group, tpg_lun_group);
 860        struct target_fabric_configfs *tf = se_tpg->se_tpg_wwn->wwn_tf;
 861        struct config_group *lun_cg = NULL, *port_stat_grp = NULL;
 862        unsigned long unpacked_lun;
 863        int errno;
 864
 865        if (strstr(name, "lun_") != name) {
 866                pr_err("Unable to locate \'_\" in"
 867                                " \"lun_$LUN_NUMBER\"\n");
 868                return ERR_PTR(-EINVAL);
 869        }
 870        if (strict_strtoul(name + 4, 0, &unpacked_lun) || unpacked_lun > UINT_MAX)
 871                return ERR_PTR(-EINVAL);
 872
 873        lun = core_get_lun_from_tpg(se_tpg, unpacked_lun);
 874        if (!lun)
 875                return ERR_PTR(-EINVAL);
 876
 877        lun_cg = &lun->lun_group;
 878        lun_cg->default_groups = kmalloc(sizeof(struct config_group *) * 2,
 879                                GFP_KERNEL);
 880        if (!lun_cg->default_groups) {
 881                pr_err("Unable to allocate lun_cg->default_groups\n");
 882                return ERR_PTR(-ENOMEM);
 883        }
 884
 885        config_group_init_type_name(&lun->lun_group, name,
 886                        &TF_CIT_TMPL(tf)->tfc_tpg_port_cit);
 887        config_group_init_type_name(&lun->port_stat_grps.stat_group,
 888                        "statistics", &TF_CIT_TMPL(tf)->tfc_tpg_port_stat_cit);
 889        lun_cg->default_groups[0] = &lun->port_stat_grps.stat_group;
 890        lun_cg->default_groups[1] = NULL;
 891
 892        port_stat_grp = &lun->port_stat_grps.stat_group;
 893        port_stat_grp->default_groups =  kzalloc(sizeof(struct config_group) * 3,
 894                                GFP_KERNEL);
 895        if (!port_stat_grp->default_groups) {
 896                pr_err("Unable to allocate port_stat_grp->default_groups\n");
 897                errno = -ENOMEM;
 898                goto out;
 899        }
 900        target_stat_setup_port_default_groups(lun);
 901
 902        return &lun->lun_group;
 903out:
 904        if (lun_cg)
 905                kfree(lun_cg->default_groups);
 906        return ERR_PTR(errno);
 907}
 908
 909static void target_fabric_drop_lun(
 910        struct config_group *group,
 911        struct config_item *item)
 912{
 913        struct se_lun *lun = container_of(to_config_group(item),
 914                                struct se_lun, lun_group);
 915        struct config_item *df_item;
 916        struct config_group *lun_cg, *port_stat_grp;
 917        int i;
 918
 919        port_stat_grp = &lun->port_stat_grps.stat_group;
 920        for (i = 0; port_stat_grp->default_groups[i]; i++) {
 921                df_item = &port_stat_grp->default_groups[i]->cg_item;
 922                port_stat_grp->default_groups[i] = NULL;
 923                config_item_put(df_item);
 924        }
 925        kfree(port_stat_grp->default_groups);
 926
 927        lun_cg = &lun->lun_group;
 928        for (i = 0; lun_cg->default_groups[i]; i++) {
 929                df_item = &lun_cg->default_groups[i]->cg_item;
 930                lun_cg->default_groups[i] = NULL;
 931                config_item_put(df_item);
 932        }
 933        kfree(lun_cg->default_groups);
 934
 935        config_item_put(item);
 936}
 937
 938static struct configfs_group_operations target_fabric_lun_group_ops = {
 939        .make_group     = &target_fabric_make_lun,
 940        .drop_item      = &target_fabric_drop_lun,
 941};
 942
 943TF_CIT_SETUP(tpg_lun, NULL, &target_fabric_lun_group_ops, NULL);
 944
 945/* End of tfc_tpg_lun_cit */
 946
 947/* Start of tfc_tpg_attrib_cit */
 948
 949CONFIGFS_EATTR_OPS(target_fabric_tpg_attrib, se_portal_group, tpg_attrib_group);
 950
 951static struct configfs_item_operations target_fabric_tpg_attrib_item_ops = {
 952        .show_attribute         = target_fabric_tpg_attrib_attr_show,
 953        .store_attribute        = target_fabric_tpg_attrib_attr_store,
 954};
 955
 956TF_CIT_SETUP(tpg_attrib, &target_fabric_tpg_attrib_item_ops, NULL, NULL);
 957
 958/* End of tfc_tpg_attrib_cit */
 959
 960/* Start of tfc_tpg_param_cit */
 961
 962CONFIGFS_EATTR_OPS(target_fabric_tpg_param, se_portal_group, tpg_param_group);
 963
 964static struct configfs_item_operations target_fabric_tpg_param_item_ops = {
 965        .show_attribute         = target_fabric_tpg_param_attr_show,
 966        .store_attribute        = target_fabric_tpg_param_attr_store,
 967};
 968
 969TF_CIT_SETUP(tpg_param, &target_fabric_tpg_param_item_ops, NULL, NULL);
 970
 971/* End of tfc_tpg_param_cit */
 972
 973/* Start of tfc_tpg_base_cit */
 974/*
 975 * For use with TF_TPG_ATTR() and TF_TPG_ATTR_RO()
 976 */
 977CONFIGFS_EATTR_OPS(target_fabric_tpg, se_portal_group, tpg_group);
 978
 979static void target_fabric_tpg_release(struct config_item *item)
 980{
 981        struct se_portal_group *se_tpg = container_of(to_config_group(item),
 982                        struct se_portal_group, tpg_group);
 983        struct se_wwn *wwn = se_tpg->se_tpg_wwn;
 984        struct target_fabric_configfs *tf = wwn->wwn_tf;
 985
 986        tf->tf_ops.fabric_drop_tpg(se_tpg);
 987}
 988
 989static struct configfs_item_operations target_fabric_tpg_base_item_ops = {
 990        .release                = target_fabric_tpg_release,
 991        .show_attribute         = target_fabric_tpg_attr_show,
 992        .store_attribute        = target_fabric_tpg_attr_store,
 993};
 994
 995TF_CIT_SETUP(tpg_base, &target_fabric_tpg_base_item_ops, NULL, NULL);
 996
 997/* End of tfc_tpg_base_cit */
 998
 999/* Start of tfc_tpg_cit */
1000
1001static struct config_group *target_fabric_make_tpg(
1002        struct config_group *group,
1003        const char *name)
1004{
1005        struct se_wwn *wwn = container_of(group, struct se_wwn, wwn_group);
1006        struct target_fabric_configfs *tf = wwn->wwn_tf;
1007        struct se_portal_group *se_tpg;
1008
1009        if (!tf->tf_ops.fabric_make_tpg) {
1010                pr_err("tf->tf_ops.fabric_make_tpg is NULL\n");
1011                return ERR_PTR(-ENOSYS);
1012        }
1013
1014        se_tpg = tf->tf_ops.fabric_make_tpg(wwn, group, name);
1015        if (!se_tpg || IS_ERR(se_tpg))
1016                return ERR_PTR(-EINVAL);
1017        /*
1018         * Setup default groups from pre-allocated se_tpg->tpg_default_groups
1019         */
1020        se_tpg->tpg_group.default_groups = se_tpg->tpg_default_groups;
1021        se_tpg->tpg_group.default_groups[0] = &se_tpg->tpg_lun_group;
1022        se_tpg->tpg_group.default_groups[1] = &se_tpg->tpg_np_group;
1023        se_tpg->tpg_group.default_groups[2] = &se_tpg->tpg_acl_group;
1024        se_tpg->tpg_group.default_groups[3] = &se_tpg->tpg_attrib_group;
1025        se_tpg->tpg_group.default_groups[4] = &se_tpg->tpg_param_group;
1026        se_tpg->tpg_group.default_groups[5] = NULL;
1027
1028        config_group_init_type_name(&se_tpg->tpg_group, name,
1029                        &TF_CIT_TMPL(tf)->tfc_tpg_base_cit);
1030        config_group_init_type_name(&se_tpg->tpg_lun_group, "lun",
1031                        &TF_CIT_TMPL(tf)->tfc_tpg_lun_cit);
1032        config_group_init_type_name(&se_tpg->tpg_np_group, "np",
1033                        &TF_CIT_TMPL(tf)->tfc_tpg_np_cit);
1034        config_group_init_type_name(&se_tpg->tpg_acl_group, "acls",
1035                        &TF_CIT_TMPL(tf)->tfc_tpg_nacl_cit);
1036        config_group_init_type_name(&se_tpg->tpg_attrib_group, "attrib",
1037                        &TF_CIT_TMPL(tf)->tfc_tpg_attrib_cit);
1038        config_group_init_type_name(&se_tpg->tpg_param_group, "param",
1039                        &TF_CIT_TMPL(tf)->tfc_tpg_param_cit);
1040
1041        return &se_tpg->tpg_group;
1042}
1043
1044static void target_fabric_drop_tpg(
1045        struct config_group *group,
1046        struct config_item *item)
1047{
1048        struct se_portal_group *se_tpg = container_of(to_config_group(item),
1049                                struct se_portal_group, tpg_group);
1050        struct config_group *tpg_cg = &se_tpg->tpg_group;
1051        struct config_item *df_item;
1052        int i;
1053        /*
1054         * Release default groups, but do not release tpg_cg->default_groups
1055         * memory as it is statically allocated at se_tpg->tpg_default_groups.
1056         */
1057        for (i = 0; tpg_cg->default_groups[i]; i++) {
1058                df_item = &tpg_cg->default_groups[i]->cg_item;
1059                tpg_cg->default_groups[i] = NULL;
1060                config_item_put(df_item);
1061        }
1062
1063        config_item_put(item);
1064}
1065
1066static void target_fabric_release_wwn(struct config_item *item)
1067{
1068        struct se_wwn *wwn = container_of(to_config_group(item),
1069                                struct se_wwn, wwn_group);
1070        struct target_fabric_configfs *tf = wwn->wwn_tf;
1071
1072        tf->tf_ops.fabric_drop_wwn(wwn);
1073}
1074
1075static struct configfs_item_operations target_fabric_tpg_item_ops = {
1076        .release        = target_fabric_release_wwn,
1077};
1078
1079static struct configfs_group_operations target_fabric_tpg_group_ops = {
1080        .make_group     = target_fabric_make_tpg,
1081        .drop_item      = target_fabric_drop_tpg,
1082};
1083
1084TF_CIT_SETUP(tpg, &target_fabric_tpg_item_ops, &target_fabric_tpg_group_ops,
1085                NULL);
1086
1087/* End of tfc_tpg_cit */
1088
1089/* Start of tfc_wwn_fabric_stats_cit */
1090/*
1091 * This is used as a placeholder for struct se_wwn->fabric_stat_group
1092 * to allow fabrics access to ->fabric_stat_group->default_groups[]
1093 */
1094TF_CIT_SETUP(wwn_fabric_stats, NULL, NULL, NULL);
1095
1096/* End of tfc_wwn_fabric_stats_cit */
1097
1098/* Start of tfc_wwn_cit */
1099
1100static struct config_group *target_fabric_make_wwn(
1101        struct config_group *group,
1102        const char *name)
1103{
1104        struct target_fabric_configfs *tf = container_of(group,
1105                                struct target_fabric_configfs, tf_group);
1106        struct se_wwn *wwn;
1107
1108        if (!tf->tf_ops.fabric_make_wwn) {
1109                pr_err("tf->tf_ops.fabric_make_wwn is NULL\n");
1110                return ERR_PTR(-ENOSYS);
1111        }
1112
1113        wwn = tf->tf_ops.fabric_make_wwn(tf, group, name);
1114        if (!wwn || IS_ERR(wwn))
1115                return ERR_PTR(-EINVAL);
1116
1117        wwn->wwn_tf = tf;
1118        /*
1119         * Setup default groups from pre-allocated wwn->wwn_default_groups
1120         */
1121        wwn->wwn_group.default_groups = wwn->wwn_default_groups;
1122        wwn->wwn_group.default_groups[0] = &wwn->fabric_stat_group;
1123        wwn->wwn_group.default_groups[1] = NULL;
1124
1125        config_group_init_type_name(&wwn->wwn_group, name,
1126                        &TF_CIT_TMPL(tf)->tfc_tpg_cit);
1127        config_group_init_type_name(&wwn->fabric_stat_group, "fabric_statistics",
1128                        &TF_CIT_TMPL(tf)->tfc_wwn_fabric_stats_cit);
1129
1130        return &wwn->wwn_group;
1131}
1132
1133static void target_fabric_drop_wwn(
1134        struct config_group *group,
1135        struct config_item *item)
1136{
1137        struct se_wwn *wwn = container_of(to_config_group(item),
1138                                struct se_wwn, wwn_group);
1139        struct config_item *df_item;
1140        struct config_group *cg = &wwn->wwn_group;
1141        int i;
1142
1143        for (i = 0; cg->default_groups[i]; i++) {
1144                df_item = &cg->default_groups[i]->cg_item;
1145                cg->default_groups[i] = NULL;
1146                config_item_put(df_item);
1147        }
1148
1149        config_item_put(item);
1150}
1151
1152static struct configfs_group_operations target_fabric_wwn_group_ops = {
1153        .make_group     = target_fabric_make_wwn,
1154        .drop_item      = target_fabric_drop_wwn,
1155};
1156/*
1157 * For use with TF_WWN_ATTR() and TF_WWN_ATTR_RO()
1158 */
1159CONFIGFS_EATTR_OPS(target_fabric_wwn, target_fabric_configfs, tf_group);
1160
1161static struct configfs_item_operations target_fabric_wwn_item_ops = {
1162        .show_attribute         = target_fabric_wwn_attr_show,
1163        .store_attribute        = target_fabric_wwn_attr_store,
1164};
1165
1166TF_CIT_SETUP(wwn, &target_fabric_wwn_item_ops, &target_fabric_wwn_group_ops, NULL);
1167
1168/* End of tfc_wwn_cit */
1169
1170/* Start of tfc_discovery_cit */
1171
1172CONFIGFS_EATTR_OPS(target_fabric_discovery, target_fabric_configfs,
1173                tf_disc_group);
1174
1175static struct configfs_item_operations target_fabric_discovery_item_ops = {
1176        .show_attribute         = target_fabric_discovery_attr_show,
1177        .store_attribute        = target_fabric_discovery_attr_store,
1178};
1179
1180TF_CIT_SETUP(discovery, &target_fabric_discovery_item_ops, NULL, NULL);
1181
1182/* End of tfc_discovery_cit */
1183
1184int target_fabric_setup_cits(struct target_fabric_configfs *tf)
1185{
1186        target_fabric_setup_discovery_cit(tf);
1187        target_fabric_setup_wwn_cit(tf);
1188        target_fabric_setup_wwn_fabric_stats_cit(tf);
1189        target_fabric_setup_tpg_cit(tf);
1190        target_fabric_setup_tpg_base_cit(tf);
1191        target_fabric_setup_tpg_port_cit(tf);
1192        target_fabric_setup_tpg_port_stat_cit(tf);
1193        target_fabric_setup_tpg_lun_cit(tf);
1194        target_fabric_setup_tpg_np_cit(tf);
1195        target_fabric_setup_tpg_np_base_cit(tf);
1196        target_fabric_setup_tpg_attrib_cit(tf);
1197        target_fabric_setup_tpg_param_cit(tf);
1198        target_fabric_setup_tpg_nacl_cit(tf);
1199        target_fabric_setup_tpg_nacl_base_cit(tf);
1200        target_fabric_setup_tpg_nacl_attrib_cit(tf);
1201        target_fabric_setup_tpg_nacl_auth_cit(tf);
1202        target_fabric_setup_tpg_nacl_param_cit(tf);
1203        target_fabric_setup_tpg_nacl_stat_cit(tf);
1204        target_fabric_setup_tpg_mappedlun_cit(tf);
1205        target_fabric_setup_tpg_mappedlun_stat_cit(tf);
1206
1207        return 0;
1208}
1209
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.