linux/drivers/target/target_core_tpg.c
<<
>>
Prefs
   1/*******************************************************************************
   2 * Filename:  target_core_tpg.c
   3 *
   4 * This file contains generic Target Portal Group related functions.
   5 *
   6 * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
   7 * Copyright (c) 2005, 2006, 2007 SBE, Inc.
   8 * Copyright (c) 2007-2010 Rising Tide Systems
   9 * Copyright (c) 2008-2010 Linux-iSCSI.org
  10 *
  11 * Nicholas A. Bellinger <nab@kernel.org>
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  26 *
  27 ******************************************************************************/
  28
  29#include <linux/net.h>
  30#include <linux/string.h>
  31#include <linux/timer.h>
  32#include <linux/slab.h>
  33#include <linux/spinlock.h>
  34#include <linux/in.h>
  35#include <linux/export.h>
  36#include <net/sock.h>
  37#include <net/tcp.h>
  38#include <scsi/scsi.h>
  39#include <scsi/scsi_cmnd.h>
  40
  41#include <target/target_core_base.h>
  42#include <target/target_core_backend.h>
  43#include <target/target_core_fabric.h>
  44
  45#include "target_core_internal.h"
  46
  47extern struct se_device *g_lun0_dev;
  48
  49static DEFINE_SPINLOCK(tpg_lock);
  50static LIST_HEAD(tpg_list);
  51
  52/*      core_clear_initiator_node_from_tpg():
  53 *
  54 *
  55 */
  56static void core_clear_initiator_node_from_tpg(
  57        struct se_node_acl *nacl,
  58        struct se_portal_group *tpg)
  59{
  60        int i;
  61        struct se_dev_entry *deve;
  62        struct se_lun *lun;
  63
  64        spin_lock_irq(&nacl->device_list_lock);
  65        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
  66                deve = nacl->device_list[i];
  67
  68                if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS))
  69                        continue;
  70
  71                if (!deve->se_lun) {
  72                        pr_err("%s device entries device pointer is"
  73                                " NULL, but Initiator has access.\n",
  74                                tpg->se_tpg_tfo->get_fabric_name());
  75                        continue;
  76                }
  77
  78                lun = deve->se_lun;
  79                spin_unlock_irq(&nacl->device_list_lock);
  80                core_disable_device_list_for_node(lun, NULL, deve->mapped_lun,
  81                        TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
  82
  83                spin_lock_irq(&nacl->device_list_lock);
  84        }
  85        spin_unlock_irq(&nacl->device_list_lock);
  86}
  87
  88/*      __core_tpg_get_initiator_node_acl():
  89 *
  90 *      spin_lock_bh(&tpg->acl_node_lock); must be held when calling
  91 */
  92struct se_node_acl *__core_tpg_get_initiator_node_acl(
  93        struct se_portal_group *tpg,
  94        const char *initiatorname)
  95{
  96        struct se_node_acl *acl;
  97
  98        list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
  99                if (!strcmp(acl->initiatorname, initiatorname))
 100                        return acl;
 101        }
 102
 103        return NULL;
 104}
 105
 106/*      core_tpg_get_initiator_node_acl():
 107 *
 108 *
 109 */
 110struct se_node_acl *core_tpg_get_initiator_node_acl(
 111        struct se_portal_group *tpg,
 112        unsigned char *initiatorname)
 113{
 114        struct se_node_acl *acl;
 115
 116        spin_lock_irq(&tpg->acl_node_lock);
 117        list_for_each_entry(acl, &tpg->acl_node_list, acl_list) {
 118                if (!strcmp(acl->initiatorname, initiatorname) &&
 119                    !acl->dynamic_node_acl) {
 120                        spin_unlock_irq(&tpg->acl_node_lock);
 121                        return acl;
 122                }
 123        }
 124        spin_unlock_irq(&tpg->acl_node_lock);
 125
 126        return NULL;
 127}
 128
 129/*      core_tpg_add_node_to_devs():
 130 *
 131 *
 132 */
 133void core_tpg_add_node_to_devs(
 134        struct se_node_acl *acl,
 135        struct se_portal_group *tpg)
 136{
 137        int i = 0;
 138        u32 lun_access = 0;
 139        struct se_lun *lun;
 140        struct se_device *dev;
 141
 142        spin_lock(&tpg->tpg_lun_lock);
 143        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
 144                lun = tpg->tpg_lun_list[i];
 145                if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE)
 146                        continue;
 147
 148                spin_unlock(&tpg->tpg_lun_lock);
 149
 150                dev = lun->lun_se_dev;
 151                /*
 152                 * By default in LIO-Target $FABRIC_MOD,
 153                 * demo_mode_write_protect is ON, or READ_ONLY;
 154                 */
 155                if (!tpg->se_tpg_tfo->tpg_check_demo_mode_write_protect(tpg)) {
 156                        lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
 157                } else {
 158                        /*
 159                         * Allow only optical drives to issue R/W in default RO
 160                         * demo mode.
 161                         */
 162                        if (dev->transport->get_device_type(dev) == TYPE_DISK)
 163                                lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
 164                        else
 165                                lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
 166                }
 167
 168                pr_debug("TARGET_CORE[%s]->TPG[%u]_LUN[%u] - Adding %s"
 169                        " access for LUN in Demo Mode\n",
 170                        tpg->se_tpg_tfo->get_fabric_name(),
 171                        tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun,
 172                        (lun_access == TRANSPORT_LUNFLAGS_READ_WRITE) ?
 173                        "READ-WRITE" : "READ-ONLY");
 174
 175                core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun,
 176                                lun_access, acl, tpg);
 177                spin_lock(&tpg->tpg_lun_lock);
 178        }
 179        spin_unlock(&tpg->tpg_lun_lock);
 180}
 181
 182/*      core_set_queue_depth_for_node():
 183 *
 184 *
 185 */
 186static int core_set_queue_depth_for_node(
 187        struct se_portal_group *tpg,
 188        struct se_node_acl *acl)
 189{
 190        if (!acl->queue_depth) {
 191                pr_err("Queue depth for %s Initiator Node: %s is 0,"
 192                        "defaulting to 1.\n", tpg->se_tpg_tfo->get_fabric_name(),
 193                        acl->initiatorname);
 194                acl->queue_depth = 1;
 195        }
 196
 197        return 0;
 198}
 199
 200void array_free(void *array, int n)
 201{
 202        void **a = array;
 203        int i;
 204
 205        for (i = 0; i < n; i++)
 206                kfree(a[i]);
 207        kfree(a);
 208}
 209
 210static void *array_zalloc(int n, size_t size, gfp_t flags)
 211{
 212        void **a;
 213        int i;
 214
 215        a = kzalloc(n * sizeof(void*), flags);
 216        if (!a)
 217                return NULL;
 218        for (i = 0; i < n; i++) {
 219                a[i] = kzalloc(size, flags);
 220                if (!a[i]) {
 221                        array_free(a, n);
 222                        return NULL;
 223                }
 224        }
 225        return a;
 226}
 227
 228/*      core_create_device_list_for_node():
 229 *
 230 *
 231 */
 232static int core_create_device_list_for_node(struct se_node_acl *nacl)
 233{
 234        struct se_dev_entry *deve;
 235        int i;
 236
 237        nacl->device_list = array_zalloc(TRANSPORT_MAX_LUNS_PER_TPG,
 238                        sizeof(struct se_dev_entry), GFP_KERNEL);
 239        if (!nacl->device_list) {
 240                pr_err("Unable to allocate memory for"
 241                        " struct se_node_acl->device_list\n");
 242                return -ENOMEM;
 243        }
 244        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
 245                deve = nacl->device_list[i];
 246
 247                atomic_set(&deve->ua_count, 0);
 248                atomic_set(&deve->pr_ref_count, 0);
 249                spin_lock_init(&deve->ua_lock);
 250                INIT_LIST_HEAD(&deve->alua_port_list);
 251                INIT_LIST_HEAD(&deve->ua_list);
 252        }
 253
 254        return 0;
 255}
 256
 257/*      core_tpg_check_initiator_node_acl()
 258 *
 259 *
 260 */
 261struct se_node_acl *core_tpg_check_initiator_node_acl(
 262        struct se_portal_group *tpg,
 263        unsigned char *initiatorname)
 264{
 265        struct se_node_acl *acl;
 266
 267        acl = core_tpg_get_initiator_node_acl(tpg, initiatorname);
 268        if (acl)
 269                return acl;
 270
 271        if (!tpg->se_tpg_tfo->tpg_check_demo_mode(tpg))
 272                return NULL;
 273
 274        acl =  tpg->se_tpg_tfo->tpg_alloc_fabric_acl(tpg);
 275        if (!acl)
 276                return NULL;
 277
 278        INIT_LIST_HEAD(&acl->acl_list);
 279        INIT_LIST_HEAD(&acl->acl_sess_list);
 280        kref_init(&acl->acl_kref);
 281        init_completion(&acl->acl_free_comp);
 282        spin_lock_init(&acl->device_list_lock);
 283        spin_lock_init(&acl->nacl_sess_lock);
 284        atomic_set(&acl->acl_pr_ref_count, 0);
 285        acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg);
 286        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
 287        acl->se_tpg = tpg;
 288        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
 289        spin_lock_init(&acl->stats_lock);
 290        acl->dynamic_node_acl = 1;
 291
 292        tpg->se_tpg_tfo->set_default_node_attributes(acl);
 293
 294        if (core_create_device_list_for_node(acl) < 0) {
 295                tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
 296                return NULL;
 297        }
 298
 299        if (core_set_queue_depth_for_node(tpg, acl) < 0) {
 300                core_free_device_list_for_node(acl, tpg);
 301                tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
 302                return NULL;
 303        }
 304        /*
 305         * Here we only create demo-mode MappedLUNs from the active
 306         * TPG LUNs if the fabric is not explicitly asking for
 307         * tpg_check_demo_mode_login_only() == 1.
 308         */
 309        if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only == NULL) ||
 310            (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) != 1))
 311                core_tpg_add_node_to_devs(acl, tpg);
 312
 313        spin_lock_irq(&tpg->acl_node_lock);
 314        list_add_tail(&acl->acl_list, &tpg->acl_node_list);
 315        tpg->num_node_acls++;
 316        spin_unlock_irq(&tpg->acl_node_lock);
 317
 318        pr_debug("%s_TPG[%u] - Added DYNAMIC ACL with TCQ Depth: %d for %s"
 319                " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
 320                tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth,
 321                tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
 322
 323        return acl;
 324}
 325EXPORT_SYMBOL(core_tpg_check_initiator_node_acl);
 326
 327void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *nacl)
 328{
 329        while (atomic_read(&nacl->acl_pr_ref_count) != 0)
 330                cpu_relax();
 331}
 332
 333void core_tpg_clear_object_luns(struct se_portal_group *tpg)
 334{
 335        int i;
 336        struct se_lun *lun;
 337
 338        spin_lock(&tpg->tpg_lun_lock);
 339        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
 340                lun = tpg->tpg_lun_list[i];
 341
 342                if ((lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) ||
 343                    (lun->lun_se_dev == NULL))
 344                        continue;
 345
 346                spin_unlock(&tpg->tpg_lun_lock);
 347                core_dev_del_lun(tpg, lun->unpacked_lun);
 348                spin_lock(&tpg->tpg_lun_lock);
 349        }
 350        spin_unlock(&tpg->tpg_lun_lock);
 351}
 352EXPORT_SYMBOL(core_tpg_clear_object_luns);
 353
 354/*      core_tpg_add_initiator_node_acl():
 355 *
 356 *
 357 */
 358struct se_node_acl *core_tpg_add_initiator_node_acl(
 359        struct se_portal_group *tpg,
 360        struct se_node_acl *se_nacl,
 361        const char *initiatorname,
 362        u32 queue_depth)
 363{
 364        struct se_node_acl *acl = NULL;
 365
 366        spin_lock_irq(&tpg->acl_node_lock);
 367        acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
 368        if (acl) {
 369                if (acl->dynamic_node_acl) {
 370                        acl->dynamic_node_acl = 0;
 371                        pr_debug("%s_TPG[%u] - Replacing dynamic ACL"
 372                                " for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
 373                                tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname);
 374                        spin_unlock_irq(&tpg->acl_node_lock);
 375                        /*
 376                         * Release the locally allocated struct se_node_acl
 377                         * because * core_tpg_add_initiator_node_acl() returned
 378                         * a pointer to an existing demo mode node ACL.
 379                         */
 380                        if (se_nacl)
 381                                tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg,
 382                                                        se_nacl);
 383                        goto done;
 384                }
 385
 386                pr_err("ACL entry for %s Initiator"
 387                        " Node %s already exists for TPG %u, ignoring"
 388                        " request.\n",  tpg->se_tpg_tfo->get_fabric_name(),
 389                        initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
 390                spin_unlock_irq(&tpg->acl_node_lock);
 391                return ERR_PTR(-EEXIST);
 392        }
 393        spin_unlock_irq(&tpg->acl_node_lock);
 394
 395        if (!se_nacl) {
 396                pr_err("struct se_node_acl pointer is NULL\n");
 397                return ERR_PTR(-EINVAL);
 398        }
 399        /*
 400         * For v4.x logic the se_node_acl_s is hanging off a fabric
 401         * dependent structure allocated via
 402         * struct target_core_fabric_ops->fabric_make_nodeacl()
 403         */
 404        acl = se_nacl;
 405
 406        INIT_LIST_HEAD(&acl->acl_list);
 407        INIT_LIST_HEAD(&acl->acl_sess_list);
 408        kref_init(&acl->acl_kref);
 409        init_completion(&acl->acl_free_comp);
 410        spin_lock_init(&acl->device_list_lock);
 411        spin_lock_init(&acl->nacl_sess_lock);
 412        atomic_set(&acl->acl_pr_ref_count, 0);
 413        acl->queue_depth = queue_depth;
 414        snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname);
 415        acl->se_tpg = tpg;
 416        acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX);
 417        spin_lock_init(&acl->stats_lock);
 418
 419        tpg->se_tpg_tfo->set_default_node_attributes(acl);
 420
 421        if (core_create_device_list_for_node(acl) < 0) {
 422                tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
 423                return ERR_PTR(-ENOMEM);
 424        }
 425
 426        if (core_set_queue_depth_for_node(tpg, acl) < 0) {
 427                core_free_device_list_for_node(acl, tpg);
 428                tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl);
 429                return ERR_PTR(-EINVAL);
 430        }
 431
 432        spin_lock_irq(&tpg->acl_node_lock);
 433        list_add_tail(&acl->acl_list, &tpg->acl_node_list);
 434        tpg->num_node_acls++;
 435        spin_unlock_irq(&tpg->acl_node_lock);
 436
 437done:
 438        pr_debug("%s_TPG[%hu] - Added ACL with TCQ Depth: %d for %s"
 439                " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
 440                tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth,
 441                tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
 442
 443        return acl;
 444}
 445EXPORT_SYMBOL(core_tpg_add_initiator_node_acl);
 446
 447/*      core_tpg_del_initiator_node_acl():
 448 *
 449 *
 450 */
 451int core_tpg_del_initiator_node_acl(
 452        struct se_portal_group *tpg,
 453        struct se_node_acl *acl,
 454        int force)
 455{
 456        LIST_HEAD(sess_list);
 457        struct se_session *sess, *sess_tmp;
 458        unsigned long flags;
 459        int rc;
 460
 461        spin_lock_irq(&tpg->acl_node_lock);
 462        if (acl->dynamic_node_acl) {
 463                acl->dynamic_node_acl = 0;
 464        }
 465        list_del(&acl->acl_list);
 466        tpg->num_node_acls--;
 467        spin_unlock_irq(&tpg->acl_node_lock);
 468
 469        spin_lock_irqsave(&acl->nacl_sess_lock, flags);
 470        acl->acl_stop = 1;
 471
 472        list_for_each_entry_safe(sess, sess_tmp, &acl->acl_sess_list,
 473                                sess_acl_list) {
 474                if (sess->sess_tearing_down != 0)
 475                        continue;
 476
 477                target_get_session(sess);
 478                list_move(&sess->sess_acl_list, &sess_list);
 479        }
 480        spin_unlock_irqrestore(&acl->nacl_sess_lock, flags);
 481
 482        list_for_each_entry_safe(sess, sess_tmp, &sess_list, sess_acl_list) {
 483                list_del(&sess->sess_acl_list);
 484
 485                rc = tpg->se_tpg_tfo->shutdown_session(sess);
 486                target_put_session(sess);
 487                if (!rc)
 488                        continue;
 489                target_put_session(sess);
 490        }
 491        target_put_nacl(acl);
 492        /*
 493         * Wait for last target_put_nacl() to complete in target_complete_nacl()
 494         * for active fabric session transport_deregister_session() callbacks.
 495         */
 496        wait_for_completion(&acl->acl_free_comp);
 497
 498        core_tpg_wait_for_nacl_pr_ref(acl);
 499        core_clear_initiator_node_from_tpg(acl, tpg);
 500        core_free_device_list_for_node(acl, tpg);
 501
 502        pr_debug("%s_TPG[%hu] - Deleted ACL with TCQ Depth: %d for %s"
 503                " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
 504                tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth,
 505                tpg->se_tpg_tfo->get_fabric_name(), acl->initiatorname);
 506
 507        return 0;
 508}
 509EXPORT_SYMBOL(core_tpg_del_initiator_node_acl);
 510
 511/*      core_tpg_set_initiator_node_queue_depth():
 512 *
 513 *
 514 */
 515int core_tpg_set_initiator_node_queue_depth(
 516        struct se_portal_group *tpg,
 517        unsigned char *initiatorname,
 518        u32 queue_depth,
 519        int force)
 520{
 521        struct se_session *sess, *init_sess = NULL;
 522        struct se_node_acl *acl;
 523        unsigned long flags;
 524        int dynamic_acl = 0;
 525
 526        spin_lock_irq(&tpg->acl_node_lock);
 527        acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname);
 528        if (!acl) {
 529                pr_err("Access Control List entry for %s Initiator"
 530                        " Node %s does not exists for TPG %hu, ignoring"
 531                        " request.\n", tpg->se_tpg_tfo->get_fabric_name(),
 532                        initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg));
 533                spin_unlock_irq(&tpg->acl_node_lock);
 534                return -ENODEV;
 535        }
 536        if (acl->dynamic_node_acl) {
 537                acl->dynamic_node_acl = 0;
 538                dynamic_acl = 1;
 539        }
 540        spin_unlock_irq(&tpg->acl_node_lock);
 541
 542        spin_lock_irqsave(&tpg->session_lock, flags);
 543        list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) {
 544                if (sess->se_node_acl != acl)
 545                        continue;
 546
 547                if (!force) {
 548                        pr_err("Unable to change queue depth for %s"
 549                                " Initiator Node: %s while session is"
 550                                " operational.  To forcefully change the queue"
 551                                " depth and force session reinstatement"
 552                                " use the \"force=1\" parameter.\n",
 553                                tpg->se_tpg_tfo->get_fabric_name(), initiatorname);
 554                        spin_unlock_irqrestore(&tpg->session_lock, flags);
 555
 556                        spin_lock_irq(&tpg->acl_node_lock);
 557                        if (dynamic_acl)
 558                                acl->dynamic_node_acl = 1;
 559                        spin_unlock_irq(&tpg->acl_node_lock);
 560                        return -EEXIST;
 561                }
 562                /*
 563                 * Determine if the session needs to be closed by our context.
 564                 */
 565                if (!tpg->se_tpg_tfo->shutdown_session(sess))
 566                        continue;
 567
 568                init_sess = sess;
 569                break;
 570        }
 571
 572        /*
 573         * User has requested to change the queue depth for a Initiator Node.
 574         * Change the value in the Node's struct se_node_acl, and call
 575         * core_set_queue_depth_for_node() to add the requested queue depth.
 576         *
 577         * Finally call  tpg->se_tpg_tfo->close_session() to force session
 578         * reinstatement to occur if there is an active session for the
 579         * $FABRIC_MOD Initiator Node in question.
 580         */
 581        acl->queue_depth = queue_depth;
 582
 583        if (core_set_queue_depth_for_node(tpg, acl) < 0) {
 584                spin_unlock_irqrestore(&tpg->session_lock, flags);
 585                /*
 586                 * Force session reinstatement if
 587                 * core_set_queue_depth_for_node() failed, because we assume
 588                 * the $FABRIC_MOD has already the set session reinstatement
 589                 * bit from tpg->se_tpg_tfo->shutdown_session() called above.
 590                 */
 591                if (init_sess)
 592                        tpg->se_tpg_tfo->close_session(init_sess);
 593
 594                spin_lock_irq(&tpg->acl_node_lock);
 595                if (dynamic_acl)
 596                        acl->dynamic_node_acl = 1;
 597                spin_unlock_irq(&tpg->acl_node_lock);
 598                return -EINVAL;
 599        }
 600        spin_unlock_irqrestore(&tpg->session_lock, flags);
 601        /*
 602         * If the $FABRIC_MOD session for the Initiator Node ACL exists,
 603         * forcefully shutdown the $FABRIC_MOD session/nexus.
 604         */
 605        if (init_sess)
 606                tpg->se_tpg_tfo->close_session(init_sess);
 607
 608        pr_debug("Successfully changed queue depth to: %d for Initiator"
 609                " Node: %s on %s Target Portal Group: %u\n", queue_depth,
 610                initiatorname, tpg->se_tpg_tfo->get_fabric_name(),
 611                tpg->se_tpg_tfo->tpg_get_tag(tpg));
 612
 613        spin_lock_irq(&tpg->acl_node_lock);
 614        if (dynamic_acl)
 615                acl->dynamic_node_acl = 1;
 616        spin_unlock_irq(&tpg->acl_node_lock);
 617
 618        return 0;
 619}
 620EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth);
 621
 622static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg)
 623{
 624        /* Set in core_dev_setup_virtual_lun0() */
 625        struct se_device *dev = g_lun0_dev;
 626        struct se_lun *lun = &se_tpg->tpg_virt_lun0;
 627        u32 lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
 628        int ret;
 629
 630        lun->unpacked_lun = 0;
 631        lun->lun_status = TRANSPORT_LUN_STATUS_FREE;
 632        atomic_set(&lun->lun_acl_count, 0);
 633        init_completion(&lun->lun_shutdown_comp);
 634        INIT_LIST_HEAD(&lun->lun_acl_list);
 635        INIT_LIST_HEAD(&lun->lun_cmd_list);
 636        spin_lock_init(&lun->lun_acl_lock);
 637        spin_lock_init(&lun->lun_cmd_lock);
 638        spin_lock_init(&lun->lun_sep_lock);
 639
 640        ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev);
 641        if (ret < 0)
 642                return ret;
 643
 644        return 0;
 645}
 646
 647static void core_tpg_release_virtual_lun0(struct se_portal_group *se_tpg)
 648{
 649        struct se_lun *lun = &se_tpg->tpg_virt_lun0;
 650
 651        core_tpg_post_dellun(se_tpg, lun);
 652}
 653
 654int core_tpg_register(
 655        struct target_core_fabric_ops *tfo,
 656        struct se_wwn *se_wwn,
 657        struct se_portal_group *se_tpg,
 658        void *tpg_fabric_ptr,
 659        int se_tpg_type)
 660{
 661        struct se_lun *lun;
 662        u32 i;
 663
 664        se_tpg->tpg_lun_list = array_zalloc(TRANSPORT_MAX_LUNS_PER_TPG,
 665                        sizeof(struct se_lun), GFP_KERNEL);
 666        if (!se_tpg->tpg_lun_list) {
 667                pr_err("Unable to allocate struct se_portal_group->"
 668                                "tpg_lun_list\n");
 669                return -ENOMEM;
 670        }
 671
 672        for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) {
 673                lun = se_tpg->tpg_lun_list[i];
 674                lun->unpacked_lun = i;
 675                lun->lun_link_magic = SE_LUN_LINK_MAGIC;
 676                lun->lun_status = TRANSPORT_LUN_STATUS_FREE;
 677                atomic_set(&lun->lun_acl_count, 0);
 678                init_completion(&lun->lun_shutdown_comp);
 679                INIT_LIST_HEAD(&lun->lun_acl_list);
 680                INIT_LIST_HEAD(&lun->lun_cmd_list);
 681                spin_lock_init(&lun->lun_acl_lock);
 682                spin_lock_init(&lun->lun_cmd_lock);
 683                spin_lock_init(&lun->lun_sep_lock);
 684        }
 685
 686        se_tpg->se_tpg_type = se_tpg_type;
 687        se_tpg->se_tpg_fabric_ptr = tpg_fabric_ptr;
 688        se_tpg->se_tpg_tfo = tfo;
 689        se_tpg->se_tpg_wwn = se_wwn;
 690        atomic_set(&se_tpg->tpg_pr_ref_count, 0);
 691        INIT_LIST_HEAD(&se_tpg->acl_node_list);
 692        INIT_LIST_HEAD(&se_tpg->se_tpg_node);
 693        INIT_LIST_HEAD(&se_tpg->tpg_sess_list);
 694        spin_lock_init(&se_tpg->acl_node_lock);
 695        spin_lock_init(&se_tpg->session_lock);
 696        spin_lock_init(&se_tpg->tpg_lun_lock);
 697
 698        if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) {
 699                if (core_tpg_setup_virtual_lun0(se_tpg) < 0) {
 700                        kfree(se_tpg);
 701                        return -ENOMEM;
 702                }
 703        }
 704
 705        spin_lock_bh(&tpg_lock);
 706        list_add_tail(&se_tpg->se_tpg_node, &tpg_list);
 707        spin_unlock_bh(&tpg_lock);
 708
 709        pr_debug("TARGET_CORE[%s]: Allocated %s struct se_portal_group for"
 710                " endpoint: %s, Portal Tag: %u\n", tfo->get_fabric_name(),
 711                (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ?
 712                "Normal" : "Discovery", (tfo->tpg_get_wwn(se_tpg) == NULL) ?
 713                "None" : tfo->tpg_get_wwn(se_tpg), tfo->tpg_get_tag(se_tpg));
 714
 715        return 0;
 716}
 717EXPORT_SYMBOL(core_tpg_register);
 718
 719int core_tpg_deregister(struct se_portal_group *se_tpg)
 720{
 721        struct se_node_acl *nacl, *nacl_tmp;
 722
 723        pr_debug("TARGET_CORE[%s]: Deallocating %s struct se_portal_group"
 724                " for endpoint: %s Portal Tag %u\n",
 725                (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ?
 726                "Normal" : "Discovery", se_tpg->se_tpg_tfo->get_fabric_name(),
 727                se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg),
 728                se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg));
 729
 730        spin_lock_bh(&tpg_lock);
 731        list_del(&se_tpg->se_tpg_node);
 732        spin_unlock_bh(&tpg_lock);
 733
 734        while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0)
 735                cpu_relax();
 736        /*
 737         * Release any remaining demo-mode generated se_node_acl that have
 738         * not been released because of TFO->tpg_check_demo_mode_cache() == 1
 739         * in transport_deregister_session().
 740         */
 741        spin_lock_irq(&se_tpg->acl_node_lock);
 742        list_for_each_entry_safe(nacl, nacl_tmp, &se_tpg->acl_node_list,
 743                        acl_list) {
 744                list_del(&nacl->acl_list);
 745                se_tpg->num_node_acls--;
 746                spin_unlock_irq(&se_tpg->acl_node_lock);
 747
 748                core_tpg_wait_for_nacl_pr_ref(nacl);
 749                core_free_device_list_for_node(nacl, se_tpg);
 750                se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, nacl);
 751
 752                spin_lock_irq(&se_tpg->acl_node_lock);
 753        }
 754        spin_unlock_irq(&se_tpg->acl_node_lock);
 755
 756        if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL)
 757                core_tpg_release_virtual_lun0(se_tpg);
 758
 759        se_tpg->se_tpg_fabric_ptr = NULL;
 760        array_free(se_tpg->tpg_lun_list, TRANSPORT_MAX_LUNS_PER_TPG);
 761        return 0;
 762}
 763EXPORT_SYMBOL(core_tpg_deregister);
 764
 765struct se_lun *core_tpg_pre_addlun(
 766        struct se_portal_group *tpg,
 767        u32 unpacked_lun)
 768{
 769        struct se_lun *lun;
 770
 771        if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
 772                pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG"
 773                        "-1: %u for Target Portal Group: %u\n",
 774                        tpg->se_tpg_tfo->get_fabric_name(),
 775                        unpacked_lun, TRANSPORT_MAX_LUNS_PER_TPG-1,
 776                        tpg->se_tpg_tfo->tpg_get_tag(tpg));
 777                return ERR_PTR(-EOVERFLOW);
 778        }
 779
 780        spin_lock(&tpg->tpg_lun_lock);
 781        lun = tpg->tpg_lun_list[unpacked_lun];
 782        if (lun->lun_status == TRANSPORT_LUN_STATUS_ACTIVE) {
 783                pr_err("TPG Logical Unit Number: %u is already active"
 784                        " on %s Target Portal Group: %u, ignoring request.\n",
 785                        unpacked_lun, tpg->se_tpg_tfo->get_fabric_name(),
 786                        tpg->se_tpg_tfo->tpg_get_tag(tpg));
 787                spin_unlock(&tpg->tpg_lun_lock);
 788                return ERR_PTR(-EINVAL);
 789        }
 790        spin_unlock(&tpg->tpg_lun_lock);
 791
 792        return lun;
 793}
 794
 795int core_tpg_post_addlun(
 796        struct se_portal_group *tpg,
 797        struct se_lun *lun,
 798        u32 lun_access,
 799        void *lun_ptr)
 800{
 801        int ret;
 802
 803        ret = core_dev_export(lun_ptr, tpg, lun);
 804        if (ret < 0)
 805                return ret;
 806
 807        spin_lock(&tpg->tpg_lun_lock);
 808        lun->lun_access = lun_access;
 809        lun->lun_status = TRANSPORT_LUN_STATUS_ACTIVE;
 810        spin_unlock(&tpg->tpg_lun_lock);
 811
 812        return 0;
 813}
 814
 815static void core_tpg_shutdown_lun(
 816        struct se_portal_group *tpg,
 817        struct se_lun *lun)
 818{
 819        core_clear_lun_from_tpg(lun, tpg);
 820        transport_clear_lun_from_sessions(lun);
 821}
 822
 823struct se_lun *core_tpg_pre_dellun(
 824        struct se_portal_group *tpg,
 825        u32 unpacked_lun)
 826{
 827        struct se_lun *lun;
 828
 829        if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) {
 830                pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG"
 831                        "-1: %u for Target Portal Group: %u\n",
 832                        tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
 833                        TRANSPORT_MAX_LUNS_PER_TPG-1,
 834                        tpg->se_tpg_tfo->tpg_get_tag(tpg));
 835                return ERR_PTR(-EOVERFLOW);
 836        }
 837
 838        spin_lock(&tpg->tpg_lun_lock);
 839        lun = tpg->tpg_lun_list[unpacked_lun];
 840        if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) {
 841                pr_err("%s Logical Unit Number: %u is not active on"
 842                        " Target Portal Group: %u, ignoring request.\n",
 843                        tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun,
 844                        tpg->se_tpg_tfo->tpg_get_tag(tpg));
 845                spin_unlock(&tpg->tpg_lun_lock);
 846                return ERR_PTR(-ENODEV);
 847        }
 848        spin_unlock(&tpg->tpg_lun_lock);
 849
 850        return lun;
 851}
 852
 853int core_tpg_post_dellun(
 854        struct se_portal_group *tpg,
 855        struct se_lun *lun)
 856{
 857        core_tpg_shutdown_lun(tpg, lun);
 858
 859        core_dev_unexport(lun->lun_se_dev, tpg, lun);
 860
 861        spin_lock(&tpg->tpg_lun_lock);
 862        lun->lun_status = TRANSPORT_LUN_STATUS_FREE;
 863        spin_unlock(&tpg->tpg_lun_lock);
 864
 865        return 0;
 866}
 867
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.