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" 43e2480563SNicholas Bellinger #include "target_core_pr.h" 44e3d6f909SAndy Grover 45e3d6f909SAndy Grover extern struct se_device *g_lun0_dev; 46e3d6f909SAndy Grover 47e3d6f909SAndy Grover static DEFINE_SPINLOCK(tpg_lock); 48e3d6f909SAndy Grover static LIST_HEAD(tpg_list); 49c66ac9dbSNicholas Bellinger 50c66ac9dbSNicholas Bellinger /* __core_tpg_get_initiator_node_acl(): 51c66ac9dbSNicholas Bellinger * 52403edd78SNicholas Bellinger * mutex_lock(&tpg->acl_node_mutex); must be held when calling 53c66ac9dbSNicholas Bellinger */ 54c66ac9dbSNicholas Bellinger struct se_node_acl *__core_tpg_get_initiator_node_acl( 55c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 56c66ac9dbSNicholas Bellinger const char *initiatorname) 57c66ac9dbSNicholas Bellinger { 58c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 59c66ac9dbSNicholas Bellinger 60c66ac9dbSNicholas Bellinger list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { 616708bb27SAndy Grover if (!strcmp(acl->initiatorname, initiatorname)) 62c66ac9dbSNicholas Bellinger return acl; 63c66ac9dbSNicholas Bellinger } 64c66ac9dbSNicholas Bellinger 65c66ac9dbSNicholas Bellinger return NULL; 66c66ac9dbSNicholas Bellinger } 67c66ac9dbSNicholas Bellinger 68c66ac9dbSNicholas Bellinger /* core_tpg_get_initiator_node_acl(): 69c66ac9dbSNicholas Bellinger * 70c66ac9dbSNicholas Bellinger * 71c66ac9dbSNicholas Bellinger */ 72c66ac9dbSNicholas Bellinger struct se_node_acl *core_tpg_get_initiator_node_acl( 73c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 74c66ac9dbSNicholas Bellinger unsigned char *initiatorname) 75c66ac9dbSNicholas Bellinger { 76c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 77c66ac9dbSNicholas Bellinger 78403edd78SNicholas Bellinger mutex_lock(&tpg->acl_node_mutex); 79fcf29481SNicholas Bellinger acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); 80403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 81c66ac9dbSNicholas Bellinger 82fcf29481SNicholas Bellinger return acl; 83c66ac9dbSNicholas Bellinger } 84b3fde035SThomas Glanzmann EXPORT_SYMBOL(core_tpg_get_initiator_node_acl); 85c66ac9dbSNicholas Bellinger 86c66ac9dbSNicholas Bellinger /* core_tpg_add_node_to_devs(): 87c66ac9dbSNicholas Bellinger * 88c66ac9dbSNicholas Bellinger * 89c66ac9dbSNicholas Bellinger */ 90c66ac9dbSNicholas Bellinger void core_tpg_add_node_to_devs( 91c66ac9dbSNicholas Bellinger struct se_node_acl *acl, 92c66ac9dbSNicholas Bellinger struct se_portal_group *tpg) 93c66ac9dbSNicholas Bellinger { 94c66ac9dbSNicholas Bellinger u32 lun_access = 0; 95c66ac9dbSNicholas Bellinger struct se_lun *lun; 96c66ac9dbSNicholas Bellinger struct se_device *dev; 97c66ac9dbSNicholas Bellinger 986bb82612SNicholas Bellinger mutex_lock(&tpg->tpg_lun_mutex); 996bb82612SNicholas Bellinger hlist_for_each_entry_rcu(lun, &tpg->tpg_lun_hlist, link) { 100c66ac9dbSNicholas Bellinger if (lun->lun_status != TRANSPORT_LUN_STATUS_ACTIVE) 101c66ac9dbSNicholas Bellinger continue; 102c66ac9dbSNicholas Bellinger 103c66ac9dbSNicholas Bellinger dev = lun->lun_se_dev; 104c66ac9dbSNicholas Bellinger /* 105c66ac9dbSNicholas Bellinger * By default in LIO-Target $FABRIC_MOD, 106c66ac9dbSNicholas Bellinger * demo_mode_write_protect is ON, or READ_ONLY; 107c66ac9dbSNicholas Bellinger */ 1086708bb27SAndy Grover if (!tpg->se_tpg_tfo->tpg_check_demo_mode_write_protect(tpg)) { 109c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; 110c66ac9dbSNicholas Bellinger } else { 111c66ac9dbSNicholas Bellinger /* 112c66ac9dbSNicholas Bellinger * Allow only optical drives to issue R/W in default RO 113c66ac9dbSNicholas Bellinger * demo mode. 114c66ac9dbSNicholas Bellinger */ 115e3d6f909SAndy Grover if (dev->transport->get_device_type(dev) == TYPE_DISK) 116c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_ONLY; 117c66ac9dbSNicholas Bellinger else 118c66ac9dbSNicholas Bellinger lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; 119c66ac9dbSNicholas Bellinger } 120c66ac9dbSNicholas Bellinger 1216708bb27SAndy Grover pr_debug("TARGET_CORE[%s]->TPG[%u]_LUN[%u] - Adding %s" 122c66ac9dbSNicholas Bellinger " access for LUN in Demo Mode\n", 123e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), 124e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, 125c66ac9dbSNicholas Bellinger (lun_access == TRANSPORT_LUNFLAGS_READ_WRITE) ? 126c66ac9dbSNicholas Bellinger "READ-WRITE" : "READ-ONLY"); 127c66ac9dbSNicholas Bellinger 128e80ac6c4SAndy Grover core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun, 129e80ac6c4SAndy Grover lun_access, acl, tpg); 130e2480563SNicholas Bellinger /* 131e2480563SNicholas Bellinger * Check to see if there are any existing persistent reservation 132e2480563SNicholas Bellinger * APTPL pre-registrations that need to be enabled for this dynamic 133e2480563SNicholas Bellinger * LUN ACL now.. 134e2480563SNicholas Bellinger */ 135e2480563SNicholas Bellinger core_scsi3_check_aptpl_registration(dev, tpg, lun, acl, 136e2480563SNicholas Bellinger lun->unpacked_lun); 137c66ac9dbSNicholas Bellinger } 1386bb82612SNicholas Bellinger mutex_unlock(&tpg->tpg_lun_mutex); 139c66ac9dbSNicholas Bellinger } 140c66ac9dbSNicholas Bellinger 141c66ac9dbSNicholas Bellinger /* core_set_queue_depth_for_node(): 142c66ac9dbSNicholas Bellinger * 143c66ac9dbSNicholas Bellinger * 144c66ac9dbSNicholas Bellinger */ 145c66ac9dbSNicholas Bellinger static int core_set_queue_depth_for_node( 146c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 147c66ac9dbSNicholas Bellinger struct se_node_acl *acl) 148c66ac9dbSNicholas Bellinger { 149c66ac9dbSNicholas Bellinger if (!acl->queue_depth) { 1506708bb27SAndy Grover pr_err("Queue depth for %s Initiator Node: %s is 0," 151e3d6f909SAndy Grover "defaulting to 1.\n", tpg->se_tpg_tfo->get_fabric_name(), 152c66ac9dbSNicholas Bellinger acl->initiatorname); 153c66ac9dbSNicholas Bellinger acl->queue_depth = 1; 154c66ac9dbSNicholas Bellinger } 155c66ac9dbSNicholas Bellinger 156c66ac9dbSNicholas Bellinger return 0; 157c66ac9dbSNicholas Bellinger } 158c66ac9dbSNicholas Bellinger 159e413f472SChristoph Hellwig static struct se_node_acl *target_alloc_node_acl(struct se_portal_group *tpg, 160e413f472SChristoph Hellwig const unsigned char *initiatorname) 161c66ac9dbSNicholas Bellinger { 162c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 163c66ac9dbSNicholas Bellinger 164144bc4c2SChristoph Hellwig acl = kzalloc(max(sizeof(*acl), tpg->se_tpg_tfo->node_acl_size), 165144bc4c2SChristoph Hellwig GFP_KERNEL); 1666708bb27SAndy Grover if (!acl) 167c66ac9dbSNicholas Bellinger return NULL; 168c66ac9dbSNicholas Bellinger 169c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_list); 170c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&acl->acl_sess_list); 17129a05deeSNicholas Bellinger INIT_HLIST_HEAD(&acl->lun_entry_hlist); 172afb999ffSNicholas Bellinger kref_init(&acl->acl_kref); 17301468346SNicholas Bellinger init_completion(&acl->acl_free_comp); 174c66ac9dbSNicholas Bellinger spin_lock_init(&acl->nacl_sess_lock); 17529a05deeSNicholas Bellinger mutex_init(&acl->lun_entry_mutex); 176c66ac9dbSNicholas Bellinger atomic_set(&acl->acl_pr_ref_count, 0); 177e1750d20SChristoph Hellwig if (tpg->se_tpg_tfo->tpg_get_default_depth) 178e3d6f909SAndy Grover acl->queue_depth = tpg->se_tpg_tfo->tpg_get_default_depth(tpg); 179e1750d20SChristoph Hellwig else 180e1750d20SChristoph Hellwig acl->queue_depth = 1; 181c66ac9dbSNicholas Bellinger snprintf(acl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); 182c66ac9dbSNicholas Bellinger acl->se_tpg = tpg; 183c66ac9dbSNicholas Bellinger acl->acl_index = scsi_get_new_index(SCSI_AUTH_INTR_INDEX); 184c66ac9dbSNicholas Bellinger 185e3d6f909SAndy Grover tpg->se_tpg_tfo->set_default_node_attributes(acl); 186c66ac9dbSNicholas Bellinger 187e413f472SChristoph Hellwig if (core_set_queue_depth_for_node(tpg, acl) < 0) 18829a05deeSNicholas Bellinger goto out_free_acl; 189e413f472SChristoph Hellwig 190e413f472SChristoph Hellwig return acl; 191e413f472SChristoph Hellwig 192e413f472SChristoph Hellwig out_free_acl: 193144bc4c2SChristoph Hellwig kfree(acl); 194c66ac9dbSNicholas Bellinger return NULL; 195c66ac9dbSNicholas Bellinger } 196c66ac9dbSNicholas Bellinger 197e413f472SChristoph Hellwig static void target_add_node_acl(struct se_node_acl *acl) 198e413f472SChristoph Hellwig { 199e413f472SChristoph Hellwig struct se_portal_group *tpg = acl->se_tpg; 200e413f472SChristoph Hellwig 201403edd78SNicholas Bellinger mutex_lock(&tpg->acl_node_mutex); 202e413f472SChristoph Hellwig list_add_tail(&acl->acl_list, &tpg->acl_node_list); 203e413f472SChristoph Hellwig tpg->num_node_acls++; 204403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 205e413f472SChristoph Hellwig 206e413f472SChristoph Hellwig pr_debug("%s_TPG[%hu] - Added %s ACL with TCQ Depth: %d for %s" 207e413f472SChristoph Hellwig " Initiator Node: %s\n", 208e413f472SChristoph Hellwig tpg->se_tpg_tfo->get_fabric_name(), 209e413f472SChristoph Hellwig tpg->se_tpg_tfo->tpg_get_tag(tpg), 210e413f472SChristoph Hellwig acl->dynamic_node_acl ? "DYNAMIC" : "", 211e413f472SChristoph Hellwig acl->queue_depth, 212e413f472SChristoph Hellwig tpg->se_tpg_tfo->get_fabric_name(), 213e413f472SChristoph Hellwig acl->initiatorname); 214c66ac9dbSNicholas Bellinger } 215e413f472SChristoph Hellwig 216e413f472SChristoph Hellwig struct se_node_acl *core_tpg_check_initiator_node_acl( 217e413f472SChristoph Hellwig struct se_portal_group *tpg, 218e413f472SChristoph Hellwig unsigned char *initiatorname) 219e413f472SChristoph Hellwig { 220e413f472SChristoph Hellwig struct se_node_acl *acl; 221e413f472SChristoph Hellwig 222e413f472SChristoph Hellwig acl = core_tpg_get_initiator_node_acl(tpg, initiatorname); 223e413f472SChristoph Hellwig if (acl) 224e413f472SChristoph Hellwig return acl; 225e413f472SChristoph Hellwig 226e413f472SChristoph Hellwig if (!tpg->se_tpg_tfo->tpg_check_demo_mode(tpg)) 227e413f472SChristoph Hellwig return NULL; 228e413f472SChristoph Hellwig 229e413f472SChristoph Hellwig acl = target_alloc_node_acl(tpg, initiatorname); 230e413f472SChristoph Hellwig if (!acl) 231e413f472SChristoph Hellwig return NULL; 232e413f472SChristoph Hellwig acl->dynamic_node_acl = 1; 233e413f472SChristoph Hellwig 234052605c6SNicholas Bellinger /* 235052605c6SNicholas Bellinger * Here we only create demo-mode MappedLUNs from the active 23635d1efe8SMasanari Iida * TPG LUNs if the fabric is not explicitly asking for 237052605c6SNicholas Bellinger * tpg_check_demo_mode_login_only() == 1. 238052605c6SNicholas Bellinger */ 239cdf88a2fSAndy Grover if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only == NULL) || 240cdf88a2fSAndy Grover (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) != 1)) 241c66ac9dbSNicholas Bellinger core_tpg_add_node_to_devs(acl, tpg); 242c66ac9dbSNicholas Bellinger 243e413f472SChristoph Hellwig target_add_node_acl(acl); 244c66ac9dbSNicholas Bellinger return acl; 245c66ac9dbSNicholas Bellinger } 246c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_check_initiator_node_acl); 247c66ac9dbSNicholas Bellinger 248c66ac9dbSNicholas Bellinger void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *nacl) 249c66ac9dbSNicholas Bellinger { 250c66ac9dbSNicholas Bellinger while (atomic_read(&nacl->acl_pr_ref_count) != 0) 251c66ac9dbSNicholas Bellinger cpu_relax(); 252c66ac9dbSNicholas Bellinger } 253c66ac9dbSNicholas Bellinger 254c66ac9dbSNicholas Bellinger struct se_node_acl *core_tpg_add_initiator_node_acl( 255c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 256c7d6a803SChristoph Hellwig const char *initiatorname) 257c66ac9dbSNicholas Bellinger { 258c7d6a803SChristoph Hellwig struct se_node_acl *acl; 259c66ac9dbSNicholas Bellinger 260403edd78SNicholas Bellinger mutex_lock(&tpg->acl_node_mutex); 261c66ac9dbSNicholas Bellinger acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); 2626708bb27SAndy Grover if (acl) { 263c66ac9dbSNicholas Bellinger if (acl->dynamic_node_acl) { 264c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 0; 2656708bb27SAndy Grover pr_debug("%s_TPG[%u] - Replacing dynamic ACL" 266e3d6f909SAndy Grover " for %s\n", tpg->se_tpg_tfo->get_fabric_name(), 267e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), initiatorname); 268403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 269e413f472SChristoph Hellwig return acl; 270c66ac9dbSNicholas Bellinger } 271c66ac9dbSNicholas Bellinger 2726708bb27SAndy Grover pr_err("ACL entry for %s Initiator" 273c66ac9dbSNicholas Bellinger " Node %s already exists for TPG %u, ignoring" 274e3d6f909SAndy Grover " request.\n", tpg->se_tpg_tfo->get_fabric_name(), 275e3d6f909SAndy Grover initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); 276403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 277c66ac9dbSNicholas Bellinger return ERR_PTR(-EEXIST); 278c66ac9dbSNicholas Bellinger } 279403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 280c66ac9dbSNicholas Bellinger 281e413f472SChristoph Hellwig acl = target_alloc_node_acl(tpg, initiatorname); 282e413f472SChristoph Hellwig if (!acl) 283c66ac9dbSNicholas Bellinger return ERR_PTR(-ENOMEM); 284c66ac9dbSNicholas Bellinger 285e413f472SChristoph Hellwig target_add_node_acl(acl); 286c66ac9dbSNicholas Bellinger return acl; 287c66ac9dbSNicholas Bellinger } 288c66ac9dbSNicholas Bellinger 289c7d6a803SChristoph Hellwig void core_tpg_del_initiator_node_acl(struct se_node_acl *acl) 290c66ac9dbSNicholas Bellinger { 291c7d6a803SChristoph Hellwig struct se_portal_group *tpg = acl->se_tpg; 292337c0607SNicholas Bellinger LIST_HEAD(sess_list); 293c66ac9dbSNicholas Bellinger struct se_session *sess, *sess_tmp; 294140854cbSNicholas Bellinger unsigned long flags; 29528168905SJörn Engel int rc; 296c66ac9dbSNicholas Bellinger 297403edd78SNicholas Bellinger mutex_lock(&tpg->acl_node_mutex); 298c66ac9dbSNicholas Bellinger if (acl->dynamic_node_acl) { 299c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 0; 300c66ac9dbSNicholas Bellinger } 301c66ac9dbSNicholas Bellinger list_del(&acl->acl_list); 302c66ac9dbSNicholas Bellinger tpg->num_node_acls--; 303403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 304c66ac9dbSNicholas Bellinger 305337c0607SNicholas Bellinger spin_lock_irqsave(&acl->nacl_sess_lock, flags); 306337c0607SNicholas Bellinger acl->acl_stop = 1; 307337c0607SNicholas Bellinger 308337c0607SNicholas Bellinger list_for_each_entry_safe(sess, sess_tmp, &acl->acl_sess_list, 309337c0607SNicholas Bellinger sess_acl_list) { 310337c0607SNicholas Bellinger if (sess->sess_tearing_down != 0) 311c66ac9dbSNicholas Bellinger continue; 312c66ac9dbSNicholas Bellinger 313337c0607SNicholas Bellinger target_get_session(sess); 314337c0607SNicholas Bellinger list_move(&sess->sess_acl_list, &sess_list); 315c66ac9dbSNicholas Bellinger } 316337c0607SNicholas Bellinger spin_unlock_irqrestore(&acl->nacl_sess_lock, flags); 317337c0607SNicholas Bellinger 318337c0607SNicholas Bellinger list_for_each_entry_safe(sess, sess_tmp, &sess_list, sess_acl_list) { 319337c0607SNicholas Bellinger list_del(&sess->sess_acl_list); 320337c0607SNicholas Bellinger 321337c0607SNicholas Bellinger rc = tpg->se_tpg_tfo->shutdown_session(sess); 322337c0607SNicholas Bellinger target_put_session(sess); 323337c0607SNicholas Bellinger if (!rc) 324337c0607SNicholas Bellinger continue; 325337c0607SNicholas Bellinger target_put_session(sess); 326337c0607SNicholas Bellinger } 327337c0607SNicholas Bellinger target_put_nacl(acl); 328337c0607SNicholas Bellinger /* 329337c0607SNicholas Bellinger * Wait for last target_put_nacl() to complete in target_complete_nacl() 330337c0607SNicholas Bellinger * for active fabric session transport_deregister_session() callbacks. 331337c0607SNicholas Bellinger */ 332337c0607SNicholas Bellinger wait_for_completion(&acl->acl_free_comp); 333c66ac9dbSNicholas Bellinger 334c66ac9dbSNicholas Bellinger core_tpg_wait_for_nacl_pr_ref(acl); 335c66ac9dbSNicholas Bellinger core_free_device_list_for_node(acl, tpg); 336c66ac9dbSNicholas Bellinger 3376708bb27SAndy Grover pr_debug("%s_TPG[%hu] - Deleted ACL with TCQ Depth: %d for %s" 338e3d6f909SAndy Grover " Initiator Node: %s\n", tpg->se_tpg_tfo->get_fabric_name(), 339e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), acl->queue_depth, 340e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), acl->initiatorname); 341c66ac9dbSNicholas Bellinger 342144bc4c2SChristoph Hellwig kfree(acl); 343c66ac9dbSNicholas Bellinger } 344c66ac9dbSNicholas Bellinger 345c66ac9dbSNicholas Bellinger /* core_tpg_set_initiator_node_queue_depth(): 346c66ac9dbSNicholas Bellinger * 347c66ac9dbSNicholas Bellinger * 348c66ac9dbSNicholas Bellinger */ 349c66ac9dbSNicholas Bellinger int core_tpg_set_initiator_node_queue_depth( 350c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 351c66ac9dbSNicholas Bellinger unsigned char *initiatorname, 352c66ac9dbSNicholas Bellinger u32 queue_depth, 353c66ac9dbSNicholas Bellinger int force) 354c66ac9dbSNicholas Bellinger { 355c66ac9dbSNicholas Bellinger struct se_session *sess, *init_sess = NULL; 356c66ac9dbSNicholas Bellinger struct se_node_acl *acl; 357140854cbSNicholas Bellinger unsigned long flags; 358c66ac9dbSNicholas Bellinger int dynamic_acl = 0; 359c66ac9dbSNicholas Bellinger 360403edd78SNicholas Bellinger mutex_lock(&tpg->acl_node_mutex); 361c66ac9dbSNicholas Bellinger acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); 3626708bb27SAndy Grover if (!acl) { 3636708bb27SAndy Grover pr_err("Access Control List entry for %s Initiator" 364c66ac9dbSNicholas Bellinger " Node %s does not exists for TPG %hu, ignoring" 365e3d6f909SAndy Grover " request.\n", tpg->se_tpg_tfo->get_fabric_name(), 366e3d6f909SAndy Grover initiatorname, tpg->se_tpg_tfo->tpg_get_tag(tpg)); 367403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 368c66ac9dbSNicholas Bellinger return -ENODEV; 369c66ac9dbSNicholas Bellinger } 370c66ac9dbSNicholas Bellinger if (acl->dynamic_node_acl) { 371c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 0; 372c66ac9dbSNicholas Bellinger dynamic_acl = 1; 373c66ac9dbSNicholas Bellinger } 374403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 375c66ac9dbSNicholas Bellinger 376140854cbSNicholas Bellinger spin_lock_irqsave(&tpg->session_lock, flags); 377c66ac9dbSNicholas Bellinger list_for_each_entry(sess, &tpg->tpg_sess_list, sess_list) { 378c66ac9dbSNicholas Bellinger if (sess->se_node_acl != acl) 379c66ac9dbSNicholas Bellinger continue; 380c66ac9dbSNicholas Bellinger 381c66ac9dbSNicholas Bellinger if (!force) { 3826708bb27SAndy Grover pr_err("Unable to change queue depth for %s" 383c66ac9dbSNicholas Bellinger " Initiator Node: %s while session is" 384c66ac9dbSNicholas Bellinger " operational. To forcefully change the queue" 385c66ac9dbSNicholas Bellinger " depth and force session reinstatement" 386c66ac9dbSNicholas Bellinger " use the \"force=1\" parameter.\n", 387e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), initiatorname); 388140854cbSNicholas Bellinger spin_unlock_irqrestore(&tpg->session_lock, flags); 389c66ac9dbSNicholas Bellinger 390403edd78SNicholas Bellinger mutex_lock(&tpg->acl_node_mutex); 391c66ac9dbSNicholas Bellinger if (dynamic_acl) 392c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 393403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 394c66ac9dbSNicholas Bellinger return -EEXIST; 395c66ac9dbSNicholas Bellinger } 396c66ac9dbSNicholas Bellinger /* 397c66ac9dbSNicholas Bellinger * Determine if the session needs to be closed by our context. 398c66ac9dbSNicholas Bellinger */ 3996708bb27SAndy Grover if (!tpg->se_tpg_tfo->shutdown_session(sess)) 400c66ac9dbSNicholas Bellinger continue; 401c66ac9dbSNicholas Bellinger 402c66ac9dbSNicholas Bellinger init_sess = sess; 403c66ac9dbSNicholas Bellinger break; 404c66ac9dbSNicholas Bellinger } 405c66ac9dbSNicholas Bellinger 406c66ac9dbSNicholas Bellinger /* 407c66ac9dbSNicholas Bellinger * User has requested to change the queue depth for a Initiator Node. 408c66ac9dbSNicholas Bellinger * Change the value in the Node's struct se_node_acl, and call 409c66ac9dbSNicholas Bellinger * core_set_queue_depth_for_node() to add the requested queue depth. 410c66ac9dbSNicholas Bellinger * 411e3d6f909SAndy Grover * Finally call tpg->se_tpg_tfo->close_session() to force session 412c66ac9dbSNicholas Bellinger * reinstatement to occur if there is an active session for the 413c66ac9dbSNicholas Bellinger * $FABRIC_MOD Initiator Node in question. 414c66ac9dbSNicholas Bellinger */ 415c66ac9dbSNicholas Bellinger acl->queue_depth = queue_depth; 416c66ac9dbSNicholas Bellinger 417c66ac9dbSNicholas Bellinger if (core_set_queue_depth_for_node(tpg, acl) < 0) { 418140854cbSNicholas Bellinger spin_unlock_irqrestore(&tpg->session_lock, flags); 419c66ac9dbSNicholas Bellinger /* 420c66ac9dbSNicholas Bellinger * Force session reinstatement if 421c66ac9dbSNicholas Bellinger * core_set_queue_depth_for_node() failed, because we assume 422c66ac9dbSNicholas Bellinger * the $FABRIC_MOD has already the set session reinstatement 423e3d6f909SAndy Grover * bit from tpg->se_tpg_tfo->shutdown_session() called above. 424c66ac9dbSNicholas Bellinger */ 425c66ac9dbSNicholas Bellinger if (init_sess) 426e3d6f909SAndy Grover tpg->se_tpg_tfo->close_session(init_sess); 427c66ac9dbSNicholas Bellinger 428403edd78SNicholas Bellinger mutex_lock(&tpg->acl_node_mutex); 429c66ac9dbSNicholas Bellinger if (dynamic_acl) 430c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 431403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 432c66ac9dbSNicholas Bellinger return -EINVAL; 433c66ac9dbSNicholas Bellinger } 434140854cbSNicholas Bellinger spin_unlock_irqrestore(&tpg->session_lock, flags); 435c66ac9dbSNicholas Bellinger /* 436c66ac9dbSNicholas Bellinger * If the $FABRIC_MOD session for the Initiator Node ACL exists, 437c66ac9dbSNicholas Bellinger * forcefully shutdown the $FABRIC_MOD session/nexus. 438c66ac9dbSNicholas Bellinger */ 439c66ac9dbSNicholas Bellinger if (init_sess) 440e3d6f909SAndy Grover tpg->se_tpg_tfo->close_session(init_sess); 441c66ac9dbSNicholas Bellinger 442bfb9035cSJoe Perches pr_debug("Successfully changed queue depth to: %d for Initiator" 443c66ac9dbSNicholas Bellinger " Node: %s on %s Target Portal Group: %u\n", queue_depth, 444e3d6f909SAndy Grover initiatorname, tpg->se_tpg_tfo->get_fabric_name(), 445e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 446c66ac9dbSNicholas Bellinger 447403edd78SNicholas Bellinger mutex_lock(&tpg->acl_node_mutex); 448c66ac9dbSNicholas Bellinger if (dynamic_acl) 449c66ac9dbSNicholas Bellinger acl->dynamic_node_acl = 1; 450403edd78SNicholas Bellinger mutex_unlock(&tpg->acl_node_mutex); 451c66ac9dbSNicholas Bellinger 452c66ac9dbSNicholas Bellinger return 0; 453c66ac9dbSNicholas Bellinger } 454c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_set_initiator_node_queue_depth); 455c66ac9dbSNicholas Bellinger 45679e62fc3SAndy Grover /* core_tpg_set_initiator_node_tag(): 45779e62fc3SAndy Grover * 45879e62fc3SAndy Grover * Initiator nodeacl tags are not used internally, but may be used by 45979e62fc3SAndy Grover * userspace to emulate aliases or groups. 46079e62fc3SAndy Grover * Returns length of newly-set tag or -EINVAL. 46179e62fc3SAndy Grover */ 46279e62fc3SAndy Grover int core_tpg_set_initiator_node_tag( 46379e62fc3SAndy Grover struct se_portal_group *tpg, 46479e62fc3SAndy Grover struct se_node_acl *acl, 46579e62fc3SAndy Grover const char *new_tag) 46679e62fc3SAndy Grover { 46779e62fc3SAndy Grover if (strlen(new_tag) >= MAX_ACL_TAG_SIZE) 46879e62fc3SAndy Grover return -EINVAL; 46979e62fc3SAndy Grover 47079e62fc3SAndy Grover if (!strncmp("NULL", new_tag, 4)) { 47179e62fc3SAndy Grover acl->acl_tag[0] = '\0'; 47279e62fc3SAndy Grover return 0; 47379e62fc3SAndy Grover } 47479e62fc3SAndy Grover 47579e62fc3SAndy Grover return snprintf(acl->acl_tag, MAX_ACL_TAG_SIZE, "%s", new_tag); 47679e62fc3SAndy Grover } 47779e62fc3SAndy Grover EXPORT_SYMBOL(core_tpg_set_initiator_node_tag); 47879e62fc3SAndy Grover 4795277797dSNicholas Bellinger static void core_tpg_lun_ref_release(struct percpu_ref *ref) 4805277797dSNicholas Bellinger { 4815277797dSNicholas Bellinger struct se_lun *lun = container_of(ref, struct se_lun, lun_ref); 4825277797dSNicholas Bellinger 4835277797dSNicholas Bellinger complete(&lun->lun_ref_comp); 4845277797dSNicholas Bellinger } 4855277797dSNicholas Bellinger 486c66ac9dbSNicholas Bellinger static int core_tpg_setup_virtual_lun0(struct se_portal_group *se_tpg) 487c66ac9dbSNicholas Bellinger { 488c66ac9dbSNicholas Bellinger /* Set in core_dev_setup_virtual_lun0() */ 489e3d6f909SAndy Grover struct se_device *dev = g_lun0_dev; 490c66ac9dbSNicholas Bellinger struct se_lun *lun = &se_tpg->tpg_virt_lun0; 491c66ac9dbSNicholas Bellinger u32 lun_access = TRANSPORT_LUNFLAGS_READ_ONLY; 492c66ac9dbSNicholas Bellinger int ret; 493c66ac9dbSNicholas Bellinger 494c66ac9dbSNicholas Bellinger lun->unpacked_lun = 0; 495c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 496c66ac9dbSNicholas Bellinger atomic_set(&lun->lun_acl_count, 0); 497c66ac9dbSNicholas Bellinger init_completion(&lun->lun_shutdown_comp); 498c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lun->lun_acl_list); 499c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_acl_lock); 500c66ac9dbSNicholas Bellinger spin_lock_init(&lun->lun_sep_lock); 5015277797dSNicholas Bellinger init_completion(&lun->lun_ref_comp); 502c66ac9dbSNicholas Bellinger 5034e13c5d0SLinus Torvalds ret = core_tpg_add_lun(se_tpg, lun, lun_access, dev); 504c66ac9dbSNicholas Bellinger if (ret < 0) 505e3d6f909SAndy Grover return ret; 506c66ac9dbSNicholas Bellinger 507c66ac9dbSNicholas Bellinger return 0; 508c66ac9dbSNicholas Bellinger } 509c66ac9dbSNicholas Bellinger 510c66ac9dbSNicholas Bellinger int core_tpg_register( 5119ac8928eSChristoph Hellwig const struct target_core_fabric_ops *tfo, 512c66ac9dbSNicholas Bellinger struct se_wwn *se_wwn, 513c66ac9dbSNicholas Bellinger struct se_portal_group *se_tpg, 514e4aae5afSChristoph Hellwig int proto_id) 515c66ac9dbSNicholas Bellinger { 5166bb82612SNicholas Bellinger INIT_HLIST_HEAD(&se_tpg->tpg_lun_hlist); 517e4aae5afSChristoph Hellwig se_tpg->proto_id = proto_id; 518c66ac9dbSNicholas Bellinger se_tpg->se_tpg_tfo = tfo; 519c66ac9dbSNicholas Bellinger se_tpg->se_tpg_wwn = se_wwn; 520c66ac9dbSNicholas Bellinger atomic_set(&se_tpg->tpg_pr_ref_count, 0); 521c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&se_tpg->acl_node_list); 522e3d6f909SAndy Grover INIT_LIST_HEAD(&se_tpg->se_tpg_node); 523c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&se_tpg->tpg_sess_list); 524c66ac9dbSNicholas Bellinger spin_lock_init(&se_tpg->session_lock); 5256bb82612SNicholas Bellinger mutex_init(&se_tpg->tpg_lun_mutex); 526403edd78SNicholas Bellinger mutex_init(&se_tpg->acl_node_mutex); 527c66ac9dbSNicholas Bellinger 528e4aae5afSChristoph Hellwig if (se_tpg->proto_id >= 0) { 5296bb82612SNicholas Bellinger if (core_tpg_setup_virtual_lun0(se_tpg) < 0) 530c66ac9dbSNicholas Bellinger return -ENOMEM; 531c66ac9dbSNicholas Bellinger } 532c66ac9dbSNicholas Bellinger 533e3d6f909SAndy Grover spin_lock_bh(&tpg_lock); 534e3d6f909SAndy Grover list_add_tail(&se_tpg->se_tpg_node, &tpg_list); 535e3d6f909SAndy Grover spin_unlock_bh(&tpg_lock); 536c66ac9dbSNicholas Bellinger 537e4aae5afSChristoph Hellwig pr_debug("TARGET_CORE[%s]: Allocated portal_group for endpoint: %s, " 538e4aae5afSChristoph Hellwig "Proto: %d, Portal Tag: %u\n", tfo->get_fabric_name(), 539e4aae5afSChristoph Hellwig tfo->tpg_get_wwn(se_tpg) ? tfo->tpg_get_wwn(se_tpg) : NULL, 540e4aae5afSChristoph Hellwig se_tpg->proto_id, tfo->tpg_get_tag(se_tpg)); 541c66ac9dbSNicholas Bellinger 542c66ac9dbSNicholas Bellinger return 0; 543c66ac9dbSNicholas Bellinger } 544c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_register); 545c66ac9dbSNicholas Bellinger 546c66ac9dbSNicholas Bellinger int core_tpg_deregister(struct se_portal_group *se_tpg) 547c66ac9dbSNicholas Bellinger { 548e4aae5afSChristoph Hellwig const struct target_core_fabric_ops *tfo = se_tpg->se_tpg_tfo; 549e89d15eeSNicholas Bellinger struct se_node_acl *nacl, *nacl_tmp; 55022793de5SNicholas Bellinger LIST_HEAD(node_list); 551e89d15eeSNicholas Bellinger 552e4aae5afSChristoph Hellwig pr_debug("TARGET_CORE[%s]: Deallocating portal_group for endpoint: %s, " 553e4aae5afSChristoph Hellwig "Proto: %d, Portal Tag: %u\n", tfo->get_fabric_name(), 554e4aae5afSChristoph Hellwig tfo->tpg_get_wwn(se_tpg) ? tfo->tpg_get_wwn(se_tpg) : NULL, 555e4aae5afSChristoph Hellwig se_tpg->proto_id, tfo->tpg_get_tag(se_tpg)); 556c66ac9dbSNicholas Bellinger 557e3d6f909SAndy Grover spin_lock_bh(&tpg_lock); 558e3d6f909SAndy Grover list_del(&se_tpg->se_tpg_node); 559e3d6f909SAndy Grover spin_unlock_bh(&tpg_lock); 560c66ac9dbSNicholas Bellinger 561c66ac9dbSNicholas Bellinger while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0) 562c66ac9dbSNicholas Bellinger cpu_relax(); 563403edd78SNicholas Bellinger 56422793de5SNicholas Bellinger mutex_lock(&se_tpg->acl_node_mutex); 56522793de5SNicholas Bellinger list_splice_init(&se_tpg->acl_node_list, &node_list); 56622793de5SNicholas Bellinger mutex_unlock(&se_tpg->acl_node_mutex); 567e89d15eeSNicholas Bellinger /* 568e89d15eeSNicholas Bellinger * Release any remaining demo-mode generated se_node_acl that have 569e89d15eeSNicholas Bellinger * not been released because of TFO->tpg_check_demo_mode_cache() == 1 570e89d15eeSNicholas Bellinger * in transport_deregister_session(). 571e89d15eeSNicholas Bellinger */ 57222793de5SNicholas Bellinger list_for_each_entry_safe(nacl, nacl_tmp, &node_list, acl_list) { 573e89d15eeSNicholas Bellinger list_del(&nacl->acl_list); 574e89d15eeSNicholas Bellinger se_tpg->num_node_acls--; 575e89d15eeSNicholas Bellinger 576e89d15eeSNicholas Bellinger core_tpg_wait_for_nacl_pr_ref(nacl); 577e89d15eeSNicholas Bellinger core_free_device_list_for_node(nacl, se_tpg); 578144bc4c2SChristoph Hellwig kfree(nacl); 579e89d15eeSNicholas Bellinger } 580c66ac9dbSNicholas Bellinger 581e4aae5afSChristoph Hellwig if (se_tpg->proto_id >= 0) 5829c7d6154SAndy Grover core_tpg_remove_lun(se_tpg, &se_tpg->tpg_virt_lun0); 583c66ac9dbSNicholas Bellinger 584c66ac9dbSNicholas Bellinger return 0; 585c66ac9dbSNicholas Bellinger } 586c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_tpg_deregister); 587c66ac9dbSNicholas Bellinger 588d344f8a1SAndy Grover struct se_lun *core_tpg_alloc_lun( 589c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 590c66ac9dbSNicholas Bellinger u32 unpacked_lun) 591c66ac9dbSNicholas Bellinger { 592c66ac9dbSNicholas Bellinger struct se_lun *lun; 593c66ac9dbSNicholas Bellinger 594c66ac9dbSNicholas Bellinger if (unpacked_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) { 5956708bb27SAndy Grover pr_err("%s LUN: %u exceeds TRANSPORT_MAX_LUNS_PER_TPG" 596c66ac9dbSNicholas Bellinger "-1: %u for Target Portal Group: %u\n", 597e3d6f909SAndy Grover tpg->se_tpg_tfo->get_fabric_name(), 598c66ac9dbSNicholas Bellinger unpacked_lun, TRANSPORT_MAX_LUNS_PER_TPG-1, 599e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg)); 600c66ac9dbSNicholas Bellinger return ERR_PTR(-EOVERFLOW); 601c66ac9dbSNicholas Bellinger } 602c66ac9dbSNicholas Bellinger 6036bb82612SNicholas Bellinger lun = kzalloc(sizeof(*lun), GFP_KERNEL); 6046bb82612SNicholas Bellinger if (!lun) { 6056bb82612SNicholas Bellinger pr_err("Unable to allocate se_lun memory\n"); 6066bb82612SNicholas Bellinger return ERR_PTR(-ENOMEM); 607c66ac9dbSNicholas Bellinger } 6086bb82612SNicholas Bellinger lun->unpacked_lun = unpacked_lun; 6096bb82612SNicholas Bellinger lun->lun_link_magic = SE_LUN_LINK_MAGIC; 6106bb82612SNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 6116bb82612SNicholas Bellinger atomic_set(&lun->lun_acl_count, 0); 6126bb82612SNicholas Bellinger init_completion(&lun->lun_shutdown_comp); 6136bb82612SNicholas Bellinger INIT_LIST_HEAD(&lun->lun_acl_list); 6146bb82612SNicholas Bellinger spin_lock_init(&lun->lun_acl_lock); 6156bb82612SNicholas Bellinger spin_lock_init(&lun->lun_sep_lock); 6166bb82612SNicholas Bellinger init_completion(&lun->lun_ref_comp); 617c66ac9dbSNicholas Bellinger 618c66ac9dbSNicholas Bellinger return lun; 619c66ac9dbSNicholas Bellinger } 620c66ac9dbSNicholas Bellinger 621d344f8a1SAndy Grover int core_tpg_add_lun( 622c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 623c66ac9dbSNicholas Bellinger struct se_lun *lun, 624c66ac9dbSNicholas Bellinger u32 lun_access, 625340dbf72SAndy Grover struct se_device *dev) 626c66ac9dbSNicholas Bellinger { 627e3d6f909SAndy Grover int ret; 628e3d6f909SAndy Grover 6292aad2a86STejun Heo ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release, 0, 630a34375efSTejun Heo GFP_KERNEL); 631e3d6f909SAndy Grover if (ret < 0) 632e3d6f909SAndy Grover return ret; 633c66ac9dbSNicholas Bellinger 634340dbf72SAndy Grover ret = core_dev_export(dev, tpg, lun); 6355277797dSNicholas Bellinger if (ret < 0) { 6369a1049daSTejun Heo percpu_ref_exit(&lun->lun_ref); 6375277797dSNicholas Bellinger return ret; 6385277797dSNicholas Bellinger } 6395277797dSNicholas Bellinger 6406bb82612SNicholas Bellinger mutex_lock(&tpg->tpg_lun_mutex); 641c66ac9dbSNicholas Bellinger lun->lun_access = lun_access; 642c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_ACTIVE; 6436bb82612SNicholas Bellinger if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) 6446bb82612SNicholas Bellinger hlist_add_head_rcu(&lun->link, &tpg->tpg_lun_hlist); 6456bb82612SNicholas Bellinger mutex_unlock(&tpg->tpg_lun_mutex); 646c66ac9dbSNicholas Bellinger 647c66ac9dbSNicholas Bellinger return 0; 648c66ac9dbSNicholas Bellinger } 649c66ac9dbSNicholas Bellinger 650cd9d7cbaSAndy Grover void core_tpg_remove_lun( 651c66ac9dbSNicholas Bellinger struct se_portal_group *tpg, 652c66ac9dbSNicholas Bellinger struct se_lun *lun) 653c66ac9dbSNicholas Bellinger { 6546bb82612SNicholas Bellinger struct se_device *dev = lun->lun_se_dev; 6556bb82612SNicholas Bellinger 6564a9a6c8dSNicholas Bellinger core_clear_lun_from_tpg(lun, tpg); 6574a9a6c8dSNicholas Bellinger transport_clear_lun_ref(lun); 658c66ac9dbSNicholas Bellinger 659c66ac9dbSNicholas Bellinger core_dev_unexport(lun->lun_se_dev, tpg, lun); 660c66ac9dbSNicholas Bellinger 6616bb82612SNicholas Bellinger mutex_lock(&tpg->tpg_lun_mutex); 662c66ac9dbSNicholas Bellinger lun->lun_status = TRANSPORT_LUN_STATUS_FREE; 6636bb82612SNicholas Bellinger if (!(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) 6646bb82612SNicholas Bellinger hlist_del_rcu(&lun->link); 6656bb82612SNicholas Bellinger mutex_unlock(&tpg->tpg_lun_mutex); 666c66ac9dbSNicholas Bellinger 6679a1049daSTejun Heo percpu_ref_exit(&lun->lun_ref); 668c66ac9dbSNicholas Bellinger } 669