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