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> 35c53181afSPaul Gortmaker #include <linux/export.h> 36c66ac9dbSNicholas Bellinger #include <net/sock.h> 37c66ac9dbSNicholas Bellinger #include <net/tcp.h> 38c66ac9dbSNicholas Bellinger #include <scsi/scsi.h> 39c66ac9dbSNicholas Bellinger #include <scsi/scsi_cmnd.h> 40c66ac9dbSNicholas Bellinger 41c66ac9dbSNicholas Bellinger #include <target/target_core_base.h> 42c66ac9dbSNicholas Bellinger #include <target/target_core_device.h> 43c66ac9dbSNicholas Bellinger #include <target/target_core_tpg.h> 44c66ac9dbSNicholas Bellinger #include <target/target_core_transport.h> 45c66ac9dbSNicholas Bellinger #include <target/target_core_fabric_ops.h> 46c66ac9dbSNicholas Bellinger 47c66ac9dbSNicholas Bellinger #include "target_core_hba.h" 48e3d6f909SAndy Grover #include "target_core_stat.h" 49e3d6f909SAndy Grover 50e3d6f909SAndy Grover extern struct se_device *g_lun0_dev; 51e3d6f909SAndy Grover 52e3d6f909SAndy Grover static DEFINE_SPINLOCK(tpg_lock); 53e3d6f909SAndy Grover static LIST_HEAD(tpg_list); 54c66ac9dbSNicholas Bellinger 55c66ac9dbSNicholas Bellinger /* core_clear_initiator_node_from_tpg(): 56c66ac9dbSNicholas Bellinger * 57c66ac9dbSNicholas Bellinger * 58c66ac9dbSNicholas Bellinger */ 59c66ac9dbSNicholas Bellinger static void core_clear_initiator_node_from_tpg( 60c66ac9dbSNicholas Bellinger struct se_node_acl *nacl, 61c66ac9dbSNicholas Bellinger struct se_portal_group *tpg) 62c66ac9dbSNicholas Bellinger { 63c66ac9dbSNicholas Bellinger int i; 64c66ac9dbSNicholas Bellinger struct se_dev_entry *deve; 65c66ac9dbSNicholas Bellinger struct se_lun *lun; 66c66ac9dbSNicholas Bellinger struct se_lun_acl *acl, *acl_tmp; 67c66ac9dbSNicholas Bellinger 68c66ac9dbSNicholas Bellinger spin_lock_irq(&nacl->device_list_lock); 69c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 70c66ac9dbSNicholas Bellinger deve = &nacl->device_list[i]; 71c66ac9dbSNicholas Bellinger 72c66ac9dbSNicholas Bellinger if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)) 73c66ac9dbSNicholas Bellinger continue; 74c66ac9dbSNicholas Bellinger 75c66ac9dbSNicholas Bellinger if (!deve->se_lun) { 766708bb27SAndy Grover pr_err("%s device entries device pointer is" 77c66ac9dbSNicholas Bellinger " NULL, but Initiator has access.\n", 78e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name()); 79c66ac9dbSNicholas Bellinger continue; 80c66ac9dbSNicholas Bellinger } 81c66ac9dbSNicholas Bellinger 82c66ac9dbSNicholas Bellinger lun = deve->se_lun; 83c66ac9dbSNicholas Bellinger spin_unlock_irq(&nacl->device_list_lock); 84c66ac9dbSNicholas Bellinger core_update_device_list_for_node(lun, NULL, deve->mapped_lun, 85c66ac9dbSNicholas Bellinger TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg, 0); 86c66ac9dbSNicholas Bellinger 87c66ac9dbSNicholas Bellinger spin_lock(&lun->lun_acl_lock); 88c66ac9dbSNicholas Bellinger list_for_each_entry_safe(acl, acl_tmp, 89c66ac9dbSNicholas Bellinger &lun->lun_acl_list, lacl_list) { 906708bb27SAndy Grover if (!strcmp(acl->initiatorname, nacl->initiatorname) && 91c66ac9dbSNicholas Bellinger (acl->mapped_lun == deve->mapped_lun)) 92c66ac9dbSNicholas Bellinger break; 93c66ac9dbSNicholas Bellinger } 94c66ac9dbSNicholas Bellinger 95c66ac9dbSNicholas Bellinger if (!acl) { 966708bb27SAndy Grover pr_err("Unable to locate struct se_lun_acl for %s," 97c66ac9dbSNicholas Bellinger " mapped_lun: %u\n", nacl->initiatorname, 98c66ac9dbSNicholas Bellinger deve->mapped_lun); 99c66ac9dbSNicholas Bellinger spin_unlock(&lun->lun_acl_lock); 100c66ac9dbSNicholas Bellinger spin_lock_irq(&nacl->device_list_lock); 101c66ac9dbSNicholas Bellinger continue; 102c66ac9dbSNicholas Bellinger } 103c66ac9dbSNicholas Bellinger 104c66ac9dbSNicholas Bellinger list_del(&acl->lacl_list); 105c66ac9dbSNicholas Bellinger spin_unlock(&lun->lun_acl_lock); 106c66ac9dbSNicholas Bellinger 107c66ac9dbSNicholas Bellinger spin_lock_irq(&nacl->device_list_lock); 108c66ac9dbSNicholas Bellinger kfree(acl); 109c66ac9dbSNicholas Bellinger } 110c66ac9dbSNicholas Bellinger spin_unlock_irq(&nacl->device_list_lock); 111c66ac9dbSNicholas Bellinger } 112c66ac9dbSNicholas Bellinger 113c66ac9dbSNicholas Bellinger /* __core_tpg_get_initiator_node_acl(): 114c66ac9dbSNicholas Bellinger * 115c66ac9dbSNicholas Bellinger * spin_lock_bh(&tpg->acl_node_lock); must be held when calling 116c66ac9dbSNicholas Bellinger */ 117c66ac9dbSNicholas Bellinger struct se_node_acl *__core_tpg_get_initiator_node_acl( 118c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 119c66ac9dbSNicholas Bellinger const char *initiatorname) 120c66ac9dbSNicholas Bellinger { 121c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 122c66ac9dbSNicholas Bellinger 123c66ac9dbSNicholas Bellinger list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { 1246708bb27SAndy Grover if (!strcmp(acl->initiatorname, initiatorname)) 125c66ac9dbSNicholas Bellinger return acl; 126c66ac9dbSNicholas Bellinger } 127c66ac9dbSNicholas Bellinger 128c66ac9dbSNicholas Bellinger return NULL; 129c66ac9dbSNicholas Bellinger } 130c66ac9dbSNicholas Bellinger 131c66ac9dbSNicholas Bellinger /* core_tpg_get_initiator_node_acl(): 132c66ac9dbSNicholas Bellinger * 133c66ac9dbSNicholas Bellinger * 134c66ac9dbSNicholas Bellinger */ 135c66ac9dbSNicholas Bellinger struct se_node_acl *core_tpg_get_initiator_node_acl( 136c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 137c66ac9dbSNicholas Bellinger unsigned char *initiatorname) 138c66ac9dbSNicholas Bellinger { 139c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 140c66ac9dbSNicholas Bellinger 14128638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 142c66ac9dbSNicholas Bellinger list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { 1436708bb27SAndy Grover if (!strcmp(acl->initiatorname, initiatorname) && 1446708bb27SAndy Grover !acl->dynamic_node_acl) { 14528638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 146c66ac9dbSNicholas Bellinger return acl; 147c66ac9dbSNicholas Bellinger } 148c66ac9dbSNicholas Bellinger } 14928638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 150c66ac9dbSNicholas Bellinger 151c66ac9dbSNicholas Bellinger return NULL; 152c66ac9dbSNicholas Bellinger } 153c66ac9dbSNicholas Bellinger 154c66ac9dbSNicholas Bellinger /* core_tpg_add_node_to_devs(): 155c66ac9dbSNicholas Bellinger * 156c66ac9dbSNicholas Bellinger * 157c66ac9dbSNicholas Bellinger */ 158c66ac9dbSNicholas Bellinger void core_tpg_add_node_to_devs( 159c66ac9dbSNicholas Bellinger struct se_node_acl *acl, 160c66ac9dbSNicholas Bellinger struct se_portal_group *tpg) 161c66ac9dbSNicholas Bellinger { 162c66ac9dbSNicholas Bellinger int i = 0; 163c66ac9dbSNicholas Bellinger u32 lun_access = 0; 164c66ac9dbSNicholas Bellinger struct se_lun *lun; 165c66ac9dbSNicholas Bellinger struct se_device *dev; 166c66ac9dbSNicholas Bellinger 167c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 168c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 169c66ac9dbSNicholas Bellinger lun = &tpg->tpg_lun_list[i]; 170c66ac9dbSNicholas Bellinger if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) 171c66ac9dbSNicholas Bellinger continue; 172c66ac9dbSNicholas Bellinger 173c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 174c66ac9dbSNicholas Bellinger 175c66ac9dbSNicholas Bellinger dev = lun->lun_se_dev; 176c66ac9dbSNicholas Bellinger /* 177c66ac9dbSNicholas Bellinger * By default in LIO-Target $FABRIC_MOD, 178c66ac9dbSNicholas Bellinger * demo_mode_write_protect is ON, or READ_ONLY; 179c66ac9dbSNicholas Bellinger */ 1806708bb27SAndy Grover if (!tpg->se_tpg_tfo->tpg_check_demo_mode_write_protect(tpg)) { 181c66ac9dbSNicholas Bellinger if (dev->dev_flags & DF_READ_ONLY) 182c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_ONLY; 183c66ac9dbSNicholas Bellinger else 184c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; 185c66ac9dbSNicholas Bellinger } else { 186c66ac9dbSNicholas Bellinger /* 187c66ac9dbSNicholas Bellinger * Allow only optical drives to issue R/W in default RO 188c66ac9dbSNicholas Bellinger * demo mode. 189c66ac9dbSNicholas Bellinger */ 190e3d6f909SAndy Grover if (dev->transport->get_device_type(dev) == TYPE_DISK) 191c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_ONLY; 192c66ac9dbSNicholas Bellinger else 193c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; 194c66ac9dbSNicholas Bellinger } 195c66ac9dbSNicholas Bellinger 1966708bb27SAndy Grover pr_debug("TARGET_CORE[%s]->TPG[%u]_LUN[%u] - Adding %s" 197c66ac9dbSNicholas Bellinger " access for LUN in Demo Mode\n", 198e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), 199e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, 200c66ac9dbSNicholas Bellinger (lun_access == TRANSPORT_LUNFLAGS_READ_WRITE) ? 201c66ac9dbSNicholas Bellinger "READ-WRITE" : "READ-ONLY"); 202c66ac9dbSNicholas Bellinger 203c66ac9dbSNicholas Bellinger core_update_device_list_for_node(lun, NULL, lun->unpacked_lun, 204c66ac9dbSNicholas Bellinger lun_access, acl, tpg, 1); 205c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 206c66ac9dbSNicholas Bellinger } 207c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 208c66ac9dbSNicholas Bellinger } 209c66ac9dbSNicholas Bellinger 210c66ac9dbSNicholas Bellinger /* core_set_queue_depth_for_node(): 211c66ac9dbSNicholas Bellinger * 212c66ac9dbSNicholas Bellinger * 213c66ac9dbSNicholas Bellinger */ 214c66ac9dbSNicholas Bellinger static int core_set_queue_depth_for_node( 215c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 216c66ac9dbSNicholas Bellinger struct se_node_acl *acl) 217c66ac9dbSNicholas Bellinger { 218c66ac9dbSNicholas Bellinger if (!acl->queue_depth) { 2196708bb27SAndy Grover pr_err("Queue depth for %s Initiator Node: %s is 0," 220e3d6f909SAndy Grover "defaulting to 1.\n", tpg->se_tpg_tfo->get_fabric_name(), 221c66ac9dbSNicholas Bellinger acl->initiatorname); 222c66ac9dbSNicholas Bellinger acl->queue_depth = 1; 223c66ac9dbSNicholas Bellinger } 224c66ac9dbSNicholas Bellinger 225c66ac9dbSNicholas Bellinger return 0; 226c66ac9dbSNicholas Bellinger } 227c66ac9dbSNicholas Bellinger 228c66ac9dbSNicholas Bellinger /* core_create_device_list_for_node(): 229c66ac9dbSNicholas Bellinger * 230c66ac9dbSNicholas Bellinger * 231c66ac9dbSNicholas Bellinger */ 232c66ac9dbSNicholas Bellinger static int core_create_device_list_for_node(struct se_node_acl *nacl) 233c66ac9dbSNicholas Bellinger { 234c66ac9dbSNicholas Bellinger struct se_dev_entry *deve; 235c66ac9dbSNicholas Bellinger int i; 236c66ac9dbSNicholas Bellinger 237c66ac9dbSNicholas Bellinger nacl->device_list = kzalloc(sizeof(struct se_dev_entry) * 238c66ac9dbSNicholas Bellinger TRANSPORT_MAX_LUNS_PER_TPG, GFP_KERNEL); 2396708bb27SAndy Grover if (!nacl->device_list) { 2406708bb27SAndy Grover pr_err("Unable to allocate memory for" 241c66ac9dbSNicholas Bellinger " struct se_node_acl->device_list\n"); 242e3d6f909SAndy Grover return -ENOMEM; 243c66ac9dbSNicholas Bellinger } 244c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 245c66ac9dbSNicholas Bellinger deve = &nacl->device_list[i]; 246c66ac9dbSNicholas Bellinger 247c66ac9dbSNicholas Bellinger atomic_set(&deve->ua_count, 0); 248c66ac9dbSNicholas Bellinger atomic_set(&deve->pr_ref_count, 0); 249c66ac9dbSNicholas Bellinger spin_lock_init(&deve->ua_lock); 250c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&deve->alua_port_list); 251c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&deve->ua_list); 252c66ac9dbSNicholas Bellinger } 253c66ac9dbSNicholas Bellinger 254c66ac9dbSNicholas Bellinger return 0; 255c66ac9dbSNicholas Bellinger } 256c66ac9dbSNicholas Bellinger 257c66ac9dbSNicholas Bellinger /* core_tpg_check_initiator_node_acl() 258c66ac9dbSNicholas Bellinger * 259c66ac9dbSNicholas Bellinger * 260c66ac9dbSNicholas Bellinger */ 261c66ac9dbSNicholas Bellinger struct se_node_acl *core_tpg_check_initiator_node_acl( 262c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 263c66ac9dbSNicholas Bellinger unsigned char *initiatorname) 264c66ac9dbSNicholas Bellinger { 265c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 266c66ac9dbSNicholas Bellinger 267c66ac9dbSNicholas Bellinger acl = core_tpg_get_initiator_node_acl(tpg, initiatorname); 2686708bb27SAndy Grover if (acl) 269c66ac9dbSNicholas Bellinger return acl; 270c66ac9dbSNicholas Bellinger 2716708bb27SAndy Grover if (!tpg->se_tpg_tfo->tpg_check_demo_mode(tpg)) 272c66ac9dbSNicholas Bellinger return NULL; 273c66ac9dbSNicholas Bellinger 274e3d6f909SAndy Grover acl = tpg->se_tpg_tfo->tpg_alloc_fabric_acl(tpg); 2756708bb27SAndy Grover if (!acl) 276c66ac9dbSNicholas Bellinger return NULL; 277c66ac9dbSNicholas Bellinger 278c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_list); 279c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_sess_list); 280c66ac9dbSNicholas Bellinger spin_lock_init(&acl->device_list_lock); 281c66ac9dbSNicholas Bellinger spin_lock_init(&acl->nacl_sess_lock); 282c66ac9dbSNicholas Bellinger atomic_set(&acl->acl_pr_ref_count, 0); 283e3d6f909SAndy Grover acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg); 284c66ac9dbSNicholas Bellinger snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); 285c66ac9dbSNicholas Bellinger acl->se_tpg = tpg; 286c66ac9dbSNicholas Bellinger acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX); 287c66ac9dbSNicholas Bellinger spin_lock_init(&acl->stats_lock); 288c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 289c66ac9dbSNicholas Bellinger 290e3d6f909SAndy Grover tpg->se_tpg_tfo->set_default_node_attributes(acl); 291c66ac9dbSNicholas Bellinger 292c66ac9dbSNicholas Bellinger if (core_create_device_list_for_node(acl) < 0) { 293e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); 294c66ac9dbSNicholas Bellinger return NULL; 295c66ac9dbSNicholas Bellinger } 296c66ac9dbSNicholas Bellinger 297c66ac9dbSNicholas Bellinger if (core_set_queue_depth_for_node(tpg, acl) < 0) { 298c66ac9dbSNicholas Bellinger core_free_device_list_for_node(acl, tpg); 299e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); 300c66ac9dbSNicholas Bellinger return NULL; 301c66ac9dbSNicholas Bellinger } 302052605c6SNicholas Bellinger /* 303052605c6SNicholas Bellinger * Here we only create demo-mode MappedLUNs from the active 304052605c6SNicholas Bellinger * TPG LUNs if the fabric is not explictly asking for 305052605c6SNicholas Bellinger * tpg_check_demo_mode_login_only() == 1. 306052605c6SNicholas Bellinger */ 307052605c6SNicholas Bellinger if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only != NULL) && 308052605c6SNicholas Bellinger (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) == 1)) 309052605c6SNicholas Bellinger do { ; } while (0); 310052605c6SNicholas Bellinger else 311c66ac9dbSNicholas Bellinger core_tpg_add_node_to_devs(acl, tpg); 312c66ac9dbSNicholas Bellinger 31328638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 314c66ac9dbSNicholas Bellinger list_add_tail(&acl->acl_list, &tpg->acl_node_list); 315c66ac9dbSNicholas Bellinger tpg->num_node_acls++; 31628638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 317c66ac9dbSNicholas Bellinger 3186708bb27SAndy Grover pr_debug("%s_TPG[%u] - Added DYNAMIC ACL with TCQ Depth: %d for %s" 319e3d6f909SAndy Grover " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(), 320e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth, 321e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), initiatorname); 322c66ac9dbSNicholas Bellinger 323c66ac9dbSNicholas Bellinger return acl; 324c66ac9dbSNicholas Bellinger } 325c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_check_initiator_node_acl); 326c66ac9dbSNicholas Bellinger 327c66ac9dbSNicholas Bellinger void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *nacl) 328c66ac9dbSNicholas Bellinger { 329c66ac9dbSNicholas Bellinger while (atomic_read(&nacl->acl_pr_ref_count) != 0) 330c66ac9dbSNicholas Bellinger cpu_relax(); 331c66ac9dbSNicholas Bellinger } 332c66ac9dbSNicholas Bellinger 333c66ac9dbSNicholas Bellinger void core_tpg_clear_object_luns(struct se_portal_group *tpg) 334c66ac9dbSNicholas Bellinger { 335c66ac9dbSNicholas Bellinger int i, ret; 336c66ac9dbSNicholas Bellinger struct se_lun *lun; 337c66ac9dbSNicholas Bellinger 338c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 339c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 340c66ac9dbSNicholas Bellinger lun = &tpg->tpg_lun_list[i]; 341c66ac9dbSNicholas Bellinger 342c66ac9dbSNicholas Bellinger if ((lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) || 343c66ac9dbSNicholas Bellinger (lun->lun_se_dev == NULL)) 344c66ac9dbSNicholas Bellinger continue; 345c66ac9dbSNicholas Bellinger 346c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 347c66ac9dbSNicholas Bellinger ret = core_dev_del_lun(tpg, lun->unpacked_lun); 348c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 349c66ac9dbSNicholas Bellinger } 350c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 351c66ac9dbSNicholas Bellinger } 352c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_clear_object_luns); 353c66ac9dbSNicholas Bellinger 354c66ac9dbSNicholas Bellinger /* core_tpg_add_initiator_node_acl(): 355c66ac9dbSNicholas Bellinger * 356c66ac9dbSNicholas Bellinger * 357c66ac9dbSNicholas Bellinger */ 358c66ac9dbSNicholas Bellinger struct se_node_acl *core_tpg_add_initiator_node_acl( 359c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 360c66ac9dbSNicholas Bellinger struct se_node_acl *se_nacl, 361c66ac9dbSNicholas Bellinger const char *initiatorname, 362c66ac9dbSNicholas Bellinger u32 queue_depth) 363c66ac9dbSNicholas Bellinger { 364c66ac9dbSNicholas Bellinger struct se_node_acl *acl = NULL; 365c66ac9dbSNicholas Bellinger 36628638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 367c66ac9dbSNicholas Bellinger acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); 3686708bb27SAndy Grover if (acl) { 369c66ac9dbSNicholas Bellinger if (acl->dynamic_node_acl) { 370c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 0; 3716708bb27SAndy Grover pr_debug("%s_TPG[%u] - Replacing dynamic ACL" 372e3d6f909SAndy Grover " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), 373e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname); 37428638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 375c66ac9dbSNicholas Bellinger /* 376c66ac9dbSNicholas Bellinger * Release the locally allocated struct se_node_acl 377c66ac9dbSNicholas Bellinger * because * core_tpg_add_initiator_node_acl() returned 378c66ac9dbSNicholas Bellinger * a pointer to an existing demo mode node ACL. 379c66ac9dbSNicholas Bellinger */ 380c66ac9dbSNicholas Bellinger if (se_nacl) 381e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, 382c66ac9dbSNicholas Bellinger se_nacl); 383c66ac9dbSNicholas Bellinger goto done; 384c66ac9dbSNicholas Bellinger } 385c66ac9dbSNicholas Bellinger 3866708bb27SAndy Grover pr_err("ACL entry for %s Initiator" 387c66ac9dbSNicholas Bellinger " Node %s already exists for TPG %u, ignoring" 388e3d6f909SAndy Grover " request.\n", tpg->se_tpg_tfo->get_fabric_name(), 389e3d6f909SAndy Grover initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); 39028638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 391c66ac9dbSNicholas Bellinger return ERR_PTR(-EEXIST); 392c66ac9dbSNicholas Bellinger } 39328638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 394c66ac9dbSNicholas Bellinger 3956708bb27SAndy Grover if (!se_nacl) { 3966708bb27SAndy Grover pr_err("struct se_node_acl pointer is NULL\n"); 397c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 398c66ac9dbSNicholas Bellinger } 399c66ac9dbSNicholas Bellinger /* 400c66ac9dbSNicholas Bellinger * For v4.x logic the se_node_acl_s is hanging off a fabric 401c66ac9dbSNicholas Bellinger * dependent structure allocated via 402c66ac9dbSNicholas Bellinger * struct target_core_fabric_ops->fabric_make_nodeacl() 403c66ac9dbSNicholas Bellinger */ 404c66ac9dbSNicholas Bellinger acl = se_nacl; 405c66ac9dbSNicholas Bellinger 406c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_list); 407c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_sess_list); 408c66ac9dbSNicholas Bellinger spin_lock_init(&acl->device_list_lock); 409c66ac9dbSNicholas Bellinger spin_lock_init(&acl->nacl_sess_lock); 410c66ac9dbSNicholas Bellinger atomic_set(&acl->acl_pr_ref_count, 0); 411c66ac9dbSNicholas Bellinger acl->queue_depth = queue_depth; 412c66ac9dbSNicholas Bellinger snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); 413c66ac9dbSNicholas Bellinger acl->se_tpg = tpg; 414c66ac9dbSNicholas Bellinger acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX); 415c66ac9dbSNicholas Bellinger spin_lock_init(&acl->stats_lock); 416c66ac9dbSNicholas Bellinger 417e3d6f909SAndy Grover tpg->se_tpg_tfo->set_default_node_attributes(acl); 418c66ac9dbSNicholas Bellinger 419c66ac9dbSNicholas Bellinger if (core_create_device_list_for_node(acl) < 0) { 420e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); 421c66ac9dbSNicholas Bellinger return ERR_PTR(-ENOMEM); 422c66ac9dbSNicholas Bellinger } 423c66ac9dbSNicholas Bellinger 424c66ac9dbSNicholas Bellinger if (core_set_queue_depth_for_node(tpg, acl) < 0) { 425c66ac9dbSNicholas Bellinger core_free_device_list_for_node(acl, tpg); 426e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); 427c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 428c66ac9dbSNicholas Bellinger } 429c66ac9dbSNicholas Bellinger 43028638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 431c66ac9dbSNicholas Bellinger list_add_tail(&acl->acl_list, &tpg->acl_node_list); 432c66ac9dbSNicholas Bellinger tpg->num_node_acls++; 43328638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 434c66ac9dbSNicholas Bellinger 435c66ac9dbSNicholas Bellinger done: 4366708bb27SAndy Grover pr_debug("%s_TPG[%hu] - Added ACL with TCQ Depth: %d for %s" 437e3d6f909SAndy Grover " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(), 438e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth, 439e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), initiatorname); 440c66ac9dbSNicholas Bellinger 441c66ac9dbSNicholas Bellinger return acl; 442c66ac9dbSNicholas Bellinger } 443c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_add_initiator_node_acl); 444c66ac9dbSNicholas Bellinger 445c66ac9dbSNicholas Bellinger /* core_tpg_del_initiator_node_acl(): 446c66ac9dbSNicholas Bellinger * 447c66ac9dbSNicholas Bellinger * 448c66ac9dbSNicholas Bellinger */ 449c66ac9dbSNicholas Bellinger int core_tpg_del_initiator_node_acl( 450c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 451c66ac9dbSNicholas Bellinger struct se_node_acl *acl, 452c66ac9dbSNicholas Bellinger int force) 453c66ac9dbSNicholas Bellinger { 454c66ac9dbSNicholas Bellinger struct se_session *sess, *sess_tmp; 455c66ac9dbSNicholas Bellinger int dynamic_acl = 0; 456c66ac9dbSNicholas Bellinger 45728638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 458c66ac9dbSNicholas Bellinger if (acl->dynamic_node_acl) { 459c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 0; 460c66ac9dbSNicholas Bellinger dynamic_acl = 1; 461c66ac9dbSNicholas Bellinger } 462c66ac9dbSNicholas Bellinger list_del(&acl->acl_list); 463c66ac9dbSNicholas Bellinger tpg->num_node_acls--; 46428638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 465c66ac9dbSNicholas Bellinger 466c66ac9dbSNicholas Bellinger spin_lock_bh(&tpg->session_lock); 467c66ac9dbSNicholas Bellinger list_for_each_entry_safe(sess, sess_tmp, 468c66ac9dbSNicholas Bellinger &tpg->tpg_sess_list, sess_list) { 469c66ac9dbSNicholas Bellinger if (sess->se_node_acl != acl) 470c66ac9dbSNicholas Bellinger continue; 471c66ac9dbSNicholas Bellinger /* 472c66ac9dbSNicholas Bellinger * Determine if the session needs to be closed by our context. 473c66ac9dbSNicholas Bellinger */ 4746708bb27SAndy Grover if (!tpg->se_tpg_tfo->shutdown_session(sess)) 475c66ac9dbSNicholas Bellinger continue; 476c66ac9dbSNicholas Bellinger 477c66ac9dbSNicholas Bellinger spin_unlock_bh(&tpg->session_lock); 478c66ac9dbSNicholas Bellinger /* 479c66ac9dbSNicholas Bellinger * If the $FABRIC_MOD session for the Initiator Node ACL exists, 480c66ac9dbSNicholas Bellinger * forcefully shutdown the $FABRIC_MOD session/nexus. 481c66ac9dbSNicholas Bellinger */ 482e3d6f909SAndy Grover tpg->se_tpg_tfo->close_session(sess); 483c66ac9dbSNicholas Bellinger 484c66ac9dbSNicholas Bellinger spin_lock_bh(&tpg->session_lock); 485c66ac9dbSNicholas Bellinger } 486c66ac9dbSNicholas Bellinger spin_unlock_bh(&tpg->session_lock); 487c66ac9dbSNicholas Bellinger 488c66ac9dbSNicholas Bellinger core_tpg_wait_for_nacl_pr_ref(acl); 489c66ac9dbSNicholas Bellinger core_clear_initiator_node_from_tpg(acl, tpg); 490c66ac9dbSNicholas Bellinger core_free_device_list_for_node(acl, tpg); 491c66ac9dbSNicholas Bellinger 4926708bb27SAndy Grover pr_debug("%s_TPG[%hu] - Deleted ACL with TCQ Depth: %d for %s" 493e3d6f909SAndy Grover " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(), 494e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth, 495e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), acl->initiatorname); 496c66ac9dbSNicholas Bellinger 497c66ac9dbSNicholas Bellinger return 0; 498c66ac9dbSNicholas Bellinger } 499c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_del_initiator_node_acl); 500c66ac9dbSNicholas Bellinger 501c66ac9dbSNicholas Bellinger /* core_tpg_set_initiator_node_queue_depth(): 502c66ac9dbSNicholas Bellinger * 503c66ac9dbSNicholas Bellinger * 504c66ac9dbSNicholas Bellinger */ 505c66ac9dbSNicholas Bellinger int core_tpg_set_initiator_node_queue_depth( 506c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 507c66ac9dbSNicholas Bellinger unsigned char *initiatorname, 508c66ac9dbSNicholas Bellinger u32 queue_depth, 509c66ac9dbSNicholas Bellinger int force) 510c66ac9dbSNicholas Bellinger { 511c66ac9dbSNicholas Bellinger struct se_session *sess, *init_sess = NULL; 512c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 513c66ac9dbSNicholas Bellinger int dynamic_acl = 0; 514c66ac9dbSNicholas Bellinger 51528638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 516c66ac9dbSNicholas Bellinger acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); 5176708bb27SAndy Grover if (!acl) { 5186708bb27SAndy Grover pr_err("Access Control List entry for %s Initiator" 519c66ac9dbSNicholas Bellinger " Node %s does not exists for TPG %hu, ignoring" 520e3d6f909SAndy Grover " request.\n", tpg->se_tpg_tfo->get_fabric_name(), 521e3d6f909SAndy Grover initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); 52228638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 523c66ac9dbSNicholas Bellinger return -ENODEV; 524c66ac9dbSNicholas Bellinger } 525c66ac9dbSNicholas Bellinger if (acl->dynamic_node_acl) { 526c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 0; 527c66ac9dbSNicholas Bellinger dynamic_acl = 1; 528c66ac9dbSNicholas Bellinger } 52928638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 530c66ac9dbSNicholas Bellinger 531c66ac9dbSNicholas Bellinger spin_lock_bh(&tpg->session_lock); 532c66ac9dbSNicholas Bellinger list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) { 533c66ac9dbSNicholas Bellinger if (sess->se_node_acl != acl) 534c66ac9dbSNicholas Bellinger continue; 535c66ac9dbSNicholas Bellinger 536c66ac9dbSNicholas Bellinger if (!force) { 5376708bb27SAndy Grover pr_err("Unable to change queue depth for %s" 538c66ac9dbSNicholas Bellinger " Initiator Node: %s while session is" 539c66ac9dbSNicholas Bellinger " operational. To forcefully change the queue" 540c66ac9dbSNicholas Bellinger " depth and force session reinstatement" 541c66ac9dbSNicholas Bellinger " use the \"force=1\" parameter.\n", 542e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), initiatorname); 543c66ac9dbSNicholas Bellinger spin_unlock_bh(&tpg->session_lock); 544c66ac9dbSNicholas Bellinger 54528638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 546c66ac9dbSNicholas Bellinger if (dynamic_acl) 547c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 54828638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 549c66ac9dbSNicholas Bellinger return -EEXIST; 550c66ac9dbSNicholas Bellinger } 551c66ac9dbSNicholas Bellinger /* 552c66ac9dbSNicholas Bellinger * Determine if the session needs to be closed by our context. 553c66ac9dbSNicholas Bellinger */ 5546708bb27SAndy Grover if (!tpg->se_tpg_tfo->shutdown_session(sess)) 555c66ac9dbSNicholas Bellinger continue; 556c66ac9dbSNicholas Bellinger 557c66ac9dbSNicholas Bellinger init_sess = sess; 558c66ac9dbSNicholas Bellinger break; 559c66ac9dbSNicholas Bellinger } 560c66ac9dbSNicholas Bellinger 561c66ac9dbSNicholas Bellinger /* 562c66ac9dbSNicholas Bellinger * User has requested to change the queue depth for a Initiator Node. 563c66ac9dbSNicholas Bellinger * Change the value in the Node's struct se_node_acl, and call 564c66ac9dbSNicholas Bellinger * core_set_queue_depth_for_node() to add the requested queue depth. 565c66ac9dbSNicholas Bellinger * 566e3d6f909SAndy Grover * Finally call tpg->se_tpg_tfo->close_session() to force session 567c66ac9dbSNicholas Bellinger * reinstatement to occur if there is an active session for the 568c66ac9dbSNicholas Bellinger * $FABRIC_MOD Initiator Node in question. 569c66ac9dbSNicholas Bellinger */ 570c66ac9dbSNicholas Bellinger acl->queue_depth = queue_depth; 571c66ac9dbSNicholas Bellinger 572c66ac9dbSNicholas Bellinger if (core_set_queue_depth_for_node(tpg, acl) < 0) { 573c66ac9dbSNicholas Bellinger spin_unlock_bh(&tpg->session_lock); 574c66ac9dbSNicholas Bellinger /* 575c66ac9dbSNicholas Bellinger * Force session reinstatement if 576c66ac9dbSNicholas Bellinger * core_set_queue_depth_for_node() failed, because we assume 577c66ac9dbSNicholas Bellinger * the $FABRIC_MOD has already the set session reinstatement 578e3d6f909SAndy Grover * bit from tpg->se_tpg_tfo->shutdown_session() called above. 579c66ac9dbSNicholas Bellinger */ 580c66ac9dbSNicholas Bellinger if (init_sess) 581e3d6f909SAndy Grover tpg->se_tpg_tfo->close_session(init_sess); 582c66ac9dbSNicholas Bellinger 58328638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 584c66ac9dbSNicholas Bellinger if (dynamic_acl) 585c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 58628638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 587c66ac9dbSNicholas Bellinger return -EINVAL; 588c66ac9dbSNicholas Bellinger } 589c66ac9dbSNicholas Bellinger spin_unlock_bh(&tpg->session_lock); 590c66ac9dbSNicholas Bellinger /* 591c66ac9dbSNicholas Bellinger * If the $FABRIC_MOD session for the Initiator Node ACL exists, 592c66ac9dbSNicholas Bellinger * forcefully shutdown the $FABRIC_MOD session/nexus. 593c66ac9dbSNicholas Bellinger */ 594c66ac9dbSNicholas Bellinger if (init_sess) 595e3d6f909SAndy Grover tpg->se_tpg_tfo->close_session(init_sess); 596c66ac9dbSNicholas Bellinger 597bfb9035cSJoe Perches pr_debug("Successfully changed queue depth to: %d for Initiator" 598c66ac9dbSNicholas Bellinger " Node: %s on %s Target Portal Group: %u\n", queue_depth, 599e3d6f909SAndy Grover initiatorname, tpg->se_tpg_tfo->get_fabric_name(), 600e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 601c66ac9dbSNicholas Bellinger 60228638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 603c66ac9dbSNicholas Bellinger if (dynamic_acl) 604c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 60528638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 606c66ac9dbSNicholas Bellinger 607c66ac9dbSNicholas Bellinger return 0; 608c66ac9dbSNicholas Bellinger } 609c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth); 610c66ac9dbSNicholas Bellinger 611c66ac9dbSNicholas Bellinger static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) 612c66ac9dbSNicholas Bellinger { 613c66ac9dbSNicholas Bellinger /* Set in core_dev_setup_virtual_lun0() */ 614e3d6f909SAndy Grover struct se_device *dev = g_lun0_dev; 615c66ac9dbSNicholas Bellinger struct se_lun *lun = &se_tpg->tpg_virt_lun0; 616c66ac9dbSNicholas Bellinger u32 lun_access = TRANSPORT_LUNFLAGS_READ_ONLY; 617c66ac9dbSNicholas Bellinger int ret; 618c66ac9dbSNicholas Bellinger 619c66ac9dbSNicholas Bellinger lun->unpacked_lun = 0; 620c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 621c66ac9dbSNicholas Bellinger atomic_set(&lun->lun_acl_count, 0); 622c66ac9dbSNicholas Bellinger init_completion(&lun->lun_shutdown_comp); 623c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lun->lun_acl_list); 624c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lun->lun_cmd_list); 625c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_acl_lock); 626c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_cmd_lock); 627c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_sep_lock); 628c66ac9dbSNicholas Bellinger 629c66ac9dbSNicholas Bellinger ret = core_tpg_post_addlun(se_tpg, lun, lun_access, dev); 630c66ac9dbSNicholas Bellinger if (ret < 0) 631e3d6f909SAndy Grover return ret; 632c66ac9dbSNicholas Bellinger 633c66ac9dbSNicholas Bellinger return 0; 634c66ac9dbSNicholas Bellinger } 635c66ac9dbSNicholas Bellinger 636c66ac9dbSNicholas Bellinger static void core_tpg_release_virtual_lun0(struct se_portal_group *se_tpg) 637c66ac9dbSNicholas Bellinger { 638c66ac9dbSNicholas Bellinger struct se_lun *lun = &se_tpg->tpg_virt_lun0; 639c66ac9dbSNicholas Bellinger 640c66ac9dbSNicholas Bellinger core_tpg_post_dellun(se_tpg, lun); 641c66ac9dbSNicholas Bellinger } 642c66ac9dbSNicholas Bellinger 643c66ac9dbSNicholas Bellinger int core_tpg_register( 644c66ac9dbSNicholas Bellinger struct target_core_fabric_ops *tfo, 645c66ac9dbSNicholas Bellinger struct se_wwn *se_wwn, 646c66ac9dbSNicholas Bellinger struct se_portal_group *se_tpg, 647c66ac9dbSNicholas Bellinger void *tpg_fabric_ptr, 648c66ac9dbSNicholas Bellinger int se_tpg_type) 649c66ac9dbSNicholas Bellinger { 650c66ac9dbSNicholas Bellinger struct se_lun *lun; 651c66ac9dbSNicholas Bellinger u32 i; 652c66ac9dbSNicholas Bellinger 653c66ac9dbSNicholas Bellinger se_tpg->tpg_lun_list = kzalloc((sizeof(struct se_lun) * 654c66ac9dbSNicholas Bellinger TRANSPORT_MAX_LUNS_PER_TPG), GFP_KERNEL); 6556708bb27SAndy Grover if (!se_tpg->tpg_lun_list) { 6566708bb27SAndy Grover pr_err("Unable to allocate struct se_portal_group->" 657c66ac9dbSNicholas Bellinger "tpg_lun_list\n"); 658c66ac9dbSNicholas Bellinger return -ENOMEM; 659c66ac9dbSNicholas Bellinger } 660c66ac9dbSNicholas Bellinger 661c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 662c66ac9dbSNicholas Bellinger lun = &se_tpg->tpg_lun_list[i]; 663c66ac9dbSNicholas Bellinger lun->unpacked_lun = i; 664c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 665c66ac9dbSNicholas Bellinger atomic_set(&lun->lun_acl_count, 0); 666c66ac9dbSNicholas Bellinger init_completion(&lun->lun_shutdown_comp); 667c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lun->lun_acl_list); 668c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lun->lun_cmd_list); 669c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_acl_lock); 670c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_cmd_lock); 671c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_sep_lock); 672c66ac9dbSNicholas Bellinger } 673c66ac9dbSNicholas Bellinger 674c66ac9dbSNicholas Bellinger se_tpg->se_tpg_type = se_tpg_type; 675c66ac9dbSNicholas Bellinger se_tpg->se_tpg_fabric_ptr = tpg_fabric_ptr; 676c66ac9dbSNicholas Bellinger se_tpg->se_tpg_tfo = tfo; 677c66ac9dbSNicholas Bellinger se_tpg->se_tpg_wwn = se_wwn; 678c66ac9dbSNicholas Bellinger atomic_set(&se_tpg->tpg_pr_ref_count, 0); 679c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&se_tpg->acl_node_list); 680e3d6f909SAndy Grover INIT_LIST_HEAD(&se_tpg->se_tpg_node); 681c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&se_tpg->tpg_sess_list); 682c66ac9dbSNicholas Bellinger spin_lock_init(&se_tpg->acl_node_lock); 683c66ac9dbSNicholas Bellinger spin_lock_init(&se_tpg->session_lock); 684c66ac9dbSNicholas Bellinger spin_lock_init(&se_tpg->tpg_lun_lock); 685c66ac9dbSNicholas Bellinger 686c66ac9dbSNicholas Bellinger if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) { 687c66ac9dbSNicholas Bellinger if (core_tpg_setup_virtual_lun0(se_tpg) < 0) { 688c66ac9dbSNicholas Bellinger kfree(se_tpg); 689c66ac9dbSNicholas Bellinger return -ENOMEM; 690c66ac9dbSNicholas Bellinger } 691c66ac9dbSNicholas Bellinger } 692c66ac9dbSNicholas Bellinger 693e3d6f909SAndy Grover spin_lock_bh(&tpg_lock); 694e3d6f909SAndy Grover list_add_tail(&se_tpg->se_tpg_node, &tpg_list); 695e3d6f909SAndy Grover spin_unlock_bh(&tpg_lock); 696c66ac9dbSNicholas Bellinger 6976708bb27SAndy Grover pr_debug("TARGET_CORE[%s]: Allocated %s struct se_portal_group for" 698c66ac9dbSNicholas Bellinger " endpoint: %s, Portal Tag: %u\n", tfo->get_fabric_name(), 699c66ac9dbSNicholas Bellinger (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ? 700c66ac9dbSNicholas Bellinger "Normal" : "Discovery", (tfo->tpg_get_wwn(se_tpg) == NULL) ? 701c66ac9dbSNicholas Bellinger "None" : tfo->tpg_get_wwn(se_tpg), tfo->tpg_get_tag(se_tpg)); 702c66ac9dbSNicholas Bellinger 703c66ac9dbSNicholas Bellinger return 0; 704c66ac9dbSNicholas Bellinger } 705c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_register); 706c66ac9dbSNicholas Bellinger 707c66ac9dbSNicholas Bellinger int core_tpg_deregister(struct se_portal_group *se_tpg) 708c66ac9dbSNicholas Bellinger { 709e89d15eeSNicholas Bellinger struct se_node_acl *nacl, *nacl_tmp; 710e89d15eeSNicholas Bellinger 7116708bb27SAndy Grover pr_debug("TARGET_CORE[%s]: Deallocating %s struct se_portal_group" 712c66ac9dbSNicholas Bellinger " for endpoint: %s Portal Tag %u\n", 713c66ac9dbSNicholas Bellinger (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ? 714e3d6f909SAndy Grover "Normal" : "Discovery", se_tpg->se_tpg_tfo->get_fabric_name(), 715e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg), 716e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); 717c66ac9dbSNicholas Bellinger 718e3d6f909SAndy Grover spin_lock_bh(&tpg_lock); 719e3d6f909SAndy Grover list_del(&se_tpg->se_tpg_node); 720e3d6f909SAndy Grover spin_unlock_bh(&tpg_lock); 721c66ac9dbSNicholas Bellinger 722c66ac9dbSNicholas Bellinger while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0) 723c66ac9dbSNicholas Bellinger cpu_relax(); 724e89d15eeSNicholas Bellinger /* 725e89d15eeSNicholas Bellinger * Release any remaining demo-mode generated se_node_acl that have 726e89d15eeSNicholas Bellinger * not been released because of TFO->tpg_check_demo_mode_cache() == 1 727e89d15eeSNicholas Bellinger * in transport_deregister_session(). 728e89d15eeSNicholas Bellinger */ 72928638887SRoland Dreier spin_lock_irq(&se_tpg->acl_node_lock); 730e89d15eeSNicholas Bellinger list_for_each_entry_safe(nacl, nacl_tmp, &se_tpg->acl_node_list, 731e89d15eeSNicholas Bellinger acl_list) { 732e89d15eeSNicholas Bellinger list_del(&nacl->acl_list); 733e89d15eeSNicholas Bellinger se_tpg->num_node_acls--; 73428638887SRoland Dreier spin_unlock_irq(&se_tpg->acl_node_lock); 735e89d15eeSNicholas Bellinger 736e89d15eeSNicholas Bellinger core_tpg_wait_for_nacl_pr_ref(nacl); 737e89d15eeSNicholas Bellinger core_free_device_list_for_node(nacl, se_tpg); 738e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, nacl); 739e89d15eeSNicholas Bellinger 74028638887SRoland Dreier spin_lock_irq(&se_tpg->acl_node_lock); 741e89d15eeSNicholas Bellinger } 74228638887SRoland Dreier spin_unlock_irq(&se_tpg->acl_node_lock); 743c66ac9dbSNicholas Bellinger 744c66ac9dbSNicholas Bellinger if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) 745c66ac9dbSNicholas Bellinger core_tpg_release_virtual_lun0(se_tpg); 746c66ac9dbSNicholas Bellinger 747c66ac9dbSNicholas Bellinger se_tpg->se_tpg_fabric_ptr = NULL; 748c66ac9dbSNicholas Bellinger kfree(se_tpg->tpg_lun_list); 749c66ac9dbSNicholas Bellinger return 0; 750c66ac9dbSNicholas Bellinger } 751c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_deregister); 752c66ac9dbSNicholas Bellinger 753c66ac9dbSNicholas Bellinger struct se_lun *core_tpg_pre_addlun( 754c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 755c66ac9dbSNicholas Bellinger u32 unpacked_lun) 756c66ac9dbSNicholas Bellinger { 757c66ac9dbSNicholas Bellinger struct se_lun *lun; 758c66ac9dbSNicholas Bellinger 759c66ac9dbSNicholas Bellinger if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) { 7606708bb27SAndy Grover pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG" 761c66ac9dbSNicholas Bellinger "-1: %u for Target Portal Group: %u\n", 762e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), 763c66ac9dbSNicholas Bellinger unpacked_lun, TRANSPORT_MAX_LUNS_PER_TPG-1, 764e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 765c66ac9dbSNicholas Bellinger return ERR_PTR(-EOVERFLOW); 766c66ac9dbSNicholas Bellinger } 767c66ac9dbSNicholas Bellinger 768c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 769c66ac9dbSNicholas Bellinger lun = &tpg->tpg_lun_list[unpacked_lun]; 770c66ac9dbSNicholas Bellinger if (lun->lun_status == TRANSPORT_LUN_STATUS_ACTIVE) { 7716708bb27SAndy Grover pr_err("TPG Logical Unit Number: %u is already active" 772c66ac9dbSNicholas Bellinger " on %s Target Portal Group: %u, ignoring request.\n", 773e3d6f909SAndy Grover unpacked_lun, tpg->se_tpg_tfo->get_fabric_name(), 774e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 775c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 776c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 777c66ac9dbSNicholas Bellinger } 778c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 779c66ac9dbSNicholas Bellinger 780c66ac9dbSNicholas Bellinger return lun; 781c66ac9dbSNicholas Bellinger } 782c66ac9dbSNicholas Bellinger 783c66ac9dbSNicholas Bellinger int core_tpg_post_addlun( 784c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 785c66ac9dbSNicholas Bellinger struct se_lun *lun, 786c66ac9dbSNicholas Bellinger u32 lun_access, 787c66ac9dbSNicholas Bellinger void *lun_ptr) 788c66ac9dbSNicholas Bellinger { 789e3d6f909SAndy Grover int ret; 790e3d6f909SAndy Grover 791e3d6f909SAndy Grover ret = core_dev_export(lun_ptr, tpg, lun); 792e3d6f909SAndy Grover if (ret < 0) 793e3d6f909SAndy Grover return ret; 794c66ac9dbSNicholas Bellinger 795c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 796c66ac9dbSNicholas Bellinger lun->lun_access = lun_access; 797c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_ACTIVE; 798c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 799c66ac9dbSNicholas Bellinger 800c66ac9dbSNicholas Bellinger return 0; 801c66ac9dbSNicholas Bellinger } 802c66ac9dbSNicholas Bellinger 803c66ac9dbSNicholas Bellinger static void core_tpg_shutdown_lun( 804c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 805c66ac9dbSNicholas Bellinger struct se_lun *lun) 806c66ac9dbSNicholas Bellinger { 807c66ac9dbSNicholas Bellinger core_clear_lun_from_tpg(lun, tpg); 808c66ac9dbSNicholas Bellinger transport_clear_lun_from_sessions(lun); 809c66ac9dbSNicholas Bellinger } 810c66ac9dbSNicholas Bellinger 811c66ac9dbSNicholas Bellinger struct se_lun *core_tpg_pre_dellun( 812c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 813c66ac9dbSNicholas Bellinger u32 unpacked_lun, 814c66ac9dbSNicholas Bellinger int *ret) 815c66ac9dbSNicholas Bellinger { 816c66ac9dbSNicholas Bellinger struct se_lun *lun; 817c66ac9dbSNicholas Bellinger 818c66ac9dbSNicholas Bellinger if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) { 8196708bb27SAndy Grover pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG" 820c66ac9dbSNicholas Bellinger "-1: %u for Target Portal Group: %u\n", 821e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun, 822c66ac9dbSNicholas Bellinger TRANSPORT_MAX_LUNS_PER_TPG-1, 823e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 824c66ac9dbSNicholas Bellinger return ERR_PTR(-EOVERFLOW); 825c66ac9dbSNicholas Bellinger } 826c66ac9dbSNicholas Bellinger 827c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 828c66ac9dbSNicholas Bellinger lun = &tpg->tpg_lun_list[unpacked_lun]; 829c66ac9dbSNicholas Bellinger if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) { 8306708bb27SAndy Grover pr_err("%s Logical Unit Number: %u is not active on" 831c66ac9dbSNicholas Bellinger " Target Portal Group: %u, ignoring request.\n", 832e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), unpacked_lun, 833e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 834c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 835c66ac9dbSNicholas Bellinger return ERR_PTR(-ENODEV); 836c66ac9dbSNicholas Bellinger } 837c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 838c66ac9dbSNicholas Bellinger 839c66ac9dbSNicholas Bellinger return lun; 840c66ac9dbSNicholas Bellinger } 841c66ac9dbSNicholas Bellinger 842c66ac9dbSNicholas Bellinger int core_tpg_post_dellun( 843c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 844c66ac9dbSNicholas Bellinger struct se_lun *lun) 845c66ac9dbSNicholas Bellinger { 846c66ac9dbSNicholas Bellinger core_tpg_shutdown_lun(tpg, lun); 847c66ac9dbSNicholas Bellinger 848c66ac9dbSNicholas Bellinger core_dev_unexport(lun->lun_se_dev, tpg, lun); 849c66ac9dbSNicholas Bellinger 850c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 851c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 852c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 853c66ac9dbSNicholas Bellinger 854c66ac9dbSNicholas Bellinger return 0; 855c66ac9dbSNicholas Bellinger } 856