1c66ac9dbSNicholas Bellinger /******************************************************************************* 2c66ac9dbSNicholas Bellinger * Filename: target_core_tpg.c 3c66ac9dbSNicholas Bellinger * 4c66ac9dbSNicholas Bellinger * This file contains generic Target Portal Group related functions. 5c66ac9dbSNicholas Bellinger * 64c76251eSNicholas Bellinger * (c) Copyright 2002-2013 Datera, Inc. 7c66ac9dbSNicholas Bellinger * 8c66ac9dbSNicholas Bellinger * Nicholas A. Bellinger <nab@kernel.org> 9c66ac9dbSNicholas Bellinger * 10c66ac9dbSNicholas Bellinger * This program is free software; you can redistribute it and/or modify 11c66ac9dbSNicholas Bellinger * it under the terms of the GNU General Public License as published by 12c66ac9dbSNicholas Bellinger * the Free Software Foundation; either version 2 of the License, or 13c66ac9dbSNicholas Bellinger * (at your option) any later version. 14c66ac9dbSNicholas Bellinger * 15c66ac9dbSNicholas Bellinger * This program is distributed in the hope that it will be useful, 16c66ac9dbSNicholas Bellinger * but WITHOUT ANY WARRANTY; without even the implied warranty of 17c66ac9dbSNicholas Bellinger * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18c66ac9dbSNicholas Bellinger * GNU General Public License for more details. 19c66ac9dbSNicholas Bellinger * 20c66ac9dbSNicholas Bellinger * You should have received a copy of the GNU General Public License 21c66ac9dbSNicholas Bellinger * along with this program; if not, write to the Free Software 22c66ac9dbSNicholas Bellinger * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23c66ac9dbSNicholas Bellinger * 24c66ac9dbSNicholas Bellinger ******************************************************************************/ 25c66ac9dbSNicholas Bellinger 26c66ac9dbSNicholas Bellinger #include <linux/net.h> 27c66ac9dbSNicholas Bellinger #include <linux/string.h> 28c66ac9dbSNicholas Bellinger #include <linux/timer.h> 29c66ac9dbSNicholas Bellinger #include <linux/slab.h> 30c66ac9dbSNicholas Bellinger #include <linux/spinlock.h> 31c66ac9dbSNicholas Bellinger #include <linux/in.h> 32c53181afSPaul Gortmaker #include <linux/export.h> 33c66ac9dbSNicholas Bellinger #include <net/sock.h> 34c66ac9dbSNicholas Bellinger #include <net/tcp.h> 35c66ac9dbSNicholas Bellinger #include <scsi/scsi.h> 36c66ac9dbSNicholas Bellinger #include <scsi/scsi_cmnd.h> 37c66ac9dbSNicholas Bellinger 38c66ac9dbSNicholas Bellinger #include <target/target_core_base.h> 39c4795fb2SChristoph Hellwig #include <target/target_core_backend.h> 40c4795fb2SChristoph Hellwig #include <target/target_core_fabric.h> 41c66ac9dbSNicholas Bellinger 42e26d99aeSChristoph Hellwig #include "target_core_internal.h" 43e3d6f909SAndy Grover 44e3d6f909SAndy Grover extern struct se_device *g_lun0_dev; 45e3d6f909SAndy Grover 46e3d6f909SAndy Grover static DEFINE_SPINLOCK(tpg_lock); 47e3d6f909SAndy Grover static LIST_HEAD(tpg_list); 48c66ac9dbSNicholas Bellinger 49c66ac9dbSNicholas Bellinger /* core_clear_initiator_node_from_tpg(): 50c66ac9dbSNicholas Bellinger * 51c66ac9dbSNicholas Bellinger * 52c66ac9dbSNicholas Bellinger */ 53c66ac9dbSNicholas Bellinger static void core_clear_initiator_node_from_tpg( 54c66ac9dbSNicholas Bellinger struct se_node_acl *nacl, 55c66ac9dbSNicholas Bellinger struct se_portal_group *tpg) 56c66ac9dbSNicholas Bellinger { 57c66ac9dbSNicholas Bellinger int i; 58c66ac9dbSNicholas Bellinger struct se_dev_entry *deve; 59c66ac9dbSNicholas Bellinger struct se_lun *lun; 60c66ac9dbSNicholas Bellinger 61c66ac9dbSNicholas Bellinger spin_lock_irq(&nacl->device_list_lock); 62c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 63f2083241SJörn Engel deve = nacl->device_list[i]; 64c66ac9dbSNicholas Bellinger 65c66ac9dbSNicholas Bellinger if (!(deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS)) 66c66ac9dbSNicholas Bellinger continue; 67c66ac9dbSNicholas Bellinger 68c66ac9dbSNicholas Bellinger if (!deve->se_lun) { 696708bb27SAndy Grover pr_err("%s device entries device pointer is" 70c66ac9dbSNicholas Bellinger " NULL, but Initiator has access.\n", 71e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name()); 72c66ac9dbSNicholas Bellinger continue; 73c66ac9dbSNicholas Bellinger } 74c66ac9dbSNicholas Bellinger 75c66ac9dbSNicholas Bellinger lun = deve->se_lun; 76c66ac9dbSNicholas Bellinger spin_unlock_irq(&nacl->device_list_lock); 77e80ac6c4SAndy Grover core_disable_device_list_for_node(lun, NULL, deve->mapped_lun, 78e80ac6c4SAndy Grover TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg); 79c66ac9dbSNicholas Bellinger 80c66ac9dbSNicholas Bellinger spin_lock_irq(&nacl->device_list_lock); 81c66ac9dbSNicholas Bellinger } 82c66ac9dbSNicholas Bellinger spin_unlock_irq(&nacl->device_list_lock); 83c66ac9dbSNicholas Bellinger } 84c66ac9dbSNicholas Bellinger 85c66ac9dbSNicholas Bellinger /* __core_tpg_get_initiator_node_acl(): 86c66ac9dbSNicholas Bellinger * 87c66ac9dbSNicholas Bellinger * spin_lock_bh(&tpg->acl_node_lock); must be held when calling 88c66ac9dbSNicholas Bellinger */ 89c66ac9dbSNicholas Bellinger struct se_node_acl *__core_tpg_get_initiator_node_acl( 90c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 91c66ac9dbSNicholas Bellinger const char *initiatorname) 92c66ac9dbSNicholas Bellinger { 93c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 94c66ac9dbSNicholas Bellinger 95c66ac9dbSNicholas Bellinger list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { 966708bb27SAndy Grover if (!strcmp(acl->initiatorname, initiatorname)) 97c66ac9dbSNicholas Bellinger return acl; 98c66ac9dbSNicholas Bellinger } 99c66ac9dbSNicholas Bellinger 100c66ac9dbSNicholas Bellinger return NULL; 101c66ac9dbSNicholas Bellinger } 102c66ac9dbSNicholas Bellinger 103c66ac9dbSNicholas Bellinger /* core_tpg_get_initiator_node_acl(): 104c66ac9dbSNicholas Bellinger * 105c66ac9dbSNicholas Bellinger * 106c66ac9dbSNicholas Bellinger */ 107c66ac9dbSNicholas Bellinger struct se_node_acl *core_tpg_get_initiator_node_acl( 108c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 109c66ac9dbSNicholas Bellinger unsigned char *initiatorname) 110c66ac9dbSNicholas Bellinger { 111c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 112c66ac9dbSNicholas Bellinger 11328638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 114fcf29481SNicholas Bellinger acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); 11528638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 116c66ac9dbSNicholas Bellinger 117fcf29481SNicholas Bellinger return acl; 118c66ac9dbSNicholas Bellinger } 119b3fde035SThomas Glanzmann EXPORT_SYMBOL(core_tpg_get_initiator_node_acl); 120c66ac9dbSNicholas Bellinger 121c66ac9dbSNicholas Bellinger /* core_tpg_add_node_to_devs(): 122c66ac9dbSNicholas Bellinger * 123c66ac9dbSNicholas Bellinger * 124c66ac9dbSNicholas Bellinger */ 125c66ac9dbSNicholas Bellinger void core_tpg_add_node_to_devs( 126c66ac9dbSNicholas Bellinger struct se_node_acl *acl, 127c66ac9dbSNicholas Bellinger struct se_portal_group *tpg) 128c66ac9dbSNicholas Bellinger { 129c66ac9dbSNicholas Bellinger int i = 0; 130c66ac9dbSNicholas Bellinger u32 lun_access = 0; 131c66ac9dbSNicholas Bellinger struct se_lun *lun; 132c66ac9dbSNicholas Bellinger struct se_device *dev; 133c66ac9dbSNicholas Bellinger 134c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 135c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 1364a5a75f3SJörn Engel lun = tpg->tpg_lun_list[i]; 137c66ac9dbSNicholas Bellinger if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) 138c66ac9dbSNicholas Bellinger continue; 139c66ac9dbSNicholas Bellinger 140c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 141c66ac9dbSNicholas Bellinger 142c66ac9dbSNicholas Bellinger dev = lun->lun_se_dev; 143c66ac9dbSNicholas Bellinger /* 144c66ac9dbSNicholas Bellinger * By default in LIO-Target $FABRIC_MOD, 145c66ac9dbSNicholas Bellinger * demo_mode_write_protect is ON, or READ_ONLY; 146c66ac9dbSNicholas Bellinger */ 1476708bb27SAndy Grover if (!tpg->se_tpg_tfo->tpg_check_demo_mode_write_protect(tpg)) { 148c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; 149c66ac9dbSNicholas Bellinger } else { 150c66ac9dbSNicholas Bellinger /* 151c66ac9dbSNicholas Bellinger * Allow only optical drives to issue R/W in default RO 152c66ac9dbSNicholas Bellinger * demo mode. 153c66ac9dbSNicholas Bellinger */ 154e3d6f909SAndy Grover if (dev->transport->get_device_type(dev) == TYPE_DISK) 155c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_ONLY; 156c66ac9dbSNicholas Bellinger else 157c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; 158c66ac9dbSNicholas Bellinger } 159c66ac9dbSNicholas Bellinger 1606708bb27SAndy Grover pr_debug("TARGET_CORE[%s]->TPG[%u]_LUN[%u] - Adding %s" 161c66ac9dbSNicholas Bellinger " access for LUN in Demo Mode\n", 162e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), 163e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, 164c66ac9dbSNicholas Bellinger (lun_access == TRANSPORT_LUNFLAGS_READ_WRITE) ? 165c66ac9dbSNicholas Bellinger "READ-WRITE" : "READ-ONLY"); 166c66ac9dbSNicholas Bellinger 167e80ac6c4SAndy Grover core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun, 168e80ac6c4SAndy Grover lun_access, acl, tpg); 169c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 170c66ac9dbSNicholas Bellinger } 171c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 172c66ac9dbSNicholas Bellinger } 173c66ac9dbSNicholas Bellinger 174c66ac9dbSNicholas Bellinger /* core_set_queue_depth_for_node(): 175c66ac9dbSNicholas Bellinger * 176c66ac9dbSNicholas Bellinger * 177c66ac9dbSNicholas Bellinger */ 178c66ac9dbSNicholas Bellinger static int core_set_queue_depth_for_node( 179c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 180c66ac9dbSNicholas Bellinger struct se_node_acl *acl) 181c66ac9dbSNicholas Bellinger { 182c66ac9dbSNicholas Bellinger if (!acl->queue_depth) { 1836708bb27SAndy Grover pr_err("Queue depth for %s Initiator Node: %s is 0," 184e3d6f909SAndy Grover "defaulting to 1.\n", tpg->se_tpg_tfo->get_fabric_name(), 185c66ac9dbSNicholas Bellinger acl->initiatorname); 186c66ac9dbSNicholas Bellinger acl->queue_depth = 1; 187c66ac9dbSNicholas Bellinger } 188c66ac9dbSNicholas Bellinger 189c66ac9dbSNicholas Bellinger return 0; 190c66ac9dbSNicholas Bellinger } 191c66ac9dbSNicholas Bellinger 1924a5a75f3SJörn Engel void array_free(void *array, int n) 1934a5a75f3SJörn Engel { 1944a5a75f3SJörn Engel void **a = array; 1954a5a75f3SJörn Engel int i; 1964a5a75f3SJörn Engel 1974a5a75f3SJörn Engel for (i = 0; i < n; i++) 1984a5a75f3SJörn Engel kfree(a[i]); 1994a5a75f3SJörn Engel kfree(a); 2004a5a75f3SJörn Engel } 2014a5a75f3SJörn Engel 2024a5a75f3SJörn Engel static void *array_zalloc(int n, size_t size, gfp_t flags) 2034a5a75f3SJörn Engel { 2044a5a75f3SJörn Engel void **a; 2054a5a75f3SJörn Engel int i; 2064a5a75f3SJörn Engel 2074a5a75f3SJörn Engel a = kzalloc(n * sizeof(void*), flags); 2084a5a75f3SJörn Engel if (!a) 2094a5a75f3SJörn Engel return NULL; 2104a5a75f3SJörn Engel for (i = 0; i < n; i++) { 2114a5a75f3SJörn Engel a[i] = kzalloc(size, flags); 2124a5a75f3SJörn Engel if (!a[i]) { 2134a5a75f3SJörn Engel array_free(a, n); 2144a5a75f3SJörn Engel return NULL; 2154a5a75f3SJörn Engel } 2164a5a75f3SJörn Engel } 2174a5a75f3SJörn Engel return a; 2184a5a75f3SJörn Engel } 2194a5a75f3SJörn Engel 220c66ac9dbSNicholas Bellinger /* core_create_device_list_for_node(): 221c66ac9dbSNicholas Bellinger * 222c66ac9dbSNicholas Bellinger * 223c66ac9dbSNicholas Bellinger */ 224c66ac9dbSNicholas Bellinger static int core_create_device_list_for_node(struct se_node_acl *nacl) 225c66ac9dbSNicholas Bellinger { 226c66ac9dbSNicholas Bellinger struct se_dev_entry *deve; 227c66ac9dbSNicholas Bellinger int i; 228c66ac9dbSNicholas Bellinger 229f2083241SJörn Engel nacl->device_list = array_zalloc(TRANSPORT_MAX_LUNS_PER_TPG, 230f2083241SJörn Engel sizeof(struct se_dev_entry), GFP_KERNEL); 2316708bb27SAndy Grover if (!nacl->device_list) { 2326708bb27SAndy Grover pr_err("Unable to allocate memory for" 233c66ac9dbSNicholas Bellinger " struct se_node_acl->device_list\n"); 234e3d6f909SAndy Grover return -ENOMEM; 235c66ac9dbSNicholas Bellinger } 236c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 237f2083241SJörn Engel deve = nacl->device_list[i]; 238c66ac9dbSNicholas Bellinger 239c66ac9dbSNicholas Bellinger atomic_set(&deve->ua_count, 0); 240c66ac9dbSNicholas Bellinger atomic_set(&deve->pr_ref_count, 0); 241c66ac9dbSNicholas Bellinger spin_lock_init(&deve->ua_lock); 242c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&deve->alua_port_list); 243c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&deve->ua_list); 244c66ac9dbSNicholas Bellinger } 245c66ac9dbSNicholas Bellinger 246c66ac9dbSNicholas Bellinger return 0; 247c66ac9dbSNicholas Bellinger } 248c66ac9dbSNicholas Bellinger 249c66ac9dbSNicholas Bellinger /* core_tpg_check_initiator_node_acl() 250c66ac9dbSNicholas Bellinger * 251c66ac9dbSNicholas Bellinger * 252c66ac9dbSNicholas Bellinger */ 253c66ac9dbSNicholas Bellinger struct se_node_acl *core_tpg_check_initiator_node_acl( 254c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 255c66ac9dbSNicholas Bellinger unsigned char *initiatorname) 256c66ac9dbSNicholas Bellinger { 257c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 258c66ac9dbSNicholas Bellinger 259c66ac9dbSNicholas Bellinger acl = core_tpg_get_initiator_node_acl(tpg, initiatorname); 2606708bb27SAndy Grover if (acl) 261c66ac9dbSNicholas Bellinger return acl; 262c66ac9dbSNicholas Bellinger 2636708bb27SAndy Grover if (!tpg->se_tpg_tfo->tpg_check_demo_mode(tpg)) 264c66ac9dbSNicholas Bellinger return NULL; 265c66ac9dbSNicholas Bellinger 266e3d6f909SAndy Grover acl = tpg->se_tpg_tfo->tpg_alloc_fabric_acl(tpg); 2676708bb27SAndy Grover if (!acl) 268c66ac9dbSNicholas Bellinger return NULL; 269c66ac9dbSNicholas Bellinger 270c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_list); 271c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_sess_list); 272afb999ffSNicholas Bellinger kref_init(&acl->acl_kref); 27301468346SNicholas Bellinger init_completion(&acl->acl_free_comp); 274c66ac9dbSNicholas Bellinger spin_lock_init(&acl->device_list_lock); 275c66ac9dbSNicholas Bellinger spin_lock_init(&acl->nacl_sess_lock); 276c66ac9dbSNicholas Bellinger atomic_set(&acl->acl_pr_ref_count, 0); 277e3d6f909SAndy Grover acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg); 278c66ac9dbSNicholas Bellinger snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); 279c66ac9dbSNicholas Bellinger acl->se_tpg = tpg; 280c66ac9dbSNicholas Bellinger acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX); 281c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 282c66ac9dbSNicholas Bellinger 283e3d6f909SAndy Grover tpg->se_tpg_tfo->set_default_node_attributes(acl); 284c66ac9dbSNicholas Bellinger 285c66ac9dbSNicholas Bellinger if (core_create_device_list_for_node(acl) < 0) { 286e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); 287c66ac9dbSNicholas Bellinger return NULL; 288c66ac9dbSNicholas Bellinger } 289c66ac9dbSNicholas Bellinger 290c66ac9dbSNicholas Bellinger if (core_set_queue_depth_for_node(tpg, acl) < 0) { 291c66ac9dbSNicholas Bellinger core_free_device_list_for_node(acl, tpg); 292e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); 293c66ac9dbSNicholas Bellinger return NULL; 294c66ac9dbSNicholas Bellinger } 295052605c6SNicholas Bellinger /* 296052605c6SNicholas Bellinger * Here we only create demo-mode MappedLUNs from the active 29735d1efe8SMasanari Iida * TPG LUNs if the fabric is not explicitly asking for 298052605c6SNicholas Bellinger * tpg_check_demo_mode_login_only() == 1. 299052605c6SNicholas Bellinger */ 300cdf88a2fSAndy Grover if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only == NULL) || 301cdf88a2fSAndy Grover (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) != 1)) 302c66ac9dbSNicholas Bellinger core_tpg_add_node_to_devs(acl, tpg); 303c66ac9dbSNicholas Bellinger 30428638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 305c66ac9dbSNicholas Bellinger list_add_tail(&acl->acl_list, &tpg->acl_node_list); 306c66ac9dbSNicholas Bellinger tpg->num_node_acls++; 30728638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 308c66ac9dbSNicholas Bellinger 3096708bb27SAndy Grover pr_debug("%s_TPG[%u] - Added DYNAMIC ACL with TCQ Depth: %d for %s" 310e3d6f909SAndy Grover " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(), 311e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth, 312e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), initiatorname); 313c66ac9dbSNicholas Bellinger 314c66ac9dbSNicholas Bellinger return acl; 315c66ac9dbSNicholas Bellinger } 316c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_check_initiator_node_acl); 317c66ac9dbSNicholas Bellinger 318c66ac9dbSNicholas Bellinger void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *nacl) 319c66ac9dbSNicholas Bellinger { 320c66ac9dbSNicholas Bellinger while (atomic_read(&nacl->acl_pr_ref_count) != 0) 321c66ac9dbSNicholas Bellinger cpu_relax(); 322c66ac9dbSNicholas Bellinger } 323c66ac9dbSNicholas Bellinger 324c66ac9dbSNicholas Bellinger void core_tpg_clear_object_luns(struct se_portal_group *tpg) 325c66ac9dbSNicholas Bellinger { 32628168905SJörn Engel int i; 327c66ac9dbSNicholas Bellinger struct se_lun *lun; 328c66ac9dbSNicholas Bellinger 329c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 330c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 3314a5a75f3SJörn Engel lun = tpg->tpg_lun_list[i]; 332c66ac9dbSNicholas Bellinger 333c66ac9dbSNicholas Bellinger if ((lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) || 334c66ac9dbSNicholas Bellinger (lun->lun_se_dev == NULL)) 335c66ac9dbSNicholas Bellinger continue; 336c66ac9dbSNicholas Bellinger 337c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 338cd9d7cbaSAndy Grover core_dev_del_lun(tpg, lun); 339c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 340c66ac9dbSNicholas Bellinger } 341c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 342c66ac9dbSNicholas Bellinger } 343c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_clear_object_luns); 344c66ac9dbSNicholas Bellinger 345c66ac9dbSNicholas Bellinger /* core_tpg_add_initiator_node_acl(): 346c66ac9dbSNicholas Bellinger * 347c66ac9dbSNicholas Bellinger * 348c66ac9dbSNicholas Bellinger */ 349c66ac9dbSNicholas Bellinger struct se_node_acl *core_tpg_add_initiator_node_acl( 350c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 351c66ac9dbSNicholas Bellinger struct se_node_acl *se_nacl, 352c66ac9dbSNicholas Bellinger const char *initiatorname, 353c66ac9dbSNicholas Bellinger u32 queue_depth) 354c66ac9dbSNicholas Bellinger { 355c66ac9dbSNicholas Bellinger struct se_node_acl *acl = NULL; 356c66ac9dbSNicholas Bellinger 35728638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 358c66ac9dbSNicholas Bellinger acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); 3596708bb27SAndy Grover if (acl) { 360c66ac9dbSNicholas Bellinger if (acl->dynamic_node_acl) { 361c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 0; 3626708bb27SAndy Grover pr_debug("%s_TPG[%u] - Replacing dynamic ACL" 363e3d6f909SAndy Grover " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), 364e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname); 36528638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 366c66ac9dbSNicholas Bellinger /* 367c66ac9dbSNicholas Bellinger * Release the locally allocated struct se_node_acl 368c66ac9dbSNicholas Bellinger * because * core_tpg_add_initiator_node_acl() returned 369c66ac9dbSNicholas Bellinger * a pointer to an existing demo mode node ACL. 370c66ac9dbSNicholas Bellinger */ 371c66ac9dbSNicholas Bellinger if (se_nacl) 372e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, 373c66ac9dbSNicholas Bellinger se_nacl); 374c66ac9dbSNicholas Bellinger goto done; 375c66ac9dbSNicholas Bellinger } 376c66ac9dbSNicholas Bellinger 3776708bb27SAndy Grover pr_err("ACL entry for %s Initiator" 378c66ac9dbSNicholas Bellinger " Node %s already exists for TPG %u, ignoring" 379e3d6f909SAndy Grover " request.\n", tpg->se_tpg_tfo->get_fabric_name(), 380e3d6f909SAndy Grover initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); 38128638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 382c66ac9dbSNicholas Bellinger return ERR_PTR(-EEXIST); 383c66ac9dbSNicholas Bellinger } 38428638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 385c66ac9dbSNicholas Bellinger 3866708bb27SAndy Grover if (!se_nacl) { 3876708bb27SAndy Grover pr_err("struct se_node_acl pointer is NULL\n"); 388c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 389c66ac9dbSNicholas Bellinger } 390c66ac9dbSNicholas Bellinger /* 391c66ac9dbSNicholas Bellinger * For v4.x logic the se_node_acl_s is hanging off a fabric 392c66ac9dbSNicholas Bellinger * dependent structure allocated via 393c66ac9dbSNicholas Bellinger * struct target_core_fabric_ops->fabric_make_nodeacl() 394c66ac9dbSNicholas Bellinger */ 395c66ac9dbSNicholas Bellinger acl = se_nacl; 396c66ac9dbSNicholas Bellinger 397c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_list); 398c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_sess_list); 399afb999ffSNicholas Bellinger kref_init(&acl->acl_kref); 40001468346SNicholas Bellinger init_completion(&acl->acl_free_comp); 401c66ac9dbSNicholas Bellinger spin_lock_init(&acl->device_list_lock); 402c66ac9dbSNicholas Bellinger spin_lock_init(&acl->nacl_sess_lock); 403c66ac9dbSNicholas Bellinger atomic_set(&acl->acl_pr_ref_count, 0); 404c66ac9dbSNicholas Bellinger acl->queue_depth = queue_depth; 405c66ac9dbSNicholas Bellinger snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); 406c66ac9dbSNicholas Bellinger acl->se_tpg = tpg; 407c66ac9dbSNicholas Bellinger acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX); 408c66ac9dbSNicholas Bellinger 409e3d6f909SAndy Grover tpg->se_tpg_tfo->set_default_node_attributes(acl); 410c66ac9dbSNicholas Bellinger 411c66ac9dbSNicholas Bellinger if (core_create_device_list_for_node(acl) < 0) { 412e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); 413c66ac9dbSNicholas Bellinger return ERR_PTR(-ENOMEM); 414c66ac9dbSNicholas Bellinger } 415c66ac9dbSNicholas Bellinger 416c66ac9dbSNicholas Bellinger if (core_set_queue_depth_for_node(tpg, acl) < 0) { 417c66ac9dbSNicholas Bellinger core_free_device_list_for_node(acl, tpg); 418e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_release_fabric_acl(tpg, acl); 419c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 420c66ac9dbSNicholas Bellinger } 421c66ac9dbSNicholas Bellinger 42228638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 423c66ac9dbSNicholas Bellinger list_add_tail(&acl->acl_list, &tpg->acl_node_list); 424c66ac9dbSNicholas Bellinger tpg->num_node_acls++; 42528638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 426c66ac9dbSNicholas Bellinger 427c66ac9dbSNicholas Bellinger done: 4286708bb27SAndy Grover pr_debug("%s_TPG[%hu] - Added ACL with TCQ Depth: %d for %s" 429e3d6f909SAndy Grover " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(), 430e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth, 431e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), initiatorname); 432c66ac9dbSNicholas Bellinger 433c66ac9dbSNicholas Bellinger return acl; 434c66ac9dbSNicholas Bellinger } 435c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_add_initiator_node_acl); 436c66ac9dbSNicholas Bellinger 437c66ac9dbSNicholas Bellinger /* core_tpg_del_initiator_node_acl(): 438c66ac9dbSNicholas Bellinger * 439c66ac9dbSNicholas Bellinger * 440c66ac9dbSNicholas Bellinger */ 441c66ac9dbSNicholas Bellinger int core_tpg_del_initiator_node_acl( 442c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 443c66ac9dbSNicholas Bellinger struct se_node_acl *acl, 444c66ac9dbSNicholas Bellinger int force) 445c66ac9dbSNicholas Bellinger { 446337c0607SNicholas Bellinger LIST_HEAD(sess_list); 447c66ac9dbSNicholas Bellinger struct se_session *sess, *sess_tmp; 448140854cbSNicholas Bellinger unsigned long flags; 44928168905SJörn Engel int rc; 450c66ac9dbSNicholas Bellinger 45128638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 452c66ac9dbSNicholas Bellinger if (acl->dynamic_node_acl) { 453c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 0; 454c66ac9dbSNicholas Bellinger } 455c66ac9dbSNicholas Bellinger list_del(&acl->acl_list); 456c66ac9dbSNicholas Bellinger tpg->num_node_acls--; 45728638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 458c66ac9dbSNicholas Bellinger 459337c0607SNicholas Bellinger spin_lock_irqsave(&acl->nacl_sess_lock, flags); 460337c0607SNicholas Bellinger acl->acl_stop = 1; 461337c0607SNicholas Bellinger 462337c0607SNicholas Bellinger list_for_each_entry_safe(sess, sess_tmp, &acl->acl_sess_list, 463337c0607SNicholas Bellinger sess_acl_list) { 464337c0607SNicholas Bellinger if (sess->sess_tearing_down != 0) 465c66ac9dbSNicholas Bellinger continue; 466c66ac9dbSNicholas Bellinger 467337c0607SNicholas Bellinger target_get_session(sess); 468337c0607SNicholas Bellinger list_move(&sess->sess_acl_list, &sess_list); 469c66ac9dbSNicholas Bellinger } 470337c0607SNicholas Bellinger spin_unlock_irqrestore(&acl->nacl_sess_lock, flags); 471337c0607SNicholas Bellinger 472337c0607SNicholas Bellinger list_for_each_entry_safe(sess, sess_tmp, &sess_list, sess_acl_list) { 473337c0607SNicholas Bellinger list_del(&sess->sess_acl_list); 474337c0607SNicholas Bellinger 475337c0607SNicholas Bellinger rc = tpg->se_tpg_tfo->shutdown_session(sess); 476337c0607SNicholas Bellinger target_put_session(sess); 477337c0607SNicholas Bellinger if (!rc) 478337c0607SNicholas Bellinger continue; 479337c0607SNicholas Bellinger target_put_session(sess); 480337c0607SNicholas Bellinger } 481337c0607SNicholas Bellinger target_put_nacl(acl); 482337c0607SNicholas Bellinger /* 483337c0607SNicholas Bellinger * Wait for last target_put_nacl() to complete in target_complete_nacl() 484337c0607SNicholas Bellinger * for active fabric session transport_deregister_session() callbacks. 485337c0607SNicholas Bellinger */ 486337c0607SNicholas Bellinger wait_for_completion(&acl->acl_free_comp); 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; 513140854cbSNicholas Bellinger unsigned long flags; 514c66ac9dbSNicholas Bellinger int dynamic_acl = 0; 515c66ac9dbSNicholas Bellinger 51628638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 517c66ac9dbSNicholas Bellinger acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); 5186708bb27SAndy Grover if (!acl) { 5196708bb27SAndy Grover pr_err("Access Control List entry for %s Initiator" 520c66ac9dbSNicholas Bellinger " Node %s does not exists for TPG %hu, ignoring" 521e3d6f909SAndy Grover " request.\n", tpg->se_tpg_tfo->get_fabric_name(), 522e3d6f909SAndy Grover initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); 52328638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 524c66ac9dbSNicholas Bellinger return -ENODEV; 525c66ac9dbSNicholas Bellinger } 526c66ac9dbSNicholas Bellinger if (acl->dynamic_node_acl) { 527c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 0; 528c66ac9dbSNicholas Bellinger dynamic_acl = 1; 529c66ac9dbSNicholas Bellinger } 53028638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 531c66ac9dbSNicholas Bellinger 532140854cbSNicholas Bellinger spin_lock_irqsave(&tpg->session_lock, flags); 533c66ac9dbSNicholas Bellinger list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) { 534c66ac9dbSNicholas Bellinger if (sess->se_node_acl != acl) 535c66ac9dbSNicholas Bellinger continue; 536c66ac9dbSNicholas Bellinger 537c66ac9dbSNicholas Bellinger if (!force) { 5386708bb27SAndy Grover pr_err("Unable to change queue depth for %s" 539c66ac9dbSNicholas Bellinger " Initiator Node: %s while session is" 540c66ac9dbSNicholas Bellinger " operational. To forcefully change the queue" 541c66ac9dbSNicholas Bellinger " depth and force session reinstatement" 542c66ac9dbSNicholas Bellinger " use the \"force=1\" parameter.\n", 543e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), initiatorname); 544140854cbSNicholas Bellinger spin_unlock_irqrestore(&tpg->session_lock, flags); 545c66ac9dbSNicholas Bellinger 54628638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 547c66ac9dbSNicholas Bellinger if (dynamic_acl) 548c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 54928638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 550c66ac9dbSNicholas Bellinger return -EEXIST; 551c66ac9dbSNicholas Bellinger } 552c66ac9dbSNicholas Bellinger /* 553c66ac9dbSNicholas Bellinger * Determine if the session needs to be closed by our context. 554c66ac9dbSNicholas Bellinger */ 5556708bb27SAndy Grover if (!tpg->se_tpg_tfo->shutdown_session(sess)) 556c66ac9dbSNicholas Bellinger continue; 557c66ac9dbSNicholas Bellinger 558c66ac9dbSNicholas Bellinger init_sess = sess; 559c66ac9dbSNicholas Bellinger break; 560c66ac9dbSNicholas Bellinger } 561c66ac9dbSNicholas Bellinger 562c66ac9dbSNicholas Bellinger /* 563c66ac9dbSNicholas Bellinger * User has requested to change the queue depth for a Initiator Node. 564c66ac9dbSNicholas Bellinger * Change the value in the Node's struct se_node_acl, and call 565c66ac9dbSNicholas Bellinger * core_set_queue_depth_for_node() to add the requested queue depth. 566c66ac9dbSNicholas Bellinger * 567e3d6f909SAndy Grover * Finally call tpg->se_tpg_tfo->close_session() to force session 568c66ac9dbSNicholas Bellinger * reinstatement to occur if there is an active session for the 569c66ac9dbSNicholas Bellinger * $FABRIC_MOD Initiator Node in question. 570c66ac9dbSNicholas Bellinger */ 571c66ac9dbSNicholas Bellinger acl->queue_depth = queue_depth; 572c66ac9dbSNicholas Bellinger 573c66ac9dbSNicholas Bellinger if (core_set_queue_depth_for_node(tpg, acl) < 0) { 574140854cbSNicholas Bellinger spin_unlock_irqrestore(&tpg->session_lock, flags); 575c66ac9dbSNicholas Bellinger /* 576c66ac9dbSNicholas Bellinger * Force session reinstatement if 577c66ac9dbSNicholas Bellinger * core_set_queue_depth_for_node() failed, because we assume 578c66ac9dbSNicholas Bellinger * the $FABRIC_MOD has already the set session reinstatement 579e3d6f909SAndy Grover * bit from tpg->se_tpg_tfo->shutdown_session() called above. 580c66ac9dbSNicholas Bellinger */ 581c66ac9dbSNicholas Bellinger if (init_sess) 582e3d6f909SAndy Grover tpg->se_tpg_tfo->close_session(init_sess); 583c66ac9dbSNicholas Bellinger 58428638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 585c66ac9dbSNicholas Bellinger if (dynamic_acl) 586c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 58728638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 588c66ac9dbSNicholas Bellinger return -EINVAL; 589c66ac9dbSNicholas Bellinger } 590140854cbSNicholas Bellinger spin_unlock_irqrestore(&tpg->session_lock, flags); 591c66ac9dbSNicholas Bellinger /* 592c66ac9dbSNicholas Bellinger * If the $FABRIC_MOD session for the Initiator Node ACL exists, 593c66ac9dbSNicholas Bellinger * forcefully shutdown the $FABRIC_MOD session/nexus. 594c66ac9dbSNicholas Bellinger */ 595c66ac9dbSNicholas Bellinger if (init_sess) 596e3d6f909SAndy Grover tpg->se_tpg_tfo->close_session(init_sess); 597c66ac9dbSNicholas Bellinger 598bfb9035cSJoe Perches pr_debug("Successfully changed queue depth to: %d for Initiator" 599c66ac9dbSNicholas Bellinger " Node: %s on %s Target Portal Group: %u\n", queue_depth, 600e3d6f909SAndy Grover initiatorname, tpg->se_tpg_tfo->get_fabric_name(), 601e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 602c66ac9dbSNicholas Bellinger 60328638887SRoland Dreier spin_lock_irq(&tpg->acl_node_lock); 604c66ac9dbSNicholas Bellinger if (dynamic_acl) 605c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 60628638887SRoland Dreier spin_unlock_irq(&tpg->acl_node_lock); 607c66ac9dbSNicholas Bellinger 608c66ac9dbSNicholas Bellinger return 0; 609c66ac9dbSNicholas Bellinger } 610c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth); 611c66ac9dbSNicholas Bellinger 61279e62fc3SAndy Grover /* core_tpg_set_initiator_node_tag(): 61379e62fc3SAndy Grover * 61479e62fc3SAndy Grover * Initiator nodeacl tags are not used internally, but may be used by 61579e62fc3SAndy Grover * userspace to emulate aliases or groups. 61679e62fc3SAndy Grover * Returns length of newly-set tag or -EINVAL. 61779e62fc3SAndy Grover */ 61879e62fc3SAndy Grover int core_tpg_set_initiator_node_tag( 61979e62fc3SAndy Grover struct se_portal_group *tpg, 62079e62fc3SAndy Grover struct se_node_acl *acl, 62179e62fc3SAndy Grover const char *new_tag) 62279e62fc3SAndy Grover { 62379e62fc3SAndy Grover if (strlen(new_tag) >= MAX_ACL_TAG_SIZE) 62479e62fc3SAndy Grover return -EINVAL; 62579e62fc3SAndy Grover 62679e62fc3SAndy Grover if (!strncmp("NULL", new_tag, 4)) { 62779e62fc3SAndy Grover acl->acl_tag[0] = '\0'; 62879e62fc3SAndy Grover return 0; 62979e62fc3SAndy Grover } 63079e62fc3SAndy Grover 63179e62fc3SAndy Grover return snprintf(acl->acl_tag, MAX_ACL_TAG_SIZE, "%s", new_tag); 63279e62fc3SAndy Grover } 63379e62fc3SAndy Grover EXPORT_SYMBOL(core_tpg_set_initiator_node_tag); 63479e62fc3SAndy Grover 6355277797dSNicholas Bellinger static void core_tpg_lun_ref_release(struct percpu_ref *ref) 6365277797dSNicholas Bellinger { 6375277797dSNicholas Bellinger struct se_lun *lun = container_of(ref, struct se_lun, lun_ref); 6385277797dSNicholas Bellinger 6395277797dSNicholas Bellinger complete(&lun->lun_ref_comp); 6405277797dSNicholas Bellinger } 6415277797dSNicholas Bellinger 642c66ac9dbSNicholas Bellinger static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) 643c66ac9dbSNicholas Bellinger { 644c66ac9dbSNicholas Bellinger /* Set in core_dev_setup_virtual_lun0() */ 645e3d6f909SAndy Grover struct se_device *dev = g_lun0_dev; 646c66ac9dbSNicholas Bellinger struct se_lun *lun = &se_tpg->tpg_virt_lun0; 647c66ac9dbSNicholas Bellinger u32 lun_access = TRANSPORT_LUNFLAGS_READ_ONLY; 648c66ac9dbSNicholas Bellinger int ret; 649c66ac9dbSNicholas Bellinger 650c66ac9dbSNicholas Bellinger lun->unpacked_lun = 0; 651c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 652c66ac9dbSNicholas Bellinger atomic_set(&lun->lun_acl_count, 0); 653c66ac9dbSNicholas Bellinger init_completion(&lun->lun_shutdown_comp); 654c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lun->lun_acl_list); 655c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_acl_lock); 656c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_sep_lock); 6575277797dSNicholas Bellinger init_completion(&lun->lun_ref_comp); 658c66ac9dbSNicholas Bellinger 6594e13c5d0SLinus Torvalds ret = core_tpg_add_lun(se_tpg, lun, lun_access, dev); 660c66ac9dbSNicholas Bellinger if (ret < 0) 661e3d6f909SAndy Grover return ret; 662c66ac9dbSNicholas Bellinger 663c66ac9dbSNicholas Bellinger return 0; 664c66ac9dbSNicholas Bellinger } 665c66ac9dbSNicholas Bellinger 666c66ac9dbSNicholas Bellinger static void core_tpg_release_virtual_lun0(struct se_portal_group *se_tpg) 667c66ac9dbSNicholas Bellinger { 668c66ac9dbSNicholas Bellinger struct se_lun *lun = &se_tpg->tpg_virt_lun0; 669c66ac9dbSNicholas Bellinger 670cd9d7cbaSAndy Grover core_tpg_remove_lun(se_tpg, lun); 671c66ac9dbSNicholas Bellinger } 672c66ac9dbSNicholas Bellinger 673c66ac9dbSNicholas Bellinger int core_tpg_register( 674c66ac9dbSNicholas Bellinger struct target_core_fabric_ops *tfo, 675c66ac9dbSNicholas Bellinger struct se_wwn *se_wwn, 676c66ac9dbSNicholas Bellinger struct se_portal_group *se_tpg, 677c66ac9dbSNicholas Bellinger void *tpg_fabric_ptr, 678c66ac9dbSNicholas Bellinger int se_tpg_type) 679c66ac9dbSNicholas Bellinger { 680c66ac9dbSNicholas Bellinger struct se_lun *lun; 681c66ac9dbSNicholas Bellinger u32 i; 682c66ac9dbSNicholas Bellinger 6834a5a75f3SJörn Engel se_tpg->tpg_lun_list = array_zalloc(TRANSPORT_MAX_LUNS_PER_TPG, 6844a5a75f3SJörn Engel sizeof(struct se_lun), GFP_KERNEL); 6856708bb27SAndy Grover if (!se_tpg->tpg_lun_list) { 6866708bb27SAndy Grover pr_err("Unable to allocate struct se_portal_group->" 687c66ac9dbSNicholas Bellinger "tpg_lun_list\n"); 688c66ac9dbSNicholas Bellinger return -ENOMEM; 689c66ac9dbSNicholas Bellinger } 690c66ac9dbSNicholas Bellinger 691c66ac9dbSNicholas Bellinger for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { 6924a5a75f3SJörn Engel lun = se_tpg->tpg_lun_list[i]; 693c66ac9dbSNicholas Bellinger lun->unpacked_lun = i; 6940ff87549SNicholas Bellinger lun->lun_link_magic = SE_LUN_LINK_MAGIC; 695c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 696c66ac9dbSNicholas Bellinger atomic_set(&lun->lun_acl_count, 0); 697c66ac9dbSNicholas Bellinger init_completion(&lun->lun_shutdown_comp); 698c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lun->lun_acl_list); 699c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_acl_lock); 700c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_sep_lock); 7015277797dSNicholas Bellinger init_completion(&lun->lun_ref_comp); 702c66ac9dbSNicholas Bellinger } 703c66ac9dbSNicholas Bellinger 704c66ac9dbSNicholas Bellinger se_tpg->se_tpg_type = se_tpg_type; 705c66ac9dbSNicholas Bellinger se_tpg->se_tpg_fabric_ptr = tpg_fabric_ptr; 706c66ac9dbSNicholas Bellinger se_tpg->se_tpg_tfo = tfo; 707c66ac9dbSNicholas Bellinger se_tpg->se_tpg_wwn = se_wwn; 708c66ac9dbSNicholas Bellinger atomic_set(&se_tpg->tpg_pr_ref_count, 0); 709c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&se_tpg->acl_node_list); 710e3d6f909SAndy Grover INIT_LIST_HEAD(&se_tpg->se_tpg_node); 711c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&se_tpg->tpg_sess_list); 712c66ac9dbSNicholas Bellinger spin_lock_init(&se_tpg->acl_node_lock); 713c66ac9dbSNicholas Bellinger spin_lock_init(&se_tpg->session_lock); 714c66ac9dbSNicholas Bellinger spin_lock_init(&se_tpg->tpg_lun_lock); 715c66ac9dbSNicholas Bellinger 716c66ac9dbSNicholas Bellinger if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) { 717c66ac9dbSNicholas Bellinger if (core_tpg_setup_virtual_lun0(se_tpg) < 0) { 7180fb889b8SWei Yongjun array_free(se_tpg->tpg_lun_list, 7190fb889b8SWei Yongjun TRANSPORT_MAX_LUNS_PER_TPG); 720c66ac9dbSNicholas Bellinger return -ENOMEM; 721c66ac9dbSNicholas Bellinger } 722c66ac9dbSNicholas Bellinger } 723c66ac9dbSNicholas Bellinger 724e3d6f909SAndy Grover spin_lock_bh(&tpg_lock); 725e3d6f909SAndy Grover list_add_tail(&se_tpg->se_tpg_node, &tpg_list); 726e3d6f909SAndy Grover spin_unlock_bh(&tpg_lock); 727c66ac9dbSNicholas Bellinger 7286708bb27SAndy Grover pr_debug("TARGET_CORE[%s]: Allocated %s struct se_portal_group for" 729c66ac9dbSNicholas Bellinger " endpoint: %s, Portal Tag: %u\n", tfo->get_fabric_name(), 730c66ac9dbSNicholas Bellinger (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ? 731c66ac9dbSNicholas Bellinger "Normal" : "Discovery", (tfo->tpg_get_wwn(se_tpg) == NULL) ? 732c66ac9dbSNicholas Bellinger "None" : tfo->tpg_get_wwn(se_tpg), tfo->tpg_get_tag(se_tpg)); 733c66ac9dbSNicholas Bellinger 734c66ac9dbSNicholas Bellinger return 0; 735c66ac9dbSNicholas Bellinger } 736c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_register); 737c66ac9dbSNicholas Bellinger 738c66ac9dbSNicholas Bellinger int core_tpg_deregister(struct se_portal_group *se_tpg) 739c66ac9dbSNicholas Bellinger { 740e89d15eeSNicholas Bellinger struct se_node_acl *nacl, *nacl_tmp; 741e89d15eeSNicholas Bellinger 7426708bb27SAndy Grover pr_debug("TARGET_CORE[%s]: Deallocating %s struct se_portal_group" 743c66ac9dbSNicholas Bellinger " for endpoint: %s Portal Tag %u\n", 744c66ac9dbSNicholas Bellinger (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) ? 745e3d6f909SAndy Grover "Normal" : "Discovery", se_tpg->se_tpg_tfo->get_fabric_name(), 746e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg), 747e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); 748c66ac9dbSNicholas Bellinger 749e3d6f909SAndy Grover spin_lock_bh(&tpg_lock); 750e3d6f909SAndy Grover list_del(&se_tpg->se_tpg_node); 751e3d6f909SAndy Grover spin_unlock_bh(&tpg_lock); 752c66ac9dbSNicholas Bellinger 753c66ac9dbSNicholas Bellinger while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0) 754c66ac9dbSNicholas Bellinger cpu_relax(); 755e89d15eeSNicholas Bellinger /* 756e89d15eeSNicholas Bellinger * Release any remaining demo-mode generated se_node_acl that have 757e89d15eeSNicholas Bellinger * not been released because of TFO->tpg_check_demo_mode_cache() == 1 758e89d15eeSNicholas Bellinger * in transport_deregister_session(). 759e89d15eeSNicholas Bellinger */ 76028638887SRoland Dreier spin_lock_irq(&se_tpg->acl_node_lock); 761e89d15eeSNicholas Bellinger list_for_each_entry_safe(nacl, nacl_tmp, &se_tpg->acl_node_list, 762e89d15eeSNicholas Bellinger acl_list) { 763e89d15eeSNicholas Bellinger list_del(&nacl->acl_list); 764e89d15eeSNicholas Bellinger se_tpg->num_node_acls--; 76528638887SRoland Dreier spin_unlock_irq(&se_tpg->acl_node_lock); 766e89d15eeSNicholas Bellinger 767e89d15eeSNicholas Bellinger core_tpg_wait_for_nacl_pr_ref(nacl); 768e89d15eeSNicholas Bellinger core_free_device_list_for_node(nacl, se_tpg); 769e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_release_fabric_acl(se_tpg, nacl); 770e89d15eeSNicholas Bellinger 77128638887SRoland Dreier spin_lock_irq(&se_tpg->acl_node_lock); 772e89d15eeSNicholas Bellinger } 77328638887SRoland Dreier spin_unlock_irq(&se_tpg->acl_node_lock); 774c66ac9dbSNicholas Bellinger 775c66ac9dbSNicholas Bellinger if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) 776c66ac9dbSNicholas Bellinger core_tpg_release_virtual_lun0(se_tpg); 777c66ac9dbSNicholas Bellinger 778c66ac9dbSNicholas Bellinger se_tpg->se_tpg_fabric_ptr = NULL; 7794a5a75f3SJörn Engel array_free(se_tpg->tpg_lun_list, TRANSPORT_MAX_LUNS_PER_TPG); 780c66ac9dbSNicholas Bellinger return 0; 781c66ac9dbSNicholas Bellinger } 782c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_deregister); 783c66ac9dbSNicholas Bellinger 784d344f8a1SAndy Grover struct se_lun *core_tpg_alloc_lun( 785c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 786c66ac9dbSNicholas Bellinger u32 unpacked_lun) 787c66ac9dbSNicholas Bellinger { 788c66ac9dbSNicholas Bellinger struct se_lun *lun; 789c66ac9dbSNicholas Bellinger 790c66ac9dbSNicholas Bellinger if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) { 7916708bb27SAndy Grover pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG" 792c66ac9dbSNicholas Bellinger "-1: %u for Target Portal Group: %u\n", 793e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), 794c66ac9dbSNicholas Bellinger unpacked_lun, TRANSPORT_MAX_LUNS_PER_TPG-1, 795e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 796c66ac9dbSNicholas Bellinger return ERR_PTR(-EOVERFLOW); 797c66ac9dbSNicholas Bellinger } 798c66ac9dbSNicholas Bellinger 799c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 8004a5a75f3SJörn Engel lun = tpg->tpg_lun_list[unpacked_lun]; 801c66ac9dbSNicholas Bellinger if (lun->lun_status == TRANSPORT_LUN_STATUS_ACTIVE) { 8026708bb27SAndy Grover pr_err("TPG Logical Unit Number: %u is already active" 803c66ac9dbSNicholas Bellinger " on %s Target Portal Group: %u, ignoring request.\n", 804e3d6f909SAndy Grover unpacked_lun, tpg->se_tpg_tfo->get_fabric_name(), 805e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 806c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 807c66ac9dbSNicholas Bellinger return ERR_PTR(-EINVAL); 808c66ac9dbSNicholas Bellinger } 809c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 810c66ac9dbSNicholas Bellinger 811c66ac9dbSNicholas Bellinger return lun; 812c66ac9dbSNicholas Bellinger } 813c66ac9dbSNicholas Bellinger 814d344f8a1SAndy Grover int core_tpg_add_lun( 815c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 816c66ac9dbSNicholas Bellinger struct se_lun *lun, 817c66ac9dbSNicholas Bellinger u32 lun_access, 818340dbf72SAndy Grover struct se_device *dev) 819c66ac9dbSNicholas Bellinger { 820e3d6f909SAndy Grover int ret; 821e3d6f909SAndy Grover 8225277797dSNicholas Bellinger ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release); 823e3d6f909SAndy Grover if (ret < 0) 824e3d6f909SAndy Grover return ret; 825c66ac9dbSNicholas Bellinger 826340dbf72SAndy Grover ret = core_dev_export(dev, tpg, lun); 8275277797dSNicholas Bellinger if (ret < 0) { 8289a1049daSTejun Heo percpu_ref_exit(&lun->lun_ref); 8295277797dSNicholas Bellinger return ret; 8305277797dSNicholas Bellinger } 8315277797dSNicholas Bellinger 832c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 833c66ac9dbSNicholas Bellinger lun->lun_access = lun_access; 834c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_ACTIVE; 835c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 836c66ac9dbSNicholas Bellinger 837c66ac9dbSNicholas Bellinger return 0; 838c66ac9dbSNicholas Bellinger } 839c66ac9dbSNicholas Bellinger 840cd9d7cbaSAndy Grover void core_tpg_remove_lun( 841c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 842c66ac9dbSNicholas Bellinger struct se_lun *lun) 843c66ac9dbSNicholas Bellinger { 8444a9a6c8dSNicholas Bellinger core_clear_lun_from_tpg(lun, tpg); 8454a9a6c8dSNicholas Bellinger transport_clear_lun_ref(lun); 846c66ac9dbSNicholas Bellinger 847c66ac9dbSNicholas Bellinger core_dev_unexport(lun->lun_se_dev, tpg, lun); 848c66ac9dbSNicholas Bellinger 849c66ac9dbSNicholas Bellinger spin_lock(&tpg->tpg_lun_lock); 850c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 851c66ac9dbSNicholas Bellinger spin_unlock(&tpg->tpg_lun_lock); 852c66ac9dbSNicholas Bellinger 8539a1049daSTejun Heo percpu_ref_exit(&lun->lun_ref); 854c66ac9dbSNicholas Bellinger } 855