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