1c66ac9dbSNicholas Bellinger /******************************************************************************* 2c66ac9dbSNicholas Bellinger * Filename: target_core_alua.c 3c66ac9dbSNicholas Bellinger * 4c66ac9dbSNicholas Bellinger * This file contains SPC-3 compliant asymmetric logical unit assigntment (ALUA) 5c66ac9dbSNicholas Bellinger * 6c66ac9dbSNicholas Bellinger * Copyright (c) 2009-2010 Rising Tide Systems 7c66ac9dbSNicholas Bellinger * Copyright (c) 2009-2010 Linux-iSCSI.org 8c66ac9dbSNicholas Bellinger * 9c66ac9dbSNicholas Bellinger * Nicholas A. Bellinger <nab@kernel.org> 10c66ac9dbSNicholas Bellinger * 11c66ac9dbSNicholas Bellinger * This program is free software; you can redistribute it and/or modify 12c66ac9dbSNicholas Bellinger * it under the terms of the GNU General Public License as published by 13c66ac9dbSNicholas Bellinger * the Free Software Foundation; either version 2 of the License, or 14c66ac9dbSNicholas Bellinger * (at your option) any later version. 15c66ac9dbSNicholas Bellinger * 16c66ac9dbSNicholas Bellinger * This program is distributed in the hope that it will be useful, 17c66ac9dbSNicholas Bellinger * but WITHOUT ANY WARRANTY; without even the implied warranty of 18c66ac9dbSNicholas Bellinger * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19c66ac9dbSNicholas Bellinger * GNU General Public License for more details. 20c66ac9dbSNicholas Bellinger * 21c66ac9dbSNicholas Bellinger * You should have received a copy of the GNU General Public License 22c66ac9dbSNicholas Bellinger * along with this program; if not, write to the Free Software 23c66ac9dbSNicholas Bellinger * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 24c66ac9dbSNicholas Bellinger * 25c66ac9dbSNicholas Bellinger ******************************************************************************/ 26c66ac9dbSNicholas Bellinger 27c66ac9dbSNicholas Bellinger #include <linux/version.h> 28c66ac9dbSNicholas Bellinger #include <linux/slab.h> 29c66ac9dbSNicholas Bellinger #include <linux/spinlock.h> 30c66ac9dbSNicholas Bellinger #include <linux/configfs.h> 31c66ac9dbSNicholas Bellinger #include <scsi/scsi.h> 32c66ac9dbSNicholas Bellinger #include <scsi/scsi_cmnd.h> 33c66ac9dbSNicholas Bellinger 34c66ac9dbSNicholas Bellinger #include <target/target_core_base.h> 35c66ac9dbSNicholas Bellinger #include <target/target_core_device.h> 36c66ac9dbSNicholas Bellinger #include <target/target_core_transport.h> 37c66ac9dbSNicholas Bellinger #include <target/target_core_fabric_ops.h> 38c66ac9dbSNicholas Bellinger #include <target/target_core_configfs.h> 39c66ac9dbSNicholas Bellinger 40c66ac9dbSNicholas Bellinger #include "target_core_alua.h" 41c66ac9dbSNicholas Bellinger #include "target_core_hba.h" 42c66ac9dbSNicholas Bellinger #include "target_core_ua.h" 43c66ac9dbSNicholas Bellinger 44c66ac9dbSNicholas Bellinger static int core_alua_check_transition(int state, int *primary); 45c66ac9dbSNicholas Bellinger static int core_alua_set_tg_pt_secondary_state( 46c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 47c66ac9dbSNicholas Bellinger struct se_port *port, int explict, int offline); 48c66ac9dbSNicholas Bellinger 49e3d6f909SAndy Grover static u16 alua_lu_gps_counter; 50e3d6f909SAndy Grover static u32 alua_lu_gps_count; 51e3d6f909SAndy Grover 52e3d6f909SAndy Grover static DEFINE_SPINLOCK(lu_gps_lock); 53e3d6f909SAndy Grover static LIST_HEAD(lu_gps_list); 54e3d6f909SAndy Grover 55e3d6f909SAndy Grover struct t10_alua_lu_gp *default_lu_gp; 56e3d6f909SAndy Grover 57c66ac9dbSNicholas Bellinger /* 58c66ac9dbSNicholas Bellinger * REPORT_TARGET_PORT_GROUPS 59c66ac9dbSNicholas Bellinger * 60c66ac9dbSNicholas Bellinger * See spc4r17 section 6.27 61c66ac9dbSNicholas Bellinger */ 62c66ac9dbSNicholas Bellinger int core_emulate_report_target_port_groups(struct se_cmd *cmd) 63c66ac9dbSNicholas Bellinger { 645951146dSAndy Grover struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev; 65c66ac9dbSNicholas Bellinger struct se_port *port; 66c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 67c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 6805d1c7c0SAndy Grover unsigned char *buf; 69c66ac9dbSNicholas Bellinger u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first 70c66ac9dbSNicholas Bellinger Target port group descriptor */ 71c66ac9dbSNicholas Bellinger 7205d1c7c0SAndy Grover buf = transport_kmap_first_data_page(cmd); 7305d1c7c0SAndy Grover 74e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 75e3d6f909SAndy Grover list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, 76c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 77c66ac9dbSNicholas Bellinger /* 78c66ac9dbSNicholas Bellinger * PREF: Preferred target port bit, determine if this 79c66ac9dbSNicholas Bellinger * bit should be set for port group. 80c66ac9dbSNicholas Bellinger */ 81c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_pref) 82c66ac9dbSNicholas Bellinger buf[off] = 0x80; 83c66ac9dbSNicholas Bellinger /* 84c66ac9dbSNicholas Bellinger * Set the ASYMMETRIC ACCESS State 85c66ac9dbSNicholas Bellinger */ 86c66ac9dbSNicholas Bellinger buf[off++] |= (atomic_read( 87c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_alua_access_state) & 0xff); 88c66ac9dbSNicholas Bellinger /* 89c66ac9dbSNicholas Bellinger * Set supported ASYMMETRIC ACCESS State bits 90c66ac9dbSNicholas Bellinger */ 91c66ac9dbSNicholas Bellinger buf[off] = 0x80; /* T_SUP */ 92c66ac9dbSNicholas Bellinger buf[off] |= 0x40; /* O_SUP */ 93c66ac9dbSNicholas Bellinger buf[off] |= 0x8; /* U_SUP */ 94c66ac9dbSNicholas Bellinger buf[off] |= 0x4; /* S_SUP */ 95c66ac9dbSNicholas Bellinger buf[off] |= 0x2; /* AN_SUP */ 96c66ac9dbSNicholas Bellinger buf[off++] |= 0x1; /* AO_SUP */ 97c66ac9dbSNicholas Bellinger /* 98c66ac9dbSNicholas Bellinger * TARGET PORT GROUP 99c66ac9dbSNicholas Bellinger */ 100c66ac9dbSNicholas Bellinger buf[off++] = ((tg_pt_gp->tg_pt_gp_id >> 8) & 0xff); 101c66ac9dbSNicholas Bellinger buf[off++] = (tg_pt_gp->tg_pt_gp_id & 0xff); 102c66ac9dbSNicholas Bellinger 103c66ac9dbSNicholas Bellinger off++; /* Skip over Reserved */ 104c66ac9dbSNicholas Bellinger /* 105c66ac9dbSNicholas Bellinger * STATUS CODE 106c66ac9dbSNicholas Bellinger */ 107c66ac9dbSNicholas Bellinger buf[off++] = (tg_pt_gp->tg_pt_gp_alua_access_status & 0xff); 108c66ac9dbSNicholas Bellinger /* 109c66ac9dbSNicholas Bellinger * Vendor Specific field 110c66ac9dbSNicholas Bellinger */ 111c66ac9dbSNicholas Bellinger buf[off++] = 0x00; 112c66ac9dbSNicholas Bellinger /* 113c66ac9dbSNicholas Bellinger * TARGET PORT COUNT 114c66ac9dbSNicholas Bellinger */ 115c66ac9dbSNicholas Bellinger buf[off++] = (tg_pt_gp->tg_pt_gp_members & 0xff); 116c66ac9dbSNicholas Bellinger rd_len += 8; 117c66ac9dbSNicholas Bellinger 118c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 119c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp_mem, &tg_pt_gp->tg_pt_gp_mem_list, 120c66ac9dbSNicholas Bellinger tg_pt_gp_mem_list) { 121c66ac9dbSNicholas Bellinger port = tg_pt_gp_mem->tg_pt; 122c66ac9dbSNicholas Bellinger /* 123c66ac9dbSNicholas Bellinger * Start Target Port descriptor format 124c66ac9dbSNicholas Bellinger * 125c66ac9dbSNicholas Bellinger * See spc4r17 section 6.2.7 Table 247 126c66ac9dbSNicholas Bellinger */ 127c66ac9dbSNicholas Bellinger off += 2; /* Skip over Obsolete */ 128c66ac9dbSNicholas Bellinger /* 129c66ac9dbSNicholas Bellinger * Set RELATIVE TARGET PORT IDENTIFIER 130c66ac9dbSNicholas Bellinger */ 131c66ac9dbSNicholas Bellinger buf[off++] = ((port->sep_rtpi >> 8) & 0xff); 132c66ac9dbSNicholas Bellinger buf[off++] = (port->sep_rtpi & 0xff); 133c66ac9dbSNicholas Bellinger rd_len += 4; 134c66ac9dbSNicholas Bellinger } 135c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 136c66ac9dbSNicholas Bellinger } 137e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 138c66ac9dbSNicholas Bellinger /* 139c66ac9dbSNicholas Bellinger * Set the RETURN DATA LENGTH set in the header of the DataIN Payload 140c66ac9dbSNicholas Bellinger */ 141c66ac9dbSNicholas Bellinger buf[0] = ((rd_len >> 24) & 0xff); 142c66ac9dbSNicholas Bellinger buf[1] = ((rd_len >> 16) & 0xff); 143c66ac9dbSNicholas Bellinger buf[2] = ((rd_len >> 8) & 0xff); 144c66ac9dbSNicholas Bellinger buf[3] = (rd_len & 0xff); 145c66ac9dbSNicholas Bellinger 14605d1c7c0SAndy Grover transport_kunmap_first_data_page(cmd); 14705d1c7c0SAndy Grover 148c66ac9dbSNicholas Bellinger return 0; 149c66ac9dbSNicholas Bellinger } 150c66ac9dbSNicholas Bellinger 151c66ac9dbSNicholas Bellinger /* 152c66ac9dbSNicholas Bellinger * SET_TARGET_PORT_GROUPS for explict ALUA operation. 153c66ac9dbSNicholas Bellinger * 154c66ac9dbSNicholas Bellinger * See spc4r17 section 6.35 155c66ac9dbSNicholas Bellinger */ 156c66ac9dbSNicholas Bellinger int core_emulate_set_target_port_groups(struct se_cmd *cmd) 157c66ac9dbSNicholas Bellinger { 1585951146dSAndy Grover struct se_device *dev = cmd->se_dev; 159e3d6f909SAndy Grover struct se_subsystem_dev *su_dev = dev->se_sub_dev; 160e3d6f909SAndy Grover struct se_port *port, *l_port = cmd->se_lun->lun_sep; 161e3d6f909SAndy Grover struct se_node_acl *nacl = cmd->se_sess->se_node_acl; 162c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp; 163c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; 16405d1c7c0SAndy Grover unsigned char *buf; 16505d1c7c0SAndy Grover unsigned char *ptr; 166c66ac9dbSNicholas Bellinger u32 len = 4; /* Skip over RESERVED area in header */ 167c66ac9dbSNicholas Bellinger int alua_access_state, primary = 0, rc; 168c66ac9dbSNicholas Bellinger u16 tg_pt_id, rtpi; 169c66ac9dbSNicholas Bellinger 170c66ac9dbSNicholas Bellinger if (!(l_port)) 171c66ac9dbSNicholas Bellinger return PYX_TRANSPORT_LU_COMM_FAILURE; 17205d1c7c0SAndy Grover 17305d1c7c0SAndy Grover buf = transport_kmap_first_data_page(cmd); 17405d1c7c0SAndy Grover 175c66ac9dbSNicholas Bellinger /* 176c66ac9dbSNicholas Bellinger * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed 177c66ac9dbSNicholas Bellinger * for the local tg_pt_gp. 178c66ac9dbSNicholas Bellinger */ 179c66ac9dbSNicholas Bellinger l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; 180c66ac9dbSNicholas Bellinger if (!(l_tg_pt_gp_mem)) { 181c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); 18205d1c7c0SAndy Grover rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; 18305d1c7c0SAndy Grover goto out; 184c66ac9dbSNicholas Bellinger } 185c66ac9dbSNicholas Bellinger spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 186c66ac9dbSNicholas Bellinger l_tg_pt_gp = l_tg_pt_gp_mem->tg_pt_gp; 187c66ac9dbSNicholas Bellinger if (!(l_tg_pt_gp)) { 188c66ac9dbSNicholas Bellinger spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 189c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); 19005d1c7c0SAndy Grover rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; 19105d1c7c0SAndy Grover goto out; 192c66ac9dbSNicholas Bellinger } 193c66ac9dbSNicholas Bellinger rc = (l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA); 194c66ac9dbSNicholas Bellinger spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 195c66ac9dbSNicholas Bellinger 196c66ac9dbSNicholas Bellinger if (!(rc)) { 197c66ac9dbSNicholas Bellinger printk(KERN_INFO "Unable to process SET_TARGET_PORT_GROUPS" 198c66ac9dbSNicholas Bellinger " while TPGS_EXPLICT_ALUA is disabled\n"); 19905d1c7c0SAndy Grover rc = PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; 20005d1c7c0SAndy Grover goto out; 201c66ac9dbSNicholas Bellinger } 202c66ac9dbSNicholas Bellinger 20305d1c7c0SAndy Grover ptr = &buf[4]; /* Skip over RESERVED area in header */ 20405d1c7c0SAndy Grover 205c66ac9dbSNicholas Bellinger while (len < cmd->data_length) { 206c66ac9dbSNicholas Bellinger alua_access_state = (ptr[0] & 0x0f); 207c66ac9dbSNicholas Bellinger /* 208c66ac9dbSNicholas Bellinger * Check the received ALUA access state, and determine if 209c66ac9dbSNicholas Bellinger * the state is a primary or secondary target port asymmetric 210c66ac9dbSNicholas Bellinger * access state. 211c66ac9dbSNicholas Bellinger */ 212c66ac9dbSNicholas Bellinger rc = core_alua_check_transition(alua_access_state, &primary); 213c66ac9dbSNicholas Bellinger if (rc != 0) { 214c66ac9dbSNicholas Bellinger /* 215c66ac9dbSNicholas Bellinger * If the SET TARGET PORT GROUPS attempts to establish 216c66ac9dbSNicholas Bellinger * an invalid combination of target port asymmetric 217c66ac9dbSNicholas Bellinger * access states or attempts to establish an 218c66ac9dbSNicholas Bellinger * unsupported target port asymmetric access state, 219c66ac9dbSNicholas Bellinger * then the command shall be terminated with CHECK 220c66ac9dbSNicholas Bellinger * CONDITION status, with the sense key set to ILLEGAL 221c66ac9dbSNicholas Bellinger * REQUEST, and the additional sense code set to INVALID 222c66ac9dbSNicholas Bellinger * FIELD IN PARAMETER LIST. 223c66ac9dbSNicholas Bellinger */ 22405d1c7c0SAndy Grover rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST; 22505d1c7c0SAndy Grover goto out; 226c66ac9dbSNicholas Bellinger } 227c66ac9dbSNicholas Bellinger rc = -1; 228c66ac9dbSNicholas Bellinger /* 229c66ac9dbSNicholas Bellinger * If the ASYMMETRIC ACCESS STATE field (see table 267) 230c66ac9dbSNicholas Bellinger * specifies a primary target port asymmetric access state, 231c66ac9dbSNicholas Bellinger * then the TARGET PORT GROUP OR TARGET PORT field specifies 232c66ac9dbSNicholas Bellinger * a primary target port group for which the primary target 233c66ac9dbSNicholas Bellinger * port asymmetric access state shall be changed. If the 234c66ac9dbSNicholas Bellinger * ASYMMETRIC ACCESS STATE field specifies a secondary target 235c66ac9dbSNicholas Bellinger * port asymmetric access state, then the TARGET PORT GROUP OR 236c66ac9dbSNicholas Bellinger * TARGET PORT field specifies the relative target port 237c66ac9dbSNicholas Bellinger * identifier (see 3.1.120) of the target port for which the 238c66ac9dbSNicholas Bellinger * secondary target port asymmetric access state shall be 239c66ac9dbSNicholas Bellinger * changed. 240c66ac9dbSNicholas Bellinger */ 241c66ac9dbSNicholas Bellinger if (primary) { 242c66ac9dbSNicholas Bellinger tg_pt_id = ((ptr[2] << 8) & 0xff); 243c66ac9dbSNicholas Bellinger tg_pt_id |= (ptr[3] & 0xff); 244c66ac9dbSNicholas Bellinger /* 245c66ac9dbSNicholas Bellinger * Locate the matching target port group ID from 246c66ac9dbSNicholas Bellinger * the global tg_pt_gp list 247c66ac9dbSNicholas Bellinger */ 248e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 249c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp, 250e3d6f909SAndy Grover &su_dev->t10_alua.tg_pt_gps_list, 251c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 252c66ac9dbSNicholas Bellinger if (!(tg_pt_gp->tg_pt_gp_valid_id)) 253c66ac9dbSNicholas Bellinger continue; 254c66ac9dbSNicholas Bellinger 255c66ac9dbSNicholas Bellinger if (tg_pt_id != tg_pt_gp->tg_pt_gp_id) 256c66ac9dbSNicholas Bellinger continue; 257c66ac9dbSNicholas Bellinger 258c66ac9dbSNicholas Bellinger atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 259c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 260e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 261c66ac9dbSNicholas Bellinger 262c66ac9dbSNicholas Bellinger rc = core_alua_do_port_transition(tg_pt_gp, 263c66ac9dbSNicholas Bellinger dev, l_port, nacl, 264c66ac9dbSNicholas Bellinger alua_access_state, 1); 265c66ac9dbSNicholas Bellinger 266e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 267c66ac9dbSNicholas Bellinger atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 268c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 269c66ac9dbSNicholas Bellinger break; 270c66ac9dbSNicholas Bellinger } 271e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 272c66ac9dbSNicholas Bellinger /* 273c66ac9dbSNicholas Bellinger * If not matching target port group ID can be located 274c66ac9dbSNicholas Bellinger * throw an exception with ASCQ: INVALID_PARAMETER_LIST 275c66ac9dbSNicholas Bellinger */ 27605d1c7c0SAndy Grover if (rc != 0) { 27705d1c7c0SAndy Grover rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST; 27805d1c7c0SAndy Grover goto out; 27905d1c7c0SAndy Grover } 280c66ac9dbSNicholas Bellinger } else { 281c66ac9dbSNicholas Bellinger /* 282c66ac9dbSNicholas Bellinger * Extact the RELATIVE TARGET PORT IDENTIFIER to identify 283c66ac9dbSNicholas Bellinger * the Target Port in question for the the incoming 284c66ac9dbSNicholas Bellinger * SET_TARGET_PORT_GROUPS op. 285c66ac9dbSNicholas Bellinger */ 286c66ac9dbSNicholas Bellinger rtpi = ((ptr[2] << 8) & 0xff); 287c66ac9dbSNicholas Bellinger rtpi |= (ptr[3] & 0xff); 288c66ac9dbSNicholas Bellinger /* 289c66ac9dbSNicholas Bellinger * Locate the matching relative target port identifer 290c66ac9dbSNicholas Bellinger * for the struct se_device storage object. 291c66ac9dbSNicholas Bellinger */ 292c66ac9dbSNicholas Bellinger spin_lock(&dev->se_port_lock); 293c66ac9dbSNicholas Bellinger list_for_each_entry(port, &dev->dev_sep_list, 294c66ac9dbSNicholas Bellinger sep_list) { 295c66ac9dbSNicholas Bellinger if (port->sep_rtpi != rtpi) 296c66ac9dbSNicholas Bellinger continue; 297c66ac9dbSNicholas Bellinger 298c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 299c66ac9dbSNicholas Bellinger spin_unlock(&dev->se_port_lock); 300c66ac9dbSNicholas Bellinger 301c66ac9dbSNicholas Bellinger rc = core_alua_set_tg_pt_secondary_state( 302c66ac9dbSNicholas Bellinger tg_pt_gp_mem, port, 1, 1); 303c66ac9dbSNicholas Bellinger 304c66ac9dbSNicholas Bellinger spin_lock(&dev->se_port_lock); 305c66ac9dbSNicholas Bellinger break; 306c66ac9dbSNicholas Bellinger } 307c66ac9dbSNicholas Bellinger spin_unlock(&dev->se_port_lock); 308c66ac9dbSNicholas Bellinger /* 309c66ac9dbSNicholas Bellinger * If not matching relative target port identifier can 310c66ac9dbSNicholas Bellinger * be located, throw an exception with ASCQ: 311c66ac9dbSNicholas Bellinger * INVALID_PARAMETER_LIST 312c66ac9dbSNicholas Bellinger */ 31305d1c7c0SAndy Grover if (rc != 0) { 31405d1c7c0SAndy Grover rc = PYX_TRANSPORT_INVALID_PARAMETER_LIST; 31505d1c7c0SAndy Grover goto out; 31605d1c7c0SAndy Grover } 317c66ac9dbSNicholas Bellinger } 318c66ac9dbSNicholas Bellinger 319c66ac9dbSNicholas Bellinger ptr += 4; 320c66ac9dbSNicholas Bellinger len += 4; 321c66ac9dbSNicholas Bellinger } 322c66ac9dbSNicholas Bellinger 32305d1c7c0SAndy Grover out: 32405d1c7c0SAndy Grover transport_kunmap_first_data_page(cmd); 32505d1c7c0SAndy Grover 326c66ac9dbSNicholas Bellinger return 0; 327c66ac9dbSNicholas Bellinger } 328c66ac9dbSNicholas Bellinger 329c66ac9dbSNicholas Bellinger static inline int core_alua_state_nonoptimized( 330c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 331c66ac9dbSNicholas Bellinger unsigned char *cdb, 332c66ac9dbSNicholas Bellinger int nonop_delay_msecs, 333c66ac9dbSNicholas Bellinger u8 *alua_ascq) 334c66ac9dbSNicholas Bellinger { 335c66ac9dbSNicholas Bellinger /* 336c66ac9dbSNicholas Bellinger * Set SCF_ALUA_NON_OPTIMIZED here, this value will be checked 337c66ac9dbSNicholas Bellinger * later to determine if processing of this cmd needs to be 338c66ac9dbSNicholas Bellinger * temporarily delayed for the Active/NonOptimized primary access state. 339c66ac9dbSNicholas Bellinger */ 340c66ac9dbSNicholas Bellinger cmd->se_cmd_flags |= SCF_ALUA_NON_OPTIMIZED; 341c66ac9dbSNicholas Bellinger cmd->alua_nonop_delay = nonop_delay_msecs; 342c66ac9dbSNicholas Bellinger return 0; 343c66ac9dbSNicholas Bellinger } 344c66ac9dbSNicholas Bellinger 345c66ac9dbSNicholas Bellinger static inline int core_alua_state_standby( 346c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 347c66ac9dbSNicholas Bellinger unsigned char *cdb, 348c66ac9dbSNicholas Bellinger u8 *alua_ascq) 349c66ac9dbSNicholas Bellinger { 350c66ac9dbSNicholas Bellinger /* 351c66ac9dbSNicholas Bellinger * Allowed CDBs for ALUA_ACCESS_STATE_STANDBY as defined by 352c66ac9dbSNicholas Bellinger * spc4r17 section 5.9.2.4.4 353c66ac9dbSNicholas Bellinger */ 354c66ac9dbSNicholas Bellinger switch (cdb[0]) { 355c66ac9dbSNicholas Bellinger case INQUIRY: 356c66ac9dbSNicholas Bellinger case LOG_SELECT: 357c66ac9dbSNicholas Bellinger case LOG_SENSE: 358c66ac9dbSNicholas Bellinger case MODE_SELECT: 359c66ac9dbSNicholas Bellinger case MODE_SENSE: 360c66ac9dbSNicholas Bellinger case REPORT_LUNS: 361c66ac9dbSNicholas Bellinger case RECEIVE_DIAGNOSTIC: 362c66ac9dbSNicholas Bellinger case SEND_DIAGNOSTIC: 363c66ac9dbSNicholas Bellinger case MAINTENANCE_IN: 364c66ac9dbSNicholas Bellinger switch (cdb[1]) { 365c66ac9dbSNicholas Bellinger case MI_REPORT_TARGET_PGS: 366c66ac9dbSNicholas Bellinger return 0; 367c66ac9dbSNicholas Bellinger default: 368c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 369c66ac9dbSNicholas Bellinger return 1; 370c66ac9dbSNicholas Bellinger } 371c66ac9dbSNicholas Bellinger case MAINTENANCE_OUT: 372c66ac9dbSNicholas Bellinger switch (cdb[1]) { 373c66ac9dbSNicholas Bellinger case MO_SET_TARGET_PGS: 374c66ac9dbSNicholas Bellinger return 0; 375c66ac9dbSNicholas Bellinger default: 376c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 377c66ac9dbSNicholas Bellinger return 1; 378c66ac9dbSNicholas Bellinger } 379c66ac9dbSNicholas Bellinger case REQUEST_SENSE: 380c66ac9dbSNicholas Bellinger case PERSISTENT_RESERVE_IN: 381c66ac9dbSNicholas Bellinger case PERSISTENT_RESERVE_OUT: 382c66ac9dbSNicholas Bellinger case READ_BUFFER: 383c66ac9dbSNicholas Bellinger case WRITE_BUFFER: 384c66ac9dbSNicholas Bellinger return 0; 385c66ac9dbSNicholas Bellinger default: 386c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 387c66ac9dbSNicholas Bellinger return 1; 388c66ac9dbSNicholas Bellinger } 389c66ac9dbSNicholas Bellinger 390c66ac9dbSNicholas Bellinger return 0; 391c66ac9dbSNicholas Bellinger } 392c66ac9dbSNicholas Bellinger 393c66ac9dbSNicholas Bellinger static inline int core_alua_state_unavailable( 394c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 395c66ac9dbSNicholas Bellinger unsigned char *cdb, 396c66ac9dbSNicholas Bellinger u8 *alua_ascq) 397c66ac9dbSNicholas Bellinger { 398c66ac9dbSNicholas Bellinger /* 399c66ac9dbSNicholas Bellinger * Allowed CDBs for ALUA_ACCESS_STATE_UNAVAILABLE as defined by 400c66ac9dbSNicholas Bellinger * spc4r17 section 5.9.2.4.5 401c66ac9dbSNicholas Bellinger */ 402c66ac9dbSNicholas Bellinger switch (cdb[0]) { 403c66ac9dbSNicholas Bellinger case INQUIRY: 404c66ac9dbSNicholas Bellinger case REPORT_LUNS: 405c66ac9dbSNicholas Bellinger case MAINTENANCE_IN: 406c66ac9dbSNicholas Bellinger switch (cdb[1]) { 407c66ac9dbSNicholas Bellinger case MI_REPORT_TARGET_PGS: 408c66ac9dbSNicholas Bellinger return 0; 409c66ac9dbSNicholas Bellinger default: 410c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 411c66ac9dbSNicholas Bellinger return 1; 412c66ac9dbSNicholas Bellinger } 413c66ac9dbSNicholas Bellinger case MAINTENANCE_OUT: 414c66ac9dbSNicholas Bellinger switch (cdb[1]) { 415c66ac9dbSNicholas Bellinger case MO_SET_TARGET_PGS: 416c66ac9dbSNicholas Bellinger return 0; 417c66ac9dbSNicholas Bellinger default: 418c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 419c66ac9dbSNicholas Bellinger return 1; 420c66ac9dbSNicholas Bellinger } 421c66ac9dbSNicholas Bellinger case REQUEST_SENSE: 422c66ac9dbSNicholas Bellinger case READ_BUFFER: 423c66ac9dbSNicholas Bellinger case WRITE_BUFFER: 424c66ac9dbSNicholas Bellinger return 0; 425c66ac9dbSNicholas Bellinger default: 426c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 427c66ac9dbSNicholas Bellinger return 1; 428c66ac9dbSNicholas Bellinger } 429c66ac9dbSNicholas Bellinger 430c66ac9dbSNicholas Bellinger return 0; 431c66ac9dbSNicholas Bellinger } 432c66ac9dbSNicholas Bellinger 433c66ac9dbSNicholas Bellinger static inline int core_alua_state_transition( 434c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 435c66ac9dbSNicholas Bellinger unsigned char *cdb, 436c66ac9dbSNicholas Bellinger u8 *alua_ascq) 437c66ac9dbSNicholas Bellinger { 438c66ac9dbSNicholas Bellinger /* 439c66ac9dbSNicholas Bellinger * Allowed CDBs for ALUA_ACCESS_STATE_TRANSITIO as defined by 440c66ac9dbSNicholas Bellinger * spc4r17 section 5.9.2.5 441c66ac9dbSNicholas Bellinger */ 442c66ac9dbSNicholas Bellinger switch (cdb[0]) { 443c66ac9dbSNicholas Bellinger case INQUIRY: 444c66ac9dbSNicholas Bellinger case REPORT_LUNS: 445c66ac9dbSNicholas Bellinger case MAINTENANCE_IN: 446c66ac9dbSNicholas Bellinger switch (cdb[1]) { 447c66ac9dbSNicholas Bellinger case MI_REPORT_TARGET_PGS: 448c66ac9dbSNicholas Bellinger return 0; 449c66ac9dbSNicholas Bellinger default: 450c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_STATE_TRANSITION; 451c66ac9dbSNicholas Bellinger return 1; 452c66ac9dbSNicholas Bellinger } 453c66ac9dbSNicholas Bellinger case REQUEST_SENSE: 454c66ac9dbSNicholas Bellinger case READ_BUFFER: 455c66ac9dbSNicholas Bellinger case WRITE_BUFFER: 456c66ac9dbSNicholas Bellinger return 0; 457c66ac9dbSNicholas Bellinger default: 458c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_STATE_TRANSITION; 459c66ac9dbSNicholas Bellinger return 1; 460c66ac9dbSNicholas Bellinger } 461c66ac9dbSNicholas Bellinger 462c66ac9dbSNicholas Bellinger return 0; 463c66ac9dbSNicholas Bellinger } 464c66ac9dbSNicholas Bellinger 465c66ac9dbSNicholas Bellinger /* 466c66ac9dbSNicholas Bellinger * Used for alua_type SPC_ALUA_PASSTHROUGH and SPC2_ALUA_DISABLED 467c66ac9dbSNicholas Bellinger * in transport_cmd_sequencer(). This function is assigned to 468c66ac9dbSNicholas Bellinger * struct t10_alua *->state_check() in core_setup_alua() 469c66ac9dbSNicholas Bellinger */ 470c66ac9dbSNicholas Bellinger static int core_alua_state_check_nop( 471c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 472c66ac9dbSNicholas Bellinger unsigned char *cdb, 473c66ac9dbSNicholas Bellinger u8 *alua_ascq) 474c66ac9dbSNicholas Bellinger { 475c66ac9dbSNicholas Bellinger return 0; 476c66ac9dbSNicholas Bellinger } 477c66ac9dbSNicholas Bellinger 478c66ac9dbSNicholas Bellinger /* 479c66ac9dbSNicholas Bellinger * Used for alua_type SPC3_ALUA_EMULATED in transport_cmd_sequencer(). 480c66ac9dbSNicholas Bellinger * This function is assigned to struct t10_alua *->state_check() in 481c66ac9dbSNicholas Bellinger * core_setup_alua() 482c66ac9dbSNicholas Bellinger * 483c66ac9dbSNicholas Bellinger * Also, this function can return three different return codes to 484c66ac9dbSNicholas Bellinger * signal transport_generic_cmd_sequencer() 485c66ac9dbSNicholas Bellinger * 486c66ac9dbSNicholas Bellinger * return 1: Is used to signal LUN not accecsable, and check condition/not ready 487c66ac9dbSNicholas Bellinger * return 0: Used to signal success 488c66ac9dbSNicholas Bellinger * reutrn -1: Used to signal failure, and invalid cdb field 489c66ac9dbSNicholas Bellinger */ 490c66ac9dbSNicholas Bellinger static int core_alua_state_check( 491c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 492c66ac9dbSNicholas Bellinger unsigned char *cdb, 493c66ac9dbSNicholas Bellinger u8 *alua_ascq) 494c66ac9dbSNicholas Bellinger { 495e3d6f909SAndy Grover struct se_lun *lun = cmd->se_lun; 496c66ac9dbSNicholas Bellinger struct se_port *port = lun->lun_sep; 497c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 498c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 499c66ac9dbSNicholas Bellinger int out_alua_state, nonop_delay_msecs; 500c66ac9dbSNicholas Bellinger 501c66ac9dbSNicholas Bellinger if (!(port)) 502c66ac9dbSNicholas Bellinger return 0; 503c66ac9dbSNicholas Bellinger /* 504c66ac9dbSNicholas Bellinger * First, check for a struct se_port specific secondary ALUA target port 505c66ac9dbSNicholas Bellinger * access state: OFFLINE 506c66ac9dbSNicholas Bellinger */ 507c66ac9dbSNicholas Bellinger if (atomic_read(&port->sep_tg_pt_secondary_offline)) { 508c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_OFFLINE; 509c66ac9dbSNicholas Bellinger printk(KERN_INFO "ALUA: Got secondary offline status for local" 510c66ac9dbSNicholas Bellinger " target port\n"); 511c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_OFFLINE; 512c66ac9dbSNicholas Bellinger return 1; 513c66ac9dbSNicholas Bellinger } 514c66ac9dbSNicholas Bellinger /* 515c66ac9dbSNicholas Bellinger * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the 516c66ac9dbSNicholas Bellinger * ALUA target port group, to obtain current ALUA access state. 517c66ac9dbSNicholas Bellinger * Otherwise look for the underlying struct se_device association with 518c66ac9dbSNicholas Bellinger * a ALUA logical unit group. 519c66ac9dbSNicholas Bellinger */ 520c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 521c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 522c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 523c66ac9dbSNicholas Bellinger out_alua_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); 524c66ac9dbSNicholas Bellinger nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs; 525c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 526c66ac9dbSNicholas Bellinger /* 52725985edcSLucas De Marchi * Process ALUA_ACCESS_STATE_ACTIVE_OPTMIZED in a separate conditional 52825985edcSLucas De Marchi * statement so the compiler knows explicitly to check this case first. 529c66ac9dbSNicholas Bellinger * For the Optimized ALUA access state case, we want to process the 530c66ac9dbSNicholas Bellinger * incoming fabric cmd ASAP.. 531c66ac9dbSNicholas Bellinger */ 532c66ac9dbSNicholas Bellinger if (out_alua_state == ALUA_ACCESS_STATE_ACTIVE_OPTMIZED) 533c66ac9dbSNicholas Bellinger return 0; 534c66ac9dbSNicholas Bellinger 535c66ac9dbSNicholas Bellinger switch (out_alua_state) { 536c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 537c66ac9dbSNicholas Bellinger return core_alua_state_nonoptimized(cmd, cdb, 538c66ac9dbSNicholas Bellinger nonop_delay_msecs, alua_ascq); 539c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_STANDBY: 540c66ac9dbSNicholas Bellinger return core_alua_state_standby(cmd, cdb, alua_ascq); 541c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_UNAVAILABLE: 542c66ac9dbSNicholas Bellinger return core_alua_state_unavailable(cmd, cdb, alua_ascq); 543c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_TRANSITION: 544c66ac9dbSNicholas Bellinger return core_alua_state_transition(cmd, cdb, alua_ascq); 545c66ac9dbSNicholas Bellinger /* 546c66ac9dbSNicholas Bellinger * OFFLINE is a secondary ALUA target port group access state, that is 547c66ac9dbSNicholas Bellinger * handled above with struct se_port->sep_tg_pt_secondary_offline=1 548c66ac9dbSNicholas Bellinger */ 549c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_OFFLINE: 550c66ac9dbSNicholas Bellinger default: 551c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unknown ALUA access state: 0x%02x\n", 552c66ac9dbSNicholas Bellinger out_alua_state); 553e3d6f909SAndy Grover return -EINVAL; 554c66ac9dbSNicholas Bellinger } 555c66ac9dbSNicholas Bellinger 556c66ac9dbSNicholas Bellinger return 0; 557c66ac9dbSNicholas Bellinger } 558c66ac9dbSNicholas Bellinger 559c66ac9dbSNicholas Bellinger /* 560c66ac9dbSNicholas Bellinger * Check implict and explict ALUA state change request. 561c66ac9dbSNicholas Bellinger */ 562c66ac9dbSNicholas Bellinger static int core_alua_check_transition(int state, int *primary) 563c66ac9dbSNicholas Bellinger { 564c66ac9dbSNicholas Bellinger switch (state) { 565c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: 566c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 567c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_STANDBY: 568c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_UNAVAILABLE: 569c66ac9dbSNicholas Bellinger /* 570c66ac9dbSNicholas Bellinger * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are 571c66ac9dbSNicholas Bellinger * defined as primary target port asymmetric access states. 572c66ac9dbSNicholas Bellinger */ 573c66ac9dbSNicholas Bellinger *primary = 1; 574c66ac9dbSNicholas Bellinger break; 575c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_OFFLINE: 576c66ac9dbSNicholas Bellinger /* 577c66ac9dbSNicholas Bellinger * OFFLINE state is defined as a secondary target port 578c66ac9dbSNicholas Bellinger * asymmetric access state. 579c66ac9dbSNicholas Bellinger */ 580c66ac9dbSNicholas Bellinger *primary = 0; 581c66ac9dbSNicholas Bellinger break; 582c66ac9dbSNicholas Bellinger default: 583c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unknown ALUA access state: 0x%02x\n", state); 584e3d6f909SAndy Grover return -EINVAL; 585c66ac9dbSNicholas Bellinger } 586c66ac9dbSNicholas Bellinger 587c66ac9dbSNicholas Bellinger return 0; 588c66ac9dbSNicholas Bellinger } 589c66ac9dbSNicholas Bellinger 590c66ac9dbSNicholas Bellinger static char *core_alua_dump_state(int state) 591c66ac9dbSNicholas Bellinger { 592c66ac9dbSNicholas Bellinger switch (state) { 593c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: 594c66ac9dbSNicholas Bellinger return "Active/Optimized"; 595c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 596c66ac9dbSNicholas Bellinger return "Active/NonOptimized"; 597c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_STANDBY: 598c66ac9dbSNicholas Bellinger return "Standby"; 599c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_UNAVAILABLE: 600c66ac9dbSNicholas Bellinger return "Unavailable"; 601c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_OFFLINE: 602c66ac9dbSNicholas Bellinger return "Offline"; 603c66ac9dbSNicholas Bellinger default: 604c66ac9dbSNicholas Bellinger return "Unknown"; 605c66ac9dbSNicholas Bellinger } 606c66ac9dbSNicholas Bellinger 607c66ac9dbSNicholas Bellinger return NULL; 608c66ac9dbSNicholas Bellinger } 609c66ac9dbSNicholas Bellinger 610c66ac9dbSNicholas Bellinger char *core_alua_dump_status(int status) 611c66ac9dbSNicholas Bellinger { 612c66ac9dbSNicholas Bellinger switch (status) { 613c66ac9dbSNicholas Bellinger case ALUA_STATUS_NONE: 614c66ac9dbSNicholas Bellinger return "None"; 615c66ac9dbSNicholas Bellinger case ALUA_STATUS_ALTERED_BY_EXPLICT_STPG: 616c66ac9dbSNicholas Bellinger return "Altered by Explict STPG"; 617c66ac9dbSNicholas Bellinger case ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA: 618c66ac9dbSNicholas Bellinger return "Altered by Implict ALUA"; 619c66ac9dbSNicholas Bellinger default: 620c66ac9dbSNicholas Bellinger return "Unknown"; 621c66ac9dbSNicholas Bellinger } 622c66ac9dbSNicholas Bellinger 623c66ac9dbSNicholas Bellinger return NULL; 624c66ac9dbSNicholas Bellinger } 625c66ac9dbSNicholas Bellinger 626c66ac9dbSNicholas Bellinger /* 627c66ac9dbSNicholas Bellinger * Used by fabric modules to determine when we need to delay processing 628c66ac9dbSNicholas Bellinger * for the Active/NonOptimized paths.. 629c66ac9dbSNicholas Bellinger */ 630c66ac9dbSNicholas Bellinger int core_alua_check_nonop_delay( 631c66ac9dbSNicholas Bellinger struct se_cmd *cmd) 632c66ac9dbSNicholas Bellinger { 633c66ac9dbSNicholas Bellinger if (!(cmd->se_cmd_flags & SCF_ALUA_NON_OPTIMIZED)) 634c66ac9dbSNicholas Bellinger return 0; 635c66ac9dbSNicholas Bellinger if (in_interrupt()) 636c66ac9dbSNicholas Bellinger return 0; 637c66ac9dbSNicholas Bellinger /* 638c66ac9dbSNicholas Bellinger * The ALUA Active/NonOptimized access state delay can be disabled 639c66ac9dbSNicholas Bellinger * in via configfs with a value of zero 640c66ac9dbSNicholas Bellinger */ 641c66ac9dbSNicholas Bellinger if (!(cmd->alua_nonop_delay)) 642c66ac9dbSNicholas Bellinger return 0; 643c66ac9dbSNicholas Bellinger /* 644c66ac9dbSNicholas Bellinger * struct se_cmd->alua_nonop_delay gets set by a target port group 645c66ac9dbSNicholas Bellinger * defined interval in core_alua_state_nonoptimized() 646c66ac9dbSNicholas Bellinger */ 647c66ac9dbSNicholas Bellinger msleep_interruptible(cmd->alua_nonop_delay); 648c66ac9dbSNicholas Bellinger return 0; 649c66ac9dbSNicholas Bellinger } 650c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_alua_check_nonop_delay); 651c66ac9dbSNicholas Bellinger 652c66ac9dbSNicholas Bellinger /* 653c66ac9dbSNicholas Bellinger * Called with tg_pt_gp->tg_pt_gp_md_mutex or tg_pt_gp_mem->sep_tg_pt_md_mutex 654c66ac9dbSNicholas Bellinger * 655c66ac9dbSNicholas Bellinger */ 656c66ac9dbSNicholas Bellinger static int core_alua_write_tpg_metadata( 657c66ac9dbSNicholas Bellinger const char *path, 658c66ac9dbSNicholas Bellinger unsigned char *md_buf, 659c66ac9dbSNicholas Bellinger u32 md_buf_len) 660c66ac9dbSNicholas Bellinger { 661c66ac9dbSNicholas Bellinger mm_segment_t old_fs; 662c66ac9dbSNicholas Bellinger struct file *file; 663c66ac9dbSNicholas Bellinger struct iovec iov[1]; 664c66ac9dbSNicholas Bellinger int flags = O_RDWR | O_CREAT | O_TRUNC, ret; 665c66ac9dbSNicholas Bellinger 666c66ac9dbSNicholas Bellinger memset(iov, 0, sizeof(struct iovec)); 667c66ac9dbSNicholas Bellinger 668c66ac9dbSNicholas Bellinger file = filp_open(path, flags, 0600); 669c66ac9dbSNicholas Bellinger if (IS_ERR(file) || !file || !file->f_dentry) { 670c66ac9dbSNicholas Bellinger printk(KERN_ERR "filp_open(%s) for ALUA metadata failed\n", 671c66ac9dbSNicholas Bellinger path); 672c66ac9dbSNicholas Bellinger return -ENODEV; 673c66ac9dbSNicholas Bellinger } 674c66ac9dbSNicholas Bellinger 675c66ac9dbSNicholas Bellinger iov[0].iov_base = &md_buf[0]; 676c66ac9dbSNicholas Bellinger iov[0].iov_len = md_buf_len; 677c66ac9dbSNicholas Bellinger 678c66ac9dbSNicholas Bellinger old_fs = get_fs(); 679c66ac9dbSNicholas Bellinger set_fs(get_ds()); 680c66ac9dbSNicholas Bellinger ret = vfs_writev(file, &iov[0], 1, &file->f_pos); 681c66ac9dbSNicholas Bellinger set_fs(old_fs); 682c66ac9dbSNicholas Bellinger 683c66ac9dbSNicholas Bellinger if (ret < 0) { 684c66ac9dbSNicholas Bellinger printk(KERN_ERR "Error writing ALUA metadata file: %s\n", path); 685c66ac9dbSNicholas Bellinger filp_close(file, NULL); 686c66ac9dbSNicholas Bellinger return -EIO; 687c66ac9dbSNicholas Bellinger } 688c66ac9dbSNicholas Bellinger filp_close(file, NULL); 689c66ac9dbSNicholas Bellinger 690c66ac9dbSNicholas Bellinger return 0; 691c66ac9dbSNicholas Bellinger } 692c66ac9dbSNicholas Bellinger 693c66ac9dbSNicholas Bellinger /* 694c66ac9dbSNicholas Bellinger * Called with tg_pt_gp->tg_pt_gp_md_mutex held 695c66ac9dbSNicholas Bellinger */ 696c66ac9dbSNicholas Bellinger static int core_alua_update_tpg_primary_metadata( 697c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 698c66ac9dbSNicholas Bellinger int primary_state, 699c66ac9dbSNicholas Bellinger unsigned char *md_buf) 700c66ac9dbSNicholas Bellinger { 701c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; 702c66ac9dbSNicholas Bellinger struct t10_wwn *wwn = &su_dev->t10_wwn; 703c66ac9dbSNicholas Bellinger char path[ALUA_METADATA_PATH_LEN]; 704c66ac9dbSNicholas Bellinger int len; 705c66ac9dbSNicholas Bellinger 706c66ac9dbSNicholas Bellinger memset(path, 0, ALUA_METADATA_PATH_LEN); 707c66ac9dbSNicholas Bellinger 708c66ac9dbSNicholas Bellinger len = snprintf(md_buf, tg_pt_gp->tg_pt_gp_md_buf_len, 709c66ac9dbSNicholas Bellinger "tg_pt_gp_id=%hu\n" 710c66ac9dbSNicholas Bellinger "alua_access_state=0x%02x\n" 711c66ac9dbSNicholas Bellinger "alua_access_status=0x%02x\n", 712c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id, primary_state, 713c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_status); 714c66ac9dbSNicholas Bellinger 715c66ac9dbSNicholas Bellinger snprintf(path, ALUA_METADATA_PATH_LEN, 716c66ac9dbSNicholas Bellinger "/var/target/alua/tpgs_%s/%s", &wwn->unit_serial[0], 717c66ac9dbSNicholas Bellinger config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item)); 718c66ac9dbSNicholas Bellinger 719c66ac9dbSNicholas Bellinger return core_alua_write_tpg_metadata(path, md_buf, len); 720c66ac9dbSNicholas Bellinger } 721c66ac9dbSNicholas Bellinger 722c66ac9dbSNicholas Bellinger static int core_alua_do_transition_tg_pt( 723c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 724c66ac9dbSNicholas Bellinger struct se_port *l_port, 725c66ac9dbSNicholas Bellinger struct se_node_acl *nacl, 726c66ac9dbSNicholas Bellinger unsigned char *md_buf, 727c66ac9dbSNicholas Bellinger int new_state, 728c66ac9dbSNicholas Bellinger int explict) 729c66ac9dbSNicholas Bellinger { 730c66ac9dbSNicholas Bellinger struct se_dev_entry *se_deve; 731c66ac9dbSNicholas Bellinger struct se_lun_acl *lacl; 732c66ac9dbSNicholas Bellinger struct se_port *port; 733c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *mem; 734c66ac9dbSNicholas Bellinger int old_state = 0; 735c66ac9dbSNicholas Bellinger /* 736c66ac9dbSNicholas Bellinger * Save the old primary ALUA access state, and set the current state 737c66ac9dbSNicholas Bellinger * to ALUA_ACCESS_STATE_TRANSITION. 738c66ac9dbSNicholas Bellinger */ 739c66ac9dbSNicholas Bellinger old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); 740c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, 741c66ac9dbSNicholas Bellinger ALUA_ACCESS_STATE_TRANSITION); 742c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_status = (explict) ? 743c66ac9dbSNicholas Bellinger ALUA_STATUS_ALTERED_BY_EXPLICT_STPG : 744c66ac9dbSNicholas Bellinger ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA; 745c66ac9dbSNicholas Bellinger /* 746c66ac9dbSNicholas Bellinger * Check for the optional ALUA primary state transition delay 747c66ac9dbSNicholas Bellinger */ 748c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0) 749c66ac9dbSNicholas Bellinger msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs); 750c66ac9dbSNicholas Bellinger 751c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 752c66ac9dbSNicholas Bellinger list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list, 753c66ac9dbSNicholas Bellinger tg_pt_gp_mem_list) { 754c66ac9dbSNicholas Bellinger port = mem->tg_pt; 755c66ac9dbSNicholas Bellinger /* 756c66ac9dbSNicholas Bellinger * After an implicit target port asymmetric access state 757c66ac9dbSNicholas Bellinger * change, a device server shall establish a unit attention 758c66ac9dbSNicholas Bellinger * condition for the initiator port associated with every I_T 759c66ac9dbSNicholas Bellinger * nexus with the additional sense code set to ASYMMETRIC 760c66ac9dbSNicholas Bellinger * ACCESS STATE CHAGED. 761c66ac9dbSNicholas Bellinger * 762c66ac9dbSNicholas Bellinger * After an explicit target port asymmetric access state 763c66ac9dbSNicholas Bellinger * change, a device server shall establish a unit attention 764c66ac9dbSNicholas Bellinger * condition with the additional sense code set to ASYMMETRIC 765c66ac9dbSNicholas Bellinger * ACCESS STATE CHANGED for the initiator port associated with 766c66ac9dbSNicholas Bellinger * every I_T nexus other than the I_T nexus on which the SET 767c66ac9dbSNicholas Bellinger * TARGET PORT GROUPS command 768c66ac9dbSNicholas Bellinger */ 769c66ac9dbSNicholas Bellinger atomic_inc(&mem->tg_pt_gp_mem_ref_cnt); 770c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 771c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 772c66ac9dbSNicholas Bellinger 773c66ac9dbSNicholas Bellinger spin_lock_bh(&port->sep_alua_lock); 774c66ac9dbSNicholas Bellinger list_for_each_entry(se_deve, &port->sep_alua_list, 775c66ac9dbSNicholas Bellinger alua_port_list) { 776c66ac9dbSNicholas Bellinger lacl = se_deve->se_lun_acl; 777c66ac9dbSNicholas Bellinger /* 778c66ac9dbSNicholas Bellinger * se_deve->se_lun_acl pointer may be NULL for a 779c66ac9dbSNicholas Bellinger * entry created without explict Node+MappedLUN ACLs 780c66ac9dbSNicholas Bellinger */ 781c66ac9dbSNicholas Bellinger if (!(lacl)) 782c66ac9dbSNicholas Bellinger continue; 783c66ac9dbSNicholas Bellinger 784c66ac9dbSNicholas Bellinger if (explict && 785c66ac9dbSNicholas Bellinger (nacl != NULL) && (nacl == lacl->se_lun_nacl) && 786c66ac9dbSNicholas Bellinger (l_port != NULL) && (l_port == port)) 787c66ac9dbSNicholas Bellinger continue; 788c66ac9dbSNicholas Bellinger 789c66ac9dbSNicholas Bellinger core_scsi3_ua_allocate(lacl->se_lun_nacl, 790c66ac9dbSNicholas Bellinger se_deve->mapped_lun, 0x2A, 791c66ac9dbSNicholas Bellinger ASCQ_2AH_ASYMMETRIC_ACCESS_STATE_CHANGED); 792c66ac9dbSNicholas Bellinger } 793c66ac9dbSNicholas Bellinger spin_unlock_bh(&port->sep_alua_lock); 794c66ac9dbSNicholas Bellinger 795c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 796c66ac9dbSNicholas Bellinger atomic_dec(&mem->tg_pt_gp_mem_ref_cnt); 797c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 798c66ac9dbSNicholas Bellinger } 799c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 800c66ac9dbSNicholas Bellinger /* 801c66ac9dbSNicholas Bellinger * Update the ALUA metadata buf that has been allocated in 802c66ac9dbSNicholas Bellinger * core_alua_do_port_transition(), this metadata will be written 803c66ac9dbSNicholas Bellinger * to struct file. 804c66ac9dbSNicholas Bellinger * 805c66ac9dbSNicholas Bellinger * Note that there is the case where we do not want to update the 806c66ac9dbSNicholas Bellinger * metadata when the saved metadata is being parsed in userspace 807c66ac9dbSNicholas Bellinger * when setting the existing port access state and access status. 808c66ac9dbSNicholas Bellinger * 809c66ac9dbSNicholas Bellinger * Also note that the failure to write out the ALUA metadata to 810c66ac9dbSNicholas Bellinger * struct file does NOT affect the actual ALUA transition. 811c66ac9dbSNicholas Bellinger */ 812c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_write_metadata) { 813c66ac9dbSNicholas Bellinger mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex); 814c66ac9dbSNicholas Bellinger core_alua_update_tpg_primary_metadata(tg_pt_gp, 815c66ac9dbSNicholas Bellinger new_state, md_buf); 816c66ac9dbSNicholas Bellinger mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex); 817c66ac9dbSNicholas Bellinger } 818c66ac9dbSNicholas Bellinger /* 819c66ac9dbSNicholas Bellinger * Set the current primary ALUA access state to the requested new state 820c66ac9dbSNicholas Bellinger */ 821c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state); 822c66ac9dbSNicholas Bellinger 823c66ac9dbSNicholas Bellinger printk(KERN_INFO "Successful %s ALUA transition TG PT Group: %s ID: %hu" 824c66ac9dbSNicholas Bellinger " from primary access state %s to %s\n", (explict) ? "explict" : 825c66ac9dbSNicholas Bellinger "implict", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), 826c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id, core_alua_dump_state(old_state), 827c66ac9dbSNicholas Bellinger core_alua_dump_state(new_state)); 828c66ac9dbSNicholas Bellinger 829c66ac9dbSNicholas Bellinger return 0; 830c66ac9dbSNicholas Bellinger } 831c66ac9dbSNicholas Bellinger 832c66ac9dbSNicholas Bellinger int core_alua_do_port_transition( 833c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *l_tg_pt_gp, 834c66ac9dbSNicholas Bellinger struct se_device *l_dev, 835c66ac9dbSNicholas Bellinger struct se_port *l_port, 836c66ac9dbSNicholas Bellinger struct se_node_acl *l_nacl, 837c66ac9dbSNicholas Bellinger int new_state, 838c66ac9dbSNicholas Bellinger int explict) 839c66ac9dbSNicholas Bellinger { 840c66ac9dbSNicholas Bellinger struct se_device *dev; 841c66ac9dbSNicholas Bellinger struct se_port *port; 842c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev; 843c66ac9dbSNicholas Bellinger struct se_node_acl *nacl; 844c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 845c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; 846c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 847c66ac9dbSNicholas Bellinger unsigned char *md_buf; 848c66ac9dbSNicholas Bellinger int primary; 849c66ac9dbSNicholas Bellinger 850c66ac9dbSNicholas Bellinger if (core_alua_check_transition(new_state, &primary) != 0) 851c66ac9dbSNicholas Bellinger return -EINVAL; 852c66ac9dbSNicholas Bellinger 853c66ac9dbSNicholas Bellinger md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL); 854c66ac9dbSNicholas Bellinger if (!(md_buf)) { 855c66ac9dbSNicholas Bellinger printk("Unable to allocate buf for ALUA metadata\n"); 856c66ac9dbSNicholas Bellinger return -ENOMEM; 857c66ac9dbSNicholas Bellinger } 858c66ac9dbSNicholas Bellinger 859c66ac9dbSNicholas Bellinger local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem; 860c66ac9dbSNicholas Bellinger spin_lock(&local_lu_gp_mem->lu_gp_mem_lock); 861c66ac9dbSNicholas Bellinger lu_gp = local_lu_gp_mem->lu_gp; 862c66ac9dbSNicholas Bellinger atomic_inc(&lu_gp->lu_gp_ref_cnt); 863c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 864c66ac9dbSNicholas Bellinger spin_unlock(&local_lu_gp_mem->lu_gp_mem_lock); 865c66ac9dbSNicholas Bellinger /* 866c66ac9dbSNicholas Bellinger * For storage objects that are members of the 'default_lu_gp', 867c66ac9dbSNicholas Bellinger * we only do transition on the passed *l_tp_pt_gp, and not 868c66ac9dbSNicholas Bellinger * on all of the matching target port groups IDs in default_lu_gp. 869c66ac9dbSNicholas Bellinger */ 870c66ac9dbSNicholas Bellinger if (!(lu_gp->lu_gp_id)) { 871c66ac9dbSNicholas Bellinger /* 872c66ac9dbSNicholas Bellinger * core_alua_do_transition_tg_pt() will always return 873c66ac9dbSNicholas Bellinger * success. 874c66ac9dbSNicholas Bellinger */ 875c66ac9dbSNicholas Bellinger core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl, 876c66ac9dbSNicholas Bellinger md_buf, new_state, explict); 877c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp->lu_gp_ref_cnt); 878c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 879c66ac9dbSNicholas Bellinger kfree(md_buf); 880c66ac9dbSNicholas Bellinger return 0; 881c66ac9dbSNicholas Bellinger } 882c66ac9dbSNicholas Bellinger /* 883c66ac9dbSNicholas Bellinger * For all other LU groups aside from 'default_lu_gp', walk all of 884c66ac9dbSNicholas Bellinger * the associated storage objects looking for a matching target port 885c66ac9dbSNicholas Bellinger * group ID from the local target port group. 886c66ac9dbSNicholas Bellinger */ 887c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 888c66ac9dbSNicholas Bellinger list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, 889c66ac9dbSNicholas Bellinger lu_gp_mem_list) { 890c66ac9dbSNicholas Bellinger 891c66ac9dbSNicholas Bellinger dev = lu_gp_mem->lu_gp_mem_dev; 892c66ac9dbSNicholas Bellinger su_dev = dev->se_sub_dev; 893c66ac9dbSNicholas Bellinger atomic_inc(&lu_gp_mem->lu_gp_mem_ref_cnt); 894c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 895c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 896c66ac9dbSNicholas Bellinger 897e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 898c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp, 899e3d6f909SAndy Grover &su_dev->t10_alua.tg_pt_gps_list, 900c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 901c66ac9dbSNicholas Bellinger 902c66ac9dbSNicholas Bellinger if (!(tg_pt_gp->tg_pt_gp_valid_id)) 903c66ac9dbSNicholas Bellinger continue; 904c66ac9dbSNicholas Bellinger /* 905c66ac9dbSNicholas Bellinger * If the target behavior port asymmetric access state 906c66ac9dbSNicholas Bellinger * is changed for any target port group accessiable via 907c66ac9dbSNicholas Bellinger * a logical unit within a LU group, the target port 908c66ac9dbSNicholas Bellinger * behavior group asymmetric access states for the same 909c66ac9dbSNicholas Bellinger * target port group accessible via other logical units 910c66ac9dbSNicholas Bellinger * in that LU group will also change. 911c66ac9dbSNicholas Bellinger */ 912c66ac9dbSNicholas Bellinger if (l_tg_pt_gp->tg_pt_gp_id != tg_pt_gp->tg_pt_gp_id) 913c66ac9dbSNicholas Bellinger continue; 914c66ac9dbSNicholas Bellinger 915c66ac9dbSNicholas Bellinger if (l_tg_pt_gp == tg_pt_gp) { 916c66ac9dbSNicholas Bellinger port = l_port; 917c66ac9dbSNicholas Bellinger nacl = l_nacl; 918c66ac9dbSNicholas Bellinger } else { 919c66ac9dbSNicholas Bellinger port = NULL; 920c66ac9dbSNicholas Bellinger nacl = NULL; 921c66ac9dbSNicholas Bellinger } 922c66ac9dbSNicholas Bellinger atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 923c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 924e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 925c66ac9dbSNicholas Bellinger /* 926c66ac9dbSNicholas Bellinger * core_alua_do_transition_tg_pt() will always return 927c66ac9dbSNicholas Bellinger * success. 928c66ac9dbSNicholas Bellinger */ 929c66ac9dbSNicholas Bellinger core_alua_do_transition_tg_pt(tg_pt_gp, port, 930c66ac9dbSNicholas Bellinger nacl, md_buf, new_state, explict); 931c66ac9dbSNicholas Bellinger 932e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 933c66ac9dbSNicholas Bellinger atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 934c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 935c66ac9dbSNicholas Bellinger } 936e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 937c66ac9dbSNicholas Bellinger 938c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 939c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp_mem->lu_gp_mem_ref_cnt); 940c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 941c66ac9dbSNicholas Bellinger } 942c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 943c66ac9dbSNicholas Bellinger 944c66ac9dbSNicholas Bellinger printk(KERN_INFO "Successfully processed LU Group: %s all ALUA TG PT" 945c66ac9dbSNicholas Bellinger " Group IDs: %hu %s transition to primary state: %s\n", 946c66ac9dbSNicholas Bellinger config_item_name(&lu_gp->lu_gp_group.cg_item), 947c66ac9dbSNicholas Bellinger l_tg_pt_gp->tg_pt_gp_id, (explict) ? "explict" : "implict", 948c66ac9dbSNicholas Bellinger core_alua_dump_state(new_state)); 949c66ac9dbSNicholas Bellinger 950c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp->lu_gp_ref_cnt); 951c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 952c66ac9dbSNicholas Bellinger kfree(md_buf); 953c66ac9dbSNicholas Bellinger return 0; 954c66ac9dbSNicholas Bellinger } 955c66ac9dbSNicholas Bellinger 956c66ac9dbSNicholas Bellinger /* 957c66ac9dbSNicholas Bellinger * Called with tg_pt_gp_mem->sep_tg_pt_md_mutex held 958c66ac9dbSNicholas Bellinger */ 959c66ac9dbSNicholas Bellinger static int core_alua_update_tpg_secondary_metadata( 960c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 961c66ac9dbSNicholas Bellinger struct se_port *port, 962c66ac9dbSNicholas Bellinger unsigned char *md_buf, 963c66ac9dbSNicholas Bellinger u32 md_buf_len) 964c66ac9dbSNicholas Bellinger { 965c66ac9dbSNicholas Bellinger struct se_portal_group *se_tpg = port->sep_tpg; 966c66ac9dbSNicholas Bellinger char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN]; 967c66ac9dbSNicholas Bellinger int len; 968c66ac9dbSNicholas Bellinger 969c66ac9dbSNicholas Bellinger memset(path, 0, ALUA_METADATA_PATH_LEN); 970c66ac9dbSNicholas Bellinger memset(wwn, 0, ALUA_SECONDARY_METADATA_WWN_LEN); 971c66ac9dbSNicholas Bellinger 972c66ac9dbSNicholas Bellinger len = snprintf(wwn, ALUA_SECONDARY_METADATA_WWN_LEN, "%s", 973e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg)); 974c66ac9dbSNicholas Bellinger 975e3d6f909SAndy Grover if (se_tpg->se_tpg_tfo->tpg_get_tag != NULL) 976c66ac9dbSNicholas Bellinger snprintf(wwn+len, ALUA_SECONDARY_METADATA_WWN_LEN-len, "+%hu", 977e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); 978c66ac9dbSNicholas Bellinger 979c66ac9dbSNicholas Bellinger len = snprintf(md_buf, md_buf_len, "alua_tg_pt_offline=%d\n" 980c66ac9dbSNicholas Bellinger "alua_tg_pt_status=0x%02x\n", 981c66ac9dbSNicholas Bellinger atomic_read(&port->sep_tg_pt_secondary_offline), 982c66ac9dbSNicholas Bellinger port->sep_tg_pt_secondary_stat); 983c66ac9dbSNicholas Bellinger 984c66ac9dbSNicholas Bellinger snprintf(path, ALUA_METADATA_PATH_LEN, "/var/target/alua/%s/%s/lun_%u", 985e3d6f909SAndy Grover se_tpg->se_tpg_tfo->get_fabric_name(), wwn, 986c66ac9dbSNicholas Bellinger port->sep_lun->unpacked_lun); 987c66ac9dbSNicholas Bellinger 988c66ac9dbSNicholas Bellinger return core_alua_write_tpg_metadata(path, md_buf, len); 989c66ac9dbSNicholas Bellinger } 990c66ac9dbSNicholas Bellinger 991c66ac9dbSNicholas Bellinger static int core_alua_set_tg_pt_secondary_state( 992c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 993c66ac9dbSNicholas Bellinger struct se_port *port, 994c66ac9dbSNicholas Bellinger int explict, 995c66ac9dbSNicholas Bellinger int offline) 996c66ac9dbSNicholas Bellinger { 997c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 998c66ac9dbSNicholas Bellinger unsigned char *md_buf; 999c66ac9dbSNicholas Bellinger u32 md_buf_len; 1000c66ac9dbSNicholas Bellinger int trans_delay_msecs; 1001c66ac9dbSNicholas Bellinger 1002c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1003c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 1004c66ac9dbSNicholas Bellinger if (!(tg_pt_gp)) { 1005c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1006c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to complete secondary state" 1007c66ac9dbSNicholas Bellinger " transition\n"); 1008e3d6f909SAndy Grover return -EINVAL; 1009c66ac9dbSNicholas Bellinger } 1010c66ac9dbSNicholas Bellinger trans_delay_msecs = tg_pt_gp->tg_pt_gp_trans_delay_msecs; 1011c66ac9dbSNicholas Bellinger /* 1012c66ac9dbSNicholas Bellinger * Set the secondary ALUA target port access state to OFFLINE 1013c66ac9dbSNicholas Bellinger * or release the previously secondary state for struct se_port 1014c66ac9dbSNicholas Bellinger */ 1015c66ac9dbSNicholas Bellinger if (offline) 1016c66ac9dbSNicholas Bellinger atomic_set(&port->sep_tg_pt_secondary_offline, 1); 1017c66ac9dbSNicholas Bellinger else 1018c66ac9dbSNicholas Bellinger atomic_set(&port->sep_tg_pt_secondary_offline, 0); 1019c66ac9dbSNicholas Bellinger 1020c66ac9dbSNicholas Bellinger md_buf_len = tg_pt_gp->tg_pt_gp_md_buf_len; 1021c66ac9dbSNicholas Bellinger port->sep_tg_pt_secondary_stat = (explict) ? 1022c66ac9dbSNicholas Bellinger ALUA_STATUS_ALTERED_BY_EXPLICT_STPG : 1023c66ac9dbSNicholas Bellinger ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA; 1024c66ac9dbSNicholas Bellinger 1025c66ac9dbSNicholas Bellinger printk(KERN_INFO "Successful %s ALUA transition TG PT Group: %s ID: %hu" 1026c66ac9dbSNicholas Bellinger " to secondary access state: %s\n", (explict) ? "explict" : 1027c66ac9dbSNicholas Bellinger "implict", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), 1028c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE"); 1029c66ac9dbSNicholas Bellinger 1030c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1031c66ac9dbSNicholas Bellinger /* 1032c66ac9dbSNicholas Bellinger * Do the optional transition delay after we set the secondary 1033c66ac9dbSNicholas Bellinger * ALUA access state. 1034c66ac9dbSNicholas Bellinger */ 1035c66ac9dbSNicholas Bellinger if (trans_delay_msecs != 0) 1036c66ac9dbSNicholas Bellinger msleep_interruptible(trans_delay_msecs); 1037c66ac9dbSNicholas Bellinger /* 1038c66ac9dbSNicholas Bellinger * See if we need to update the ALUA fabric port metadata for 1039c66ac9dbSNicholas Bellinger * secondary state and status 1040c66ac9dbSNicholas Bellinger */ 1041c66ac9dbSNicholas Bellinger if (port->sep_tg_pt_secondary_write_md) { 1042c66ac9dbSNicholas Bellinger md_buf = kzalloc(md_buf_len, GFP_KERNEL); 1043c66ac9dbSNicholas Bellinger if (!(md_buf)) { 1044c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate md_buf for" 1045c66ac9dbSNicholas Bellinger " secondary ALUA access metadata\n"); 1046e3d6f909SAndy Grover return -ENOMEM; 1047c66ac9dbSNicholas Bellinger } 1048c66ac9dbSNicholas Bellinger mutex_lock(&port->sep_tg_pt_md_mutex); 1049c66ac9dbSNicholas Bellinger core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port, 1050c66ac9dbSNicholas Bellinger md_buf, md_buf_len); 1051c66ac9dbSNicholas Bellinger mutex_unlock(&port->sep_tg_pt_md_mutex); 1052c66ac9dbSNicholas Bellinger 1053c66ac9dbSNicholas Bellinger kfree(md_buf); 1054c66ac9dbSNicholas Bellinger } 1055c66ac9dbSNicholas Bellinger 1056c66ac9dbSNicholas Bellinger return 0; 1057c66ac9dbSNicholas Bellinger } 1058c66ac9dbSNicholas Bellinger 1059c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp * 1060c66ac9dbSNicholas Bellinger core_alua_allocate_lu_gp(const char *name, int def_group) 1061c66ac9dbSNicholas Bellinger { 1062c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1063c66ac9dbSNicholas Bellinger 1064c66ac9dbSNicholas Bellinger lu_gp = kmem_cache_zalloc(t10_alua_lu_gp_cache, GFP_KERNEL); 1065c66ac9dbSNicholas Bellinger if (!(lu_gp)) { 1066c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate struct t10_alua_lu_gp\n"); 10676eab04a8SJustin P. Mattock return ERR_PTR(-ENOMEM); 1068c66ac9dbSNicholas Bellinger } 1069e3d6f909SAndy Grover INIT_LIST_HEAD(&lu_gp->lu_gp_node); 1070c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lu_gp->lu_gp_mem_list); 1071c66ac9dbSNicholas Bellinger spin_lock_init(&lu_gp->lu_gp_lock); 1072c66ac9dbSNicholas Bellinger atomic_set(&lu_gp->lu_gp_ref_cnt, 0); 1073c66ac9dbSNicholas Bellinger 1074c66ac9dbSNicholas Bellinger if (def_group) { 1075e3d6f909SAndy Grover lu_gp->lu_gp_id = alua_lu_gps_counter++; 1076c66ac9dbSNicholas Bellinger lu_gp->lu_gp_valid_id = 1; 1077e3d6f909SAndy Grover alua_lu_gps_count++; 1078c66ac9dbSNicholas Bellinger } 1079c66ac9dbSNicholas Bellinger 1080c66ac9dbSNicholas Bellinger return lu_gp; 1081c66ac9dbSNicholas Bellinger } 1082c66ac9dbSNicholas Bellinger 1083c66ac9dbSNicholas Bellinger int core_alua_set_lu_gp_id(struct t10_alua_lu_gp *lu_gp, u16 lu_gp_id) 1084c66ac9dbSNicholas Bellinger { 1085c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp_tmp; 1086c66ac9dbSNicholas Bellinger u16 lu_gp_id_tmp; 1087c66ac9dbSNicholas Bellinger /* 1088c66ac9dbSNicholas Bellinger * The lu_gp->lu_gp_id may only be set once.. 1089c66ac9dbSNicholas Bellinger */ 1090c66ac9dbSNicholas Bellinger if (lu_gp->lu_gp_valid_id) { 1091c66ac9dbSNicholas Bellinger printk(KERN_WARNING "ALUA LU Group already has a valid ID," 1092c66ac9dbSNicholas Bellinger " ignoring request\n"); 1093e3d6f909SAndy Grover return -EINVAL; 1094c66ac9dbSNicholas Bellinger } 1095c66ac9dbSNicholas Bellinger 1096e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1097e3d6f909SAndy Grover if (alua_lu_gps_count == 0x0000ffff) { 1098e3d6f909SAndy Grover printk(KERN_ERR "Maximum ALUA alua_lu_gps_count:" 1099c66ac9dbSNicholas Bellinger " 0x0000ffff reached\n"); 1100e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1101c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_lu_gp_cache, lu_gp); 1102e3d6f909SAndy Grover return -ENOSPC; 1103c66ac9dbSNicholas Bellinger } 1104c66ac9dbSNicholas Bellinger again: 1105c66ac9dbSNicholas Bellinger lu_gp_id_tmp = (lu_gp_id != 0) ? lu_gp_id : 1106e3d6f909SAndy Grover alua_lu_gps_counter++; 1107c66ac9dbSNicholas Bellinger 1108e3d6f909SAndy Grover list_for_each_entry(lu_gp_tmp, &lu_gps_list, lu_gp_node) { 1109c66ac9dbSNicholas Bellinger if (lu_gp_tmp->lu_gp_id == lu_gp_id_tmp) { 1110c66ac9dbSNicholas Bellinger if (!(lu_gp_id)) 1111c66ac9dbSNicholas Bellinger goto again; 1112c66ac9dbSNicholas Bellinger 1113c66ac9dbSNicholas Bellinger printk(KERN_WARNING "ALUA Logical Unit Group ID: %hu" 1114c66ac9dbSNicholas Bellinger " already exists, ignoring request\n", 1115c66ac9dbSNicholas Bellinger lu_gp_id); 1116e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1117e3d6f909SAndy Grover return -EINVAL; 1118c66ac9dbSNicholas Bellinger } 1119c66ac9dbSNicholas Bellinger } 1120c66ac9dbSNicholas Bellinger 1121c66ac9dbSNicholas Bellinger lu_gp->lu_gp_id = lu_gp_id_tmp; 1122c66ac9dbSNicholas Bellinger lu_gp->lu_gp_valid_id = 1; 1123e3d6f909SAndy Grover list_add_tail(&lu_gp->lu_gp_node, &lu_gps_list); 1124e3d6f909SAndy Grover alua_lu_gps_count++; 1125e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1126c66ac9dbSNicholas Bellinger 1127c66ac9dbSNicholas Bellinger return 0; 1128c66ac9dbSNicholas Bellinger } 1129c66ac9dbSNicholas Bellinger 1130c66ac9dbSNicholas Bellinger static struct t10_alua_lu_gp_member * 1131c66ac9dbSNicholas Bellinger core_alua_allocate_lu_gp_mem(struct se_device *dev) 1132c66ac9dbSNicholas Bellinger { 1133c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 1134c66ac9dbSNicholas Bellinger 1135c66ac9dbSNicholas Bellinger lu_gp_mem = kmem_cache_zalloc(t10_alua_lu_gp_mem_cache, GFP_KERNEL); 1136c66ac9dbSNicholas Bellinger if (!(lu_gp_mem)) { 1137c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate struct t10_alua_lu_gp_member\n"); 1138c66ac9dbSNicholas Bellinger return ERR_PTR(-ENOMEM); 1139c66ac9dbSNicholas Bellinger } 1140c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lu_gp_mem->lu_gp_mem_list); 1141c66ac9dbSNicholas Bellinger spin_lock_init(&lu_gp_mem->lu_gp_mem_lock); 1142c66ac9dbSNicholas Bellinger atomic_set(&lu_gp_mem->lu_gp_mem_ref_cnt, 0); 1143c66ac9dbSNicholas Bellinger 1144c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_mem_dev = dev; 1145c66ac9dbSNicholas Bellinger dev->dev_alua_lu_gp_mem = lu_gp_mem; 1146c66ac9dbSNicholas Bellinger 1147c66ac9dbSNicholas Bellinger return lu_gp_mem; 1148c66ac9dbSNicholas Bellinger } 1149c66ac9dbSNicholas Bellinger 1150c66ac9dbSNicholas Bellinger void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp) 1151c66ac9dbSNicholas Bellinger { 1152c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, *lu_gp_mem_tmp; 1153c66ac9dbSNicholas Bellinger /* 1154c66ac9dbSNicholas Bellinger * Once we have reached this point, config_item_put() has 1155c66ac9dbSNicholas Bellinger * already been called from target_core_alua_drop_lu_gp(). 1156c66ac9dbSNicholas Bellinger * 1157c66ac9dbSNicholas Bellinger * Here, we remove the *lu_gp from the global list so that 1158c66ac9dbSNicholas Bellinger * no associations can be made while we are releasing 1159c66ac9dbSNicholas Bellinger * struct t10_alua_lu_gp. 1160c66ac9dbSNicholas Bellinger */ 1161e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1162c66ac9dbSNicholas Bellinger atomic_set(&lu_gp->lu_gp_shutdown, 1); 1163e3d6f909SAndy Grover list_del(&lu_gp->lu_gp_node); 1164e3d6f909SAndy Grover alua_lu_gps_count--; 1165e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1166c66ac9dbSNicholas Bellinger /* 1167c66ac9dbSNicholas Bellinger * Allow struct t10_alua_lu_gp * referenced by core_alua_get_lu_gp_by_name() 1168c66ac9dbSNicholas Bellinger * in target_core_configfs.c:target_core_store_alua_lu_gp() to be 1169c66ac9dbSNicholas Bellinger * released with core_alua_put_lu_gp_from_name() 1170c66ac9dbSNicholas Bellinger */ 1171c66ac9dbSNicholas Bellinger while (atomic_read(&lu_gp->lu_gp_ref_cnt)) 1172c66ac9dbSNicholas Bellinger cpu_relax(); 1173c66ac9dbSNicholas Bellinger /* 1174c66ac9dbSNicholas Bellinger * Release reference to struct t10_alua_lu_gp * from all associated 1175c66ac9dbSNicholas Bellinger * struct se_device. 1176c66ac9dbSNicholas Bellinger */ 1177c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1178c66ac9dbSNicholas Bellinger list_for_each_entry_safe(lu_gp_mem, lu_gp_mem_tmp, 1179c66ac9dbSNicholas Bellinger &lu_gp->lu_gp_mem_list, lu_gp_mem_list) { 1180c66ac9dbSNicholas Bellinger if (lu_gp_mem->lu_gp_assoc) { 1181c66ac9dbSNicholas Bellinger list_del(&lu_gp_mem->lu_gp_mem_list); 1182c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members--; 1183c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 0; 1184c66ac9dbSNicholas Bellinger } 1185c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1186c66ac9dbSNicholas Bellinger /* 1187c66ac9dbSNicholas Bellinger * 118825985edcSLucas De Marchi * lu_gp_mem is associated with a single 1189c66ac9dbSNicholas Bellinger * struct se_device->dev_alua_lu_gp_mem, and is released when 1190c66ac9dbSNicholas Bellinger * struct se_device is released via core_alua_free_lu_gp_mem(). 1191c66ac9dbSNicholas Bellinger * 1192c66ac9dbSNicholas Bellinger * If the passed lu_gp does NOT match the default_lu_gp, assume 1193c66ac9dbSNicholas Bellinger * we want to re-assocate a given lu_gp_mem with default_lu_gp. 1194c66ac9dbSNicholas Bellinger */ 1195c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 1196e3d6f909SAndy Grover if (lu_gp != default_lu_gp) 1197c66ac9dbSNicholas Bellinger __core_alua_attach_lu_gp_mem(lu_gp_mem, 1198e3d6f909SAndy Grover default_lu_gp); 1199c66ac9dbSNicholas Bellinger else 1200c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = NULL; 1201c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 1202c66ac9dbSNicholas Bellinger 1203c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1204c66ac9dbSNicholas Bellinger } 1205c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1206c66ac9dbSNicholas Bellinger 1207c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_lu_gp_cache, lu_gp); 1208c66ac9dbSNicholas Bellinger } 1209c66ac9dbSNicholas Bellinger 1210c66ac9dbSNicholas Bellinger void core_alua_free_lu_gp_mem(struct se_device *dev) 1211c66ac9dbSNicholas Bellinger { 1212c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = dev->se_sub_dev; 1213e3d6f909SAndy Grover struct t10_alua *alua = &su_dev->t10_alua; 1214c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1215c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 1216c66ac9dbSNicholas Bellinger 1217c66ac9dbSNicholas Bellinger if (alua->alua_type != SPC3_ALUA_EMULATED) 1218c66ac9dbSNicholas Bellinger return; 1219c66ac9dbSNicholas Bellinger 1220c66ac9dbSNicholas Bellinger lu_gp_mem = dev->dev_alua_lu_gp_mem; 1221c66ac9dbSNicholas Bellinger if (!(lu_gp_mem)) 1222c66ac9dbSNicholas Bellinger return; 1223c66ac9dbSNicholas Bellinger 1224c66ac9dbSNicholas Bellinger while (atomic_read(&lu_gp_mem->lu_gp_mem_ref_cnt)) 1225c66ac9dbSNicholas Bellinger cpu_relax(); 1226c66ac9dbSNicholas Bellinger 1227c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 1228c66ac9dbSNicholas Bellinger lu_gp = lu_gp_mem->lu_gp; 1229c66ac9dbSNicholas Bellinger if ((lu_gp)) { 1230c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1231c66ac9dbSNicholas Bellinger if (lu_gp_mem->lu_gp_assoc) { 1232c66ac9dbSNicholas Bellinger list_del(&lu_gp_mem->lu_gp_mem_list); 1233c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members--; 1234c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 0; 1235c66ac9dbSNicholas Bellinger } 1236c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1237c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = NULL; 1238c66ac9dbSNicholas Bellinger } 1239c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 1240c66ac9dbSNicholas Bellinger 1241c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_lu_gp_mem_cache, lu_gp_mem); 1242c66ac9dbSNicholas Bellinger } 1243c66ac9dbSNicholas Bellinger 1244c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *core_alua_get_lu_gp_by_name(const char *name) 1245c66ac9dbSNicholas Bellinger { 1246c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1247c66ac9dbSNicholas Bellinger struct config_item *ci; 1248c66ac9dbSNicholas Bellinger 1249e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1250e3d6f909SAndy Grover list_for_each_entry(lu_gp, &lu_gps_list, lu_gp_node) { 1251c66ac9dbSNicholas Bellinger if (!(lu_gp->lu_gp_valid_id)) 1252c66ac9dbSNicholas Bellinger continue; 1253c66ac9dbSNicholas Bellinger ci = &lu_gp->lu_gp_group.cg_item; 1254c66ac9dbSNicholas Bellinger if (!(strcmp(config_item_name(ci), name))) { 1255c66ac9dbSNicholas Bellinger atomic_inc(&lu_gp->lu_gp_ref_cnt); 1256e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1257c66ac9dbSNicholas Bellinger return lu_gp; 1258c66ac9dbSNicholas Bellinger } 1259c66ac9dbSNicholas Bellinger } 1260e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1261c66ac9dbSNicholas Bellinger 1262c66ac9dbSNicholas Bellinger return NULL; 1263c66ac9dbSNicholas Bellinger } 1264c66ac9dbSNicholas Bellinger 1265c66ac9dbSNicholas Bellinger void core_alua_put_lu_gp_from_name(struct t10_alua_lu_gp *lu_gp) 1266c66ac9dbSNicholas Bellinger { 1267e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1268c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp->lu_gp_ref_cnt); 1269e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1270c66ac9dbSNicholas Bellinger } 1271c66ac9dbSNicholas Bellinger 1272c66ac9dbSNicholas Bellinger /* 1273c66ac9dbSNicholas Bellinger * Called with struct t10_alua_lu_gp_member->lu_gp_mem_lock 1274c66ac9dbSNicholas Bellinger */ 1275c66ac9dbSNicholas Bellinger void __core_alua_attach_lu_gp_mem( 1276c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, 1277c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp) 1278c66ac9dbSNicholas Bellinger { 1279c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1280c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = lu_gp; 1281c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 1; 1282c66ac9dbSNicholas Bellinger list_add_tail(&lu_gp_mem->lu_gp_mem_list, &lu_gp->lu_gp_mem_list); 1283c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members++; 1284c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1285c66ac9dbSNicholas Bellinger } 1286c66ac9dbSNicholas Bellinger 1287c66ac9dbSNicholas Bellinger /* 1288c66ac9dbSNicholas Bellinger * Called with struct t10_alua_lu_gp_member->lu_gp_mem_lock 1289c66ac9dbSNicholas Bellinger */ 1290c66ac9dbSNicholas Bellinger void __core_alua_drop_lu_gp_mem( 1291c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, 1292c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp) 1293c66ac9dbSNicholas Bellinger { 1294c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1295c66ac9dbSNicholas Bellinger list_del(&lu_gp_mem->lu_gp_mem_list); 1296c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = NULL; 1297c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 0; 1298c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members--; 1299c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1300c66ac9dbSNicholas Bellinger } 1301c66ac9dbSNicholas Bellinger 1302c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp( 1303c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1304c66ac9dbSNicholas Bellinger const char *name, 1305c66ac9dbSNicholas Bellinger int def_group) 1306c66ac9dbSNicholas Bellinger { 1307c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1308c66ac9dbSNicholas Bellinger 1309c66ac9dbSNicholas Bellinger tg_pt_gp = kmem_cache_zalloc(t10_alua_tg_pt_gp_cache, GFP_KERNEL); 1310c66ac9dbSNicholas Bellinger if (!(tg_pt_gp)) { 1311c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate struct t10_alua_tg_pt_gp\n"); 1312c66ac9dbSNicholas Bellinger return NULL; 1313c66ac9dbSNicholas Bellinger } 1314c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_list); 1315c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_mem_list); 1316c66ac9dbSNicholas Bellinger mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); 1317c66ac9dbSNicholas Bellinger spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); 1318c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); 1319c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_su_dev = su_dev; 1320c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN; 1321c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, 1322c66ac9dbSNicholas Bellinger ALUA_ACCESS_STATE_ACTIVE_OPTMIZED); 1323c66ac9dbSNicholas Bellinger /* 1324c66ac9dbSNicholas Bellinger * Enable both explict and implict ALUA support by default 1325c66ac9dbSNicholas Bellinger */ 1326c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = 1327c66ac9dbSNicholas Bellinger TPGS_EXPLICT_ALUA | TPGS_IMPLICT_ALUA; 1328c66ac9dbSNicholas Bellinger /* 1329c66ac9dbSNicholas Bellinger * Set the default Active/NonOptimized Delay in milliseconds 1330c66ac9dbSNicholas Bellinger */ 1331c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS; 1332c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS; 1333c66ac9dbSNicholas Bellinger 1334c66ac9dbSNicholas Bellinger if (def_group) { 1335e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 1336c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id = 1337e3d6f909SAndy Grover su_dev->t10_alua.alua_tg_pt_gps_counter++; 1338c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_valid_id = 1; 1339e3d6f909SAndy Grover su_dev->t10_alua.alua_tg_pt_gps_count++; 1340c66ac9dbSNicholas Bellinger list_add_tail(&tg_pt_gp->tg_pt_gp_list, 1341e3d6f909SAndy Grover &su_dev->t10_alua.tg_pt_gps_list); 1342e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 1343c66ac9dbSNicholas Bellinger } 1344c66ac9dbSNicholas Bellinger 1345c66ac9dbSNicholas Bellinger return tg_pt_gp; 1346c66ac9dbSNicholas Bellinger } 1347c66ac9dbSNicholas Bellinger 1348c66ac9dbSNicholas Bellinger int core_alua_set_tg_pt_gp_id( 1349c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1350c66ac9dbSNicholas Bellinger u16 tg_pt_gp_id) 1351c66ac9dbSNicholas Bellinger { 1352c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; 1353c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp_tmp; 1354c66ac9dbSNicholas Bellinger u16 tg_pt_gp_id_tmp; 1355c66ac9dbSNicholas Bellinger /* 1356c66ac9dbSNicholas Bellinger * The tg_pt_gp->tg_pt_gp_id may only be set once.. 1357c66ac9dbSNicholas Bellinger */ 1358c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_valid_id) { 1359c66ac9dbSNicholas Bellinger printk(KERN_WARNING "ALUA TG PT Group already has a valid ID," 1360c66ac9dbSNicholas Bellinger " ignoring request\n"); 1361e3d6f909SAndy Grover return -EINVAL; 1362c66ac9dbSNicholas Bellinger } 1363c66ac9dbSNicholas Bellinger 1364e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 1365e3d6f909SAndy Grover if (su_dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) { 1366c66ac9dbSNicholas Bellinger printk(KERN_ERR "Maximum ALUA alua_tg_pt_gps_count:" 1367c66ac9dbSNicholas Bellinger " 0x0000ffff reached\n"); 1368e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 1369c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); 1370e3d6f909SAndy Grover return -ENOSPC; 1371c66ac9dbSNicholas Bellinger } 1372c66ac9dbSNicholas Bellinger again: 1373c66ac9dbSNicholas Bellinger tg_pt_gp_id_tmp = (tg_pt_gp_id != 0) ? tg_pt_gp_id : 1374e3d6f909SAndy Grover su_dev->t10_alua.alua_tg_pt_gps_counter++; 1375c66ac9dbSNicholas Bellinger 1376e3d6f909SAndy Grover list_for_each_entry(tg_pt_gp_tmp, &su_dev->t10_alua.tg_pt_gps_list, 1377c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 1378c66ac9dbSNicholas Bellinger if (tg_pt_gp_tmp->tg_pt_gp_id == tg_pt_gp_id_tmp) { 1379c66ac9dbSNicholas Bellinger if (!(tg_pt_gp_id)) 1380c66ac9dbSNicholas Bellinger goto again; 1381c66ac9dbSNicholas Bellinger 1382c66ac9dbSNicholas Bellinger printk(KERN_ERR "ALUA Target Port Group ID: %hu already" 1383c66ac9dbSNicholas Bellinger " exists, ignoring request\n", tg_pt_gp_id); 1384e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 1385e3d6f909SAndy Grover return -EINVAL; 1386c66ac9dbSNicholas Bellinger } 1387c66ac9dbSNicholas Bellinger } 1388c66ac9dbSNicholas Bellinger 1389c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id = tg_pt_gp_id_tmp; 1390c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_valid_id = 1; 1391c66ac9dbSNicholas Bellinger list_add_tail(&tg_pt_gp->tg_pt_gp_list, 1392e3d6f909SAndy Grover &su_dev->t10_alua.tg_pt_gps_list); 1393e3d6f909SAndy Grover su_dev->t10_alua.alua_tg_pt_gps_count++; 1394e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 1395c66ac9dbSNicholas Bellinger 1396c66ac9dbSNicholas Bellinger return 0; 1397c66ac9dbSNicholas Bellinger } 1398c66ac9dbSNicholas Bellinger 1399c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( 1400c66ac9dbSNicholas Bellinger struct se_port *port) 1401c66ac9dbSNicholas Bellinger { 1402c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1403c66ac9dbSNicholas Bellinger 1404c66ac9dbSNicholas Bellinger tg_pt_gp_mem = kmem_cache_zalloc(t10_alua_tg_pt_gp_mem_cache, 1405c66ac9dbSNicholas Bellinger GFP_KERNEL); 1406c66ac9dbSNicholas Bellinger if (!(tg_pt_gp_mem)) { 1407c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to allocate struct t10_alua_tg_pt_gp_member\n"); 1408c66ac9dbSNicholas Bellinger return ERR_PTR(-ENOMEM); 1409c66ac9dbSNicholas Bellinger } 1410c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1411c66ac9dbSNicholas Bellinger spin_lock_init(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1412c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt, 0); 1413c66ac9dbSNicholas Bellinger 1414c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt = port; 1415c66ac9dbSNicholas Bellinger port->sep_alua_tg_pt_gp_mem = tg_pt_gp_mem; 1416c66ac9dbSNicholas Bellinger atomic_set(&port->sep_tg_pt_gp_active, 1); 1417c66ac9dbSNicholas Bellinger 1418c66ac9dbSNicholas Bellinger return tg_pt_gp_mem; 1419c66ac9dbSNicholas Bellinger } 1420c66ac9dbSNicholas Bellinger 1421c66ac9dbSNicholas Bellinger void core_alua_free_tg_pt_gp( 1422c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1423c66ac9dbSNicholas Bellinger { 1424c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; 1425c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *tg_pt_gp_mem_tmp; 1426c66ac9dbSNicholas Bellinger /* 1427c66ac9dbSNicholas Bellinger * Once we have reached this point, config_item_put() has already 1428c66ac9dbSNicholas Bellinger * been called from target_core_alua_drop_tg_pt_gp(). 1429c66ac9dbSNicholas Bellinger * 1430c66ac9dbSNicholas Bellinger * Here we remove *tg_pt_gp from the global list so that 1431c66ac9dbSNicholas Bellinger * no assications *OR* explict ALUA via SET_TARGET_PORT_GROUPS 1432c66ac9dbSNicholas Bellinger * can be made while we are releasing struct t10_alua_tg_pt_gp. 1433c66ac9dbSNicholas Bellinger */ 1434e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 1435c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp->tg_pt_gp_list); 1436e3d6f909SAndy Grover su_dev->t10_alua.alua_tg_pt_gps_counter--; 1437e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 1438c66ac9dbSNicholas Bellinger /* 1439c66ac9dbSNicholas Bellinger * Allow a struct t10_alua_tg_pt_gp_member * referenced by 1440c66ac9dbSNicholas Bellinger * core_alua_get_tg_pt_gp_by_name() in 1441c66ac9dbSNicholas Bellinger * target_core_configfs.c:target_core_store_alua_tg_pt_gp() 1442c66ac9dbSNicholas Bellinger * to be released with core_alua_put_tg_pt_gp_from_name(). 1443c66ac9dbSNicholas Bellinger */ 1444c66ac9dbSNicholas Bellinger while (atomic_read(&tg_pt_gp->tg_pt_gp_ref_cnt)) 1445c66ac9dbSNicholas Bellinger cpu_relax(); 1446c66ac9dbSNicholas Bellinger /* 1447c66ac9dbSNicholas Bellinger * Release reference to struct t10_alua_tg_pt_gp from all associated 1448c66ac9dbSNicholas Bellinger * struct se_port. 1449c66ac9dbSNicholas Bellinger */ 1450c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1451c66ac9dbSNicholas Bellinger list_for_each_entry_safe(tg_pt_gp_mem, tg_pt_gp_mem_tmp, 1452c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_mem_list, tg_pt_gp_mem_list) { 1453c66ac9dbSNicholas Bellinger if (tg_pt_gp_mem->tg_pt_gp_assoc) { 1454c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1455c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members--; 1456c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 0; 1457c66ac9dbSNicholas Bellinger } 1458c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1459c66ac9dbSNicholas Bellinger /* 146025985edcSLucas De Marchi * tg_pt_gp_mem is associated with a single 1461c66ac9dbSNicholas Bellinger * se_port->sep_alua_tg_pt_gp_mem, and is released via 1462c66ac9dbSNicholas Bellinger * core_alua_free_tg_pt_gp_mem(). 1463c66ac9dbSNicholas Bellinger * 1464c66ac9dbSNicholas Bellinger * If the passed tg_pt_gp does NOT match the default_tg_pt_gp, 1465c66ac9dbSNicholas Bellinger * assume we want to re-assocate a given tg_pt_gp_mem with 1466c66ac9dbSNicholas Bellinger * default_tg_pt_gp. 1467c66ac9dbSNicholas Bellinger */ 1468c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1469e3d6f909SAndy Grover if (tg_pt_gp != su_dev->t10_alua.default_tg_pt_gp) { 1470c66ac9dbSNicholas Bellinger __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, 1471e3d6f909SAndy Grover su_dev->t10_alua.default_tg_pt_gp); 1472c66ac9dbSNicholas Bellinger } else 1473c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = NULL; 1474c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1475c66ac9dbSNicholas Bellinger 1476c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1477c66ac9dbSNicholas Bellinger } 1478c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1479c66ac9dbSNicholas Bellinger 1480c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); 1481c66ac9dbSNicholas Bellinger } 1482c66ac9dbSNicholas Bellinger 1483c66ac9dbSNicholas Bellinger void core_alua_free_tg_pt_gp_mem(struct se_port *port) 1484c66ac9dbSNicholas Bellinger { 1485c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev; 1486e3d6f909SAndy Grover struct t10_alua *alua = &su_dev->t10_alua; 1487c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1488c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1489c66ac9dbSNicholas Bellinger 1490c66ac9dbSNicholas Bellinger if (alua->alua_type != SPC3_ALUA_EMULATED) 1491c66ac9dbSNicholas Bellinger return; 1492c66ac9dbSNicholas Bellinger 1493c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 1494c66ac9dbSNicholas Bellinger if (!(tg_pt_gp_mem)) 1495c66ac9dbSNicholas Bellinger return; 1496c66ac9dbSNicholas Bellinger 1497c66ac9dbSNicholas Bellinger while (atomic_read(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt)) 1498c66ac9dbSNicholas Bellinger cpu_relax(); 1499c66ac9dbSNicholas Bellinger 1500c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1501c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 1502c66ac9dbSNicholas Bellinger if ((tg_pt_gp)) { 1503c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1504c66ac9dbSNicholas Bellinger if (tg_pt_gp_mem->tg_pt_gp_assoc) { 1505c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1506c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members--; 1507c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 0; 1508c66ac9dbSNicholas Bellinger } 1509c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1510c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = NULL; 1511c66ac9dbSNicholas Bellinger } 1512c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1513c66ac9dbSNicholas Bellinger 1514c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_tg_pt_gp_mem_cache, tg_pt_gp_mem); 1515c66ac9dbSNicholas Bellinger } 1516c66ac9dbSNicholas Bellinger 1517c66ac9dbSNicholas Bellinger static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( 1518c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev, 1519c66ac9dbSNicholas Bellinger const char *name) 1520c66ac9dbSNicholas Bellinger { 1521c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1522c66ac9dbSNicholas Bellinger struct config_item *ci; 1523c66ac9dbSNicholas Bellinger 1524e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 1525e3d6f909SAndy Grover list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, 1526c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 1527c66ac9dbSNicholas Bellinger if (!(tg_pt_gp->tg_pt_gp_valid_id)) 1528c66ac9dbSNicholas Bellinger continue; 1529c66ac9dbSNicholas Bellinger ci = &tg_pt_gp->tg_pt_gp_group.cg_item; 1530c66ac9dbSNicholas Bellinger if (!(strcmp(config_item_name(ci), name))) { 1531c66ac9dbSNicholas Bellinger atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 1532e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 1533c66ac9dbSNicholas Bellinger return tg_pt_gp; 1534c66ac9dbSNicholas Bellinger } 1535c66ac9dbSNicholas Bellinger } 1536e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 1537c66ac9dbSNicholas Bellinger 1538c66ac9dbSNicholas Bellinger return NULL; 1539c66ac9dbSNicholas Bellinger } 1540c66ac9dbSNicholas Bellinger 1541c66ac9dbSNicholas Bellinger static void core_alua_put_tg_pt_gp_from_name( 1542c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1543c66ac9dbSNicholas Bellinger { 1544c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = tg_pt_gp->tg_pt_gp_su_dev; 1545c66ac9dbSNicholas Bellinger 1546e3d6f909SAndy Grover spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 1547c66ac9dbSNicholas Bellinger atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 1548e3d6f909SAndy Grover spin_unlock(&su_dev->t10_alua.tg_pt_gps_lock); 1549c66ac9dbSNicholas Bellinger } 1550c66ac9dbSNicholas Bellinger 1551c66ac9dbSNicholas Bellinger /* 1552c66ac9dbSNicholas Bellinger * Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held 1553c66ac9dbSNicholas Bellinger */ 1554c66ac9dbSNicholas Bellinger void __core_alua_attach_tg_pt_gp_mem( 1555c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 1556c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1557c66ac9dbSNicholas Bellinger { 1558c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1559c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = tg_pt_gp; 1560c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 1; 1561c66ac9dbSNicholas Bellinger list_add_tail(&tg_pt_gp_mem->tg_pt_gp_mem_list, 1562c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_mem_list); 1563c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members++; 1564c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1565c66ac9dbSNicholas Bellinger } 1566c66ac9dbSNicholas Bellinger 1567c66ac9dbSNicholas Bellinger /* 1568c66ac9dbSNicholas Bellinger * Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held 1569c66ac9dbSNicholas Bellinger */ 1570c66ac9dbSNicholas Bellinger static void __core_alua_drop_tg_pt_gp_mem( 1571c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 1572c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1573c66ac9dbSNicholas Bellinger { 1574c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1575c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1576c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = NULL; 1577c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 0; 1578c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members--; 1579c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1580c66ac9dbSNicholas Bellinger } 1581c66ac9dbSNicholas Bellinger 1582c66ac9dbSNicholas Bellinger ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page) 1583c66ac9dbSNicholas Bellinger { 1584c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev; 1585c66ac9dbSNicholas Bellinger struct config_item *tg_pt_ci; 1586e3d6f909SAndy Grover struct t10_alua *alua = &su_dev->t10_alua; 1587c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1588c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1589c66ac9dbSNicholas Bellinger ssize_t len = 0; 1590c66ac9dbSNicholas Bellinger 1591c66ac9dbSNicholas Bellinger if (alua->alua_type != SPC3_ALUA_EMULATED) 1592c66ac9dbSNicholas Bellinger return len; 1593c66ac9dbSNicholas Bellinger 1594c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 1595c66ac9dbSNicholas Bellinger if (!(tg_pt_gp_mem)) 1596c66ac9dbSNicholas Bellinger return len; 1597c66ac9dbSNicholas Bellinger 1598c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1599c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 1600c66ac9dbSNicholas Bellinger if ((tg_pt_gp)) { 1601c66ac9dbSNicholas Bellinger tg_pt_ci = &tg_pt_gp->tg_pt_gp_group.cg_item; 1602c66ac9dbSNicholas Bellinger len += sprintf(page, "TG Port Alias: %s\nTG Port Group ID:" 1603c66ac9dbSNicholas Bellinger " %hu\nTG Port Primary Access State: %s\nTG Port " 1604c66ac9dbSNicholas Bellinger "Primary Access Status: %s\nTG Port Secondary Access" 1605c66ac9dbSNicholas Bellinger " State: %s\nTG Port Secondary Access Status: %s\n", 1606c66ac9dbSNicholas Bellinger config_item_name(tg_pt_ci), tg_pt_gp->tg_pt_gp_id, 1607c66ac9dbSNicholas Bellinger core_alua_dump_state(atomic_read( 1608c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_alua_access_state)), 1609c66ac9dbSNicholas Bellinger core_alua_dump_status( 1610c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_status), 1611c66ac9dbSNicholas Bellinger (atomic_read(&port->sep_tg_pt_secondary_offline)) ? 1612c66ac9dbSNicholas Bellinger "Offline" : "None", 1613c66ac9dbSNicholas Bellinger core_alua_dump_status(port->sep_tg_pt_secondary_stat)); 1614c66ac9dbSNicholas Bellinger } 1615c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1616c66ac9dbSNicholas Bellinger 1617c66ac9dbSNicholas Bellinger return len; 1618c66ac9dbSNicholas Bellinger } 1619c66ac9dbSNicholas Bellinger 1620c66ac9dbSNicholas Bellinger ssize_t core_alua_store_tg_pt_gp_info( 1621c66ac9dbSNicholas Bellinger struct se_port *port, 1622c66ac9dbSNicholas Bellinger const char *page, 1623c66ac9dbSNicholas Bellinger size_t count) 1624c66ac9dbSNicholas Bellinger { 1625c66ac9dbSNicholas Bellinger struct se_portal_group *tpg; 1626c66ac9dbSNicholas Bellinger struct se_lun *lun; 1627c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = port->sep_lun->lun_se_dev->se_sub_dev; 1628c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL; 1629c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1630c66ac9dbSNicholas Bellinger unsigned char buf[TG_PT_GROUP_NAME_BUF]; 1631c66ac9dbSNicholas Bellinger int move = 0; 1632c66ac9dbSNicholas Bellinger 1633c66ac9dbSNicholas Bellinger tpg = port->sep_tpg; 1634c66ac9dbSNicholas Bellinger lun = port->sep_lun; 1635c66ac9dbSNicholas Bellinger 1636e3d6f909SAndy Grover if (su_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) { 1637c66ac9dbSNicholas Bellinger printk(KERN_WARNING "SPC3_ALUA_EMULATED not enabled for" 1638e3d6f909SAndy Grover " %s/tpgt_%hu/%s\n", tpg->se_tpg_tfo->tpg_get_wwn(tpg), 1639e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), 1640c66ac9dbSNicholas Bellinger config_item_name(&lun->lun_group.cg_item)); 1641c66ac9dbSNicholas Bellinger return -EINVAL; 1642c66ac9dbSNicholas Bellinger } 1643c66ac9dbSNicholas Bellinger 1644c66ac9dbSNicholas Bellinger if (count > TG_PT_GROUP_NAME_BUF) { 1645c66ac9dbSNicholas Bellinger printk(KERN_ERR "ALUA Target Port Group alias too large!\n"); 1646c66ac9dbSNicholas Bellinger return -EINVAL; 1647c66ac9dbSNicholas Bellinger } 1648c66ac9dbSNicholas Bellinger memset(buf, 0, TG_PT_GROUP_NAME_BUF); 1649c66ac9dbSNicholas Bellinger memcpy(buf, page, count); 1650c66ac9dbSNicholas Bellinger /* 1651c66ac9dbSNicholas Bellinger * Any ALUA target port group alias besides "NULL" means we will be 1652c66ac9dbSNicholas Bellinger * making a new group association. 1653c66ac9dbSNicholas Bellinger */ 1654c66ac9dbSNicholas Bellinger if (strcmp(strstrip(buf), "NULL")) { 1655c66ac9dbSNicholas Bellinger /* 1656c66ac9dbSNicholas Bellinger * core_alua_get_tg_pt_gp_by_name() will increment reference to 1657c66ac9dbSNicholas Bellinger * struct t10_alua_tg_pt_gp. This reference is released with 1658c66ac9dbSNicholas Bellinger * core_alua_put_tg_pt_gp_from_name() below. 1659c66ac9dbSNicholas Bellinger */ 1660c66ac9dbSNicholas Bellinger tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(su_dev, 1661c66ac9dbSNicholas Bellinger strstrip(buf)); 1662c66ac9dbSNicholas Bellinger if (!(tg_pt_gp_new)) 1663c66ac9dbSNicholas Bellinger return -ENODEV; 1664c66ac9dbSNicholas Bellinger } 1665c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 1666c66ac9dbSNicholas Bellinger if (!(tg_pt_gp_mem)) { 1667c66ac9dbSNicholas Bellinger if (tg_pt_gp_new) 1668c66ac9dbSNicholas Bellinger core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new); 1669c66ac9dbSNicholas Bellinger printk(KERN_ERR "NULL struct se_port->sep_alua_tg_pt_gp_mem pointer\n"); 1670c66ac9dbSNicholas Bellinger return -EINVAL; 1671c66ac9dbSNicholas Bellinger } 1672c66ac9dbSNicholas Bellinger 1673c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1674c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 1675c66ac9dbSNicholas Bellinger if ((tg_pt_gp)) { 1676c66ac9dbSNicholas Bellinger /* 1677c66ac9dbSNicholas Bellinger * Clearing an existing tg_pt_gp association, and replacing 1678c66ac9dbSNicholas Bellinger * with the default_tg_pt_gp. 1679c66ac9dbSNicholas Bellinger */ 1680c66ac9dbSNicholas Bellinger if (!(tg_pt_gp_new)) { 1681c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: Moving" 1682c66ac9dbSNicholas Bellinger " %s/tpgt_%hu/%s from ALUA Target Port Group:" 1683c66ac9dbSNicholas Bellinger " alua/%s, ID: %hu back to" 1684c66ac9dbSNicholas Bellinger " default_tg_pt_gp\n", 1685e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_wwn(tpg), 1686e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), 1687c66ac9dbSNicholas Bellinger config_item_name(&lun->lun_group.cg_item), 1688c66ac9dbSNicholas Bellinger config_item_name( 1689c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_group.cg_item), 1690c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id); 1691c66ac9dbSNicholas Bellinger 1692c66ac9dbSNicholas Bellinger __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); 1693c66ac9dbSNicholas Bellinger __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, 1694e3d6f909SAndy Grover su_dev->t10_alua.default_tg_pt_gp); 1695c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1696c66ac9dbSNicholas Bellinger 1697c66ac9dbSNicholas Bellinger return count; 1698c66ac9dbSNicholas Bellinger } 1699c66ac9dbSNicholas Bellinger /* 1700c66ac9dbSNicholas Bellinger * Removing existing association of tg_pt_gp_mem with tg_pt_gp 1701c66ac9dbSNicholas Bellinger */ 1702c66ac9dbSNicholas Bellinger __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); 1703c66ac9dbSNicholas Bellinger move = 1; 1704c66ac9dbSNicholas Bellinger } 1705c66ac9dbSNicholas Bellinger /* 1706c66ac9dbSNicholas Bellinger * Associate tg_pt_gp_mem with tg_pt_gp_new. 1707c66ac9dbSNicholas Bellinger */ 1708c66ac9dbSNicholas Bellinger __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp_new); 1709c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1710c66ac9dbSNicholas Bellinger printk(KERN_INFO "Target_Core_ConfigFS: %s %s/tpgt_%hu/%s to ALUA" 1711c66ac9dbSNicholas Bellinger " Target Port Group: alua/%s, ID: %hu\n", (move) ? 1712e3d6f909SAndy Grover "Moving" : "Adding", tpg->se_tpg_tfo->tpg_get_wwn(tpg), 1713e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), 1714c66ac9dbSNicholas Bellinger config_item_name(&lun->lun_group.cg_item), 1715c66ac9dbSNicholas Bellinger config_item_name(&tg_pt_gp_new->tg_pt_gp_group.cg_item), 1716c66ac9dbSNicholas Bellinger tg_pt_gp_new->tg_pt_gp_id); 1717c66ac9dbSNicholas Bellinger 1718c66ac9dbSNicholas Bellinger core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new); 1719c66ac9dbSNicholas Bellinger return count; 1720c66ac9dbSNicholas Bellinger } 1721c66ac9dbSNicholas Bellinger 1722c66ac9dbSNicholas Bellinger ssize_t core_alua_show_access_type( 1723c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1724c66ac9dbSNicholas Bellinger char *page) 1725c66ac9dbSNicholas Bellinger { 1726c66ac9dbSNicholas Bellinger if ((tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA) && 1727c66ac9dbSNicholas Bellinger (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA)) 1728c66ac9dbSNicholas Bellinger return sprintf(page, "Implict and Explict\n"); 1729c66ac9dbSNicholas Bellinger else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICT_ALUA) 1730c66ac9dbSNicholas Bellinger return sprintf(page, "Implict\n"); 1731c66ac9dbSNicholas Bellinger else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICT_ALUA) 1732c66ac9dbSNicholas Bellinger return sprintf(page, "Explict\n"); 1733c66ac9dbSNicholas Bellinger else 1734c66ac9dbSNicholas Bellinger return sprintf(page, "None\n"); 1735c66ac9dbSNicholas Bellinger } 1736c66ac9dbSNicholas Bellinger 1737c66ac9dbSNicholas Bellinger ssize_t core_alua_store_access_type( 1738c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1739c66ac9dbSNicholas Bellinger const char *page, 1740c66ac9dbSNicholas Bellinger size_t count) 1741c66ac9dbSNicholas Bellinger { 1742c66ac9dbSNicholas Bellinger unsigned long tmp; 1743c66ac9dbSNicholas Bellinger int ret; 1744c66ac9dbSNicholas Bellinger 1745c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 1746c66ac9dbSNicholas Bellinger if (ret < 0) { 1747c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract alua_access_type\n"); 1748c66ac9dbSNicholas Bellinger return -EINVAL; 1749c66ac9dbSNicholas Bellinger } 1750c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1) && (tmp != 2) && (tmp != 3)) { 1751c66ac9dbSNicholas Bellinger printk(KERN_ERR "Illegal value for alua_access_type:" 1752c66ac9dbSNicholas Bellinger " %lu\n", tmp); 1753c66ac9dbSNicholas Bellinger return -EINVAL; 1754c66ac9dbSNicholas Bellinger } 1755c66ac9dbSNicholas Bellinger if (tmp == 3) 1756c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = 1757c66ac9dbSNicholas Bellinger TPGS_IMPLICT_ALUA | TPGS_EXPLICT_ALUA; 1758c66ac9dbSNicholas Bellinger else if (tmp == 2) 1759c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_EXPLICT_ALUA; 1760c66ac9dbSNicholas Bellinger else if (tmp == 1) 1761c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_IMPLICT_ALUA; 1762c66ac9dbSNicholas Bellinger else 1763c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = 0; 1764c66ac9dbSNicholas Bellinger 1765c66ac9dbSNicholas Bellinger return count; 1766c66ac9dbSNicholas Bellinger } 1767c66ac9dbSNicholas Bellinger 1768c66ac9dbSNicholas Bellinger ssize_t core_alua_show_nonop_delay_msecs( 1769c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1770c66ac9dbSNicholas Bellinger char *page) 1771c66ac9dbSNicholas Bellinger { 1772c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_nonop_delay_msecs); 1773c66ac9dbSNicholas Bellinger } 1774c66ac9dbSNicholas Bellinger 1775c66ac9dbSNicholas Bellinger ssize_t core_alua_store_nonop_delay_msecs( 1776c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1777c66ac9dbSNicholas Bellinger const char *page, 1778c66ac9dbSNicholas Bellinger size_t count) 1779c66ac9dbSNicholas Bellinger { 1780c66ac9dbSNicholas Bellinger unsigned long tmp; 1781c66ac9dbSNicholas Bellinger int ret; 1782c66ac9dbSNicholas Bellinger 1783c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 1784c66ac9dbSNicholas Bellinger if (ret < 0) { 1785c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract nonop_delay_msecs\n"); 1786c66ac9dbSNicholas Bellinger return -EINVAL; 1787c66ac9dbSNicholas Bellinger } 1788c66ac9dbSNicholas Bellinger if (tmp > ALUA_MAX_NONOP_DELAY_MSECS) { 1789c66ac9dbSNicholas Bellinger printk(KERN_ERR "Passed nonop_delay_msecs: %lu, exceeds" 1790c66ac9dbSNicholas Bellinger " ALUA_MAX_NONOP_DELAY_MSECS: %d\n", tmp, 1791c66ac9dbSNicholas Bellinger ALUA_MAX_NONOP_DELAY_MSECS); 1792c66ac9dbSNicholas Bellinger return -EINVAL; 1793c66ac9dbSNicholas Bellinger } 1794c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_nonop_delay_msecs = (int)tmp; 1795c66ac9dbSNicholas Bellinger 1796c66ac9dbSNicholas Bellinger return count; 1797c66ac9dbSNicholas Bellinger } 1798c66ac9dbSNicholas Bellinger 1799c66ac9dbSNicholas Bellinger ssize_t core_alua_show_trans_delay_msecs( 1800c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1801c66ac9dbSNicholas Bellinger char *page) 1802c66ac9dbSNicholas Bellinger { 1803c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_trans_delay_msecs); 1804c66ac9dbSNicholas Bellinger } 1805c66ac9dbSNicholas Bellinger 1806c66ac9dbSNicholas Bellinger ssize_t core_alua_store_trans_delay_msecs( 1807c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1808c66ac9dbSNicholas Bellinger const char *page, 1809c66ac9dbSNicholas Bellinger size_t count) 1810c66ac9dbSNicholas Bellinger { 1811c66ac9dbSNicholas Bellinger unsigned long tmp; 1812c66ac9dbSNicholas Bellinger int ret; 1813c66ac9dbSNicholas Bellinger 1814c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 1815c66ac9dbSNicholas Bellinger if (ret < 0) { 1816c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract trans_delay_msecs\n"); 1817c66ac9dbSNicholas Bellinger return -EINVAL; 1818c66ac9dbSNicholas Bellinger } 1819c66ac9dbSNicholas Bellinger if (tmp > ALUA_MAX_TRANS_DELAY_MSECS) { 1820c66ac9dbSNicholas Bellinger printk(KERN_ERR "Passed trans_delay_msecs: %lu, exceeds" 1821c66ac9dbSNicholas Bellinger " ALUA_MAX_TRANS_DELAY_MSECS: %d\n", tmp, 1822c66ac9dbSNicholas Bellinger ALUA_MAX_TRANS_DELAY_MSECS); 1823c66ac9dbSNicholas Bellinger return -EINVAL; 1824c66ac9dbSNicholas Bellinger } 1825c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_trans_delay_msecs = (int)tmp; 1826c66ac9dbSNicholas Bellinger 1827c66ac9dbSNicholas Bellinger return count; 1828c66ac9dbSNicholas Bellinger } 1829c66ac9dbSNicholas Bellinger 1830c66ac9dbSNicholas Bellinger ssize_t core_alua_show_preferred_bit( 1831c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1832c66ac9dbSNicholas Bellinger char *page) 1833c66ac9dbSNicholas Bellinger { 1834c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_pref); 1835c66ac9dbSNicholas Bellinger } 1836c66ac9dbSNicholas Bellinger 1837c66ac9dbSNicholas Bellinger ssize_t core_alua_store_preferred_bit( 1838c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1839c66ac9dbSNicholas Bellinger const char *page, 1840c66ac9dbSNicholas Bellinger size_t count) 1841c66ac9dbSNicholas Bellinger { 1842c66ac9dbSNicholas Bellinger unsigned long tmp; 1843c66ac9dbSNicholas Bellinger int ret; 1844c66ac9dbSNicholas Bellinger 1845c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 1846c66ac9dbSNicholas Bellinger if (ret < 0) { 1847c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract preferred ALUA value\n"); 1848c66ac9dbSNicholas Bellinger return -EINVAL; 1849c66ac9dbSNicholas Bellinger } 1850c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 1851c66ac9dbSNicholas Bellinger printk(KERN_ERR "Illegal value for preferred ALUA: %lu\n", tmp); 1852c66ac9dbSNicholas Bellinger return -EINVAL; 1853c66ac9dbSNicholas Bellinger } 1854c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_pref = (int)tmp; 1855c66ac9dbSNicholas Bellinger 1856c66ac9dbSNicholas Bellinger return count; 1857c66ac9dbSNicholas Bellinger } 1858c66ac9dbSNicholas Bellinger 1859c66ac9dbSNicholas Bellinger ssize_t core_alua_show_offline_bit(struct se_lun *lun, char *page) 1860c66ac9dbSNicholas Bellinger { 1861c66ac9dbSNicholas Bellinger if (!(lun->lun_sep)) 1862c66ac9dbSNicholas Bellinger return -ENODEV; 1863c66ac9dbSNicholas Bellinger 1864c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", 1865c66ac9dbSNicholas Bellinger atomic_read(&lun->lun_sep->sep_tg_pt_secondary_offline)); 1866c66ac9dbSNicholas Bellinger } 1867c66ac9dbSNicholas Bellinger 1868c66ac9dbSNicholas Bellinger ssize_t core_alua_store_offline_bit( 1869c66ac9dbSNicholas Bellinger struct se_lun *lun, 1870c66ac9dbSNicholas Bellinger const char *page, 1871c66ac9dbSNicholas Bellinger size_t count) 1872c66ac9dbSNicholas Bellinger { 1873c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1874c66ac9dbSNicholas Bellinger unsigned long tmp; 1875c66ac9dbSNicholas Bellinger int ret; 1876c66ac9dbSNicholas Bellinger 1877c66ac9dbSNicholas Bellinger if (!(lun->lun_sep)) 1878c66ac9dbSNicholas Bellinger return -ENODEV; 1879c66ac9dbSNicholas Bellinger 1880c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 1881c66ac9dbSNicholas Bellinger if (ret < 0) { 1882c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract alua_tg_pt_offline value\n"); 1883c66ac9dbSNicholas Bellinger return -EINVAL; 1884c66ac9dbSNicholas Bellinger } 1885c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 1886c66ac9dbSNicholas Bellinger printk(KERN_ERR "Illegal value for alua_tg_pt_offline: %lu\n", 1887c66ac9dbSNicholas Bellinger tmp); 1888c66ac9dbSNicholas Bellinger return -EINVAL; 1889c66ac9dbSNicholas Bellinger } 1890c66ac9dbSNicholas Bellinger tg_pt_gp_mem = lun->lun_sep->sep_alua_tg_pt_gp_mem; 1891c66ac9dbSNicholas Bellinger if (!(tg_pt_gp_mem)) { 1892c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to locate *tg_pt_gp_mem\n"); 1893c66ac9dbSNicholas Bellinger return -EINVAL; 1894c66ac9dbSNicholas Bellinger } 1895c66ac9dbSNicholas Bellinger 1896c66ac9dbSNicholas Bellinger ret = core_alua_set_tg_pt_secondary_state(tg_pt_gp_mem, 1897c66ac9dbSNicholas Bellinger lun->lun_sep, 0, (int)tmp); 1898c66ac9dbSNicholas Bellinger if (ret < 0) 1899c66ac9dbSNicholas Bellinger return -EINVAL; 1900c66ac9dbSNicholas Bellinger 1901c66ac9dbSNicholas Bellinger return count; 1902c66ac9dbSNicholas Bellinger } 1903c66ac9dbSNicholas Bellinger 1904c66ac9dbSNicholas Bellinger ssize_t core_alua_show_secondary_status( 1905c66ac9dbSNicholas Bellinger struct se_lun *lun, 1906c66ac9dbSNicholas Bellinger char *page) 1907c66ac9dbSNicholas Bellinger { 1908c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", lun->lun_sep->sep_tg_pt_secondary_stat); 1909c66ac9dbSNicholas Bellinger } 1910c66ac9dbSNicholas Bellinger 1911c66ac9dbSNicholas Bellinger ssize_t core_alua_store_secondary_status( 1912c66ac9dbSNicholas Bellinger struct se_lun *lun, 1913c66ac9dbSNicholas Bellinger const char *page, 1914c66ac9dbSNicholas Bellinger size_t count) 1915c66ac9dbSNicholas Bellinger { 1916c66ac9dbSNicholas Bellinger unsigned long tmp; 1917c66ac9dbSNicholas Bellinger int ret; 1918c66ac9dbSNicholas Bellinger 1919c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 1920c66ac9dbSNicholas Bellinger if (ret < 0) { 1921c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract alua_tg_pt_status\n"); 1922c66ac9dbSNicholas Bellinger return -EINVAL; 1923c66ac9dbSNicholas Bellinger } 1924c66ac9dbSNicholas Bellinger if ((tmp != ALUA_STATUS_NONE) && 1925c66ac9dbSNicholas Bellinger (tmp != ALUA_STATUS_ALTERED_BY_EXPLICT_STPG) && 1926c66ac9dbSNicholas Bellinger (tmp != ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA)) { 1927c66ac9dbSNicholas Bellinger printk(KERN_ERR "Illegal value for alua_tg_pt_status: %lu\n", 1928c66ac9dbSNicholas Bellinger tmp); 1929c66ac9dbSNicholas Bellinger return -EINVAL; 1930c66ac9dbSNicholas Bellinger } 1931c66ac9dbSNicholas Bellinger lun->lun_sep->sep_tg_pt_secondary_stat = (int)tmp; 1932c66ac9dbSNicholas Bellinger 1933c66ac9dbSNicholas Bellinger return count; 1934c66ac9dbSNicholas Bellinger } 1935c66ac9dbSNicholas Bellinger 1936c66ac9dbSNicholas Bellinger ssize_t core_alua_show_secondary_write_metadata( 1937c66ac9dbSNicholas Bellinger struct se_lun *lun, 1938c66ac9dbSNicholas Bellinger char *page) 1939c66ac9dbSNicholas Bellinger { 1940c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", 1941c66ac9dbSNicholas Bellinger lun->lun_sep->sep_tg_pt_secondary_write_md); 1942c66ac9dbSNicholas Bellinger } 1943c66ac9dbSNicholas Bellinger 1944c66ac9dbSNicholas Bellinger ssize_t core_alua_store_secondary_write_metadata( 1945c66ac9dbSNicholas Bellinger struct se_lun *lun, 1946c66ac9dbSNicholas Bellinger const char *page, 1947c66ac9dbSNicholas Bellinger size_t count) 1948c66ac9dbSNicholas Bellinger { 1949c66ac9dbSNicholas Bellinger unsigned long tmp; 1950c66ac9dbSNicholas Bellinger int ret; 1951c66ac9dbSNicholas Bellinger 1952c66ac9dbSNicholas Bellinger ret = strict_strtoul(page, 0, &tmp); 1953c66ac9dbSNicholas Bellinger if (ret < 0) { 1954c66ac9dbSNicholas Bellinger printk(KERN_ERR "Unable to extract alua_tg_pt_write_md\n"); 1955c66ac9dbSNicholas Bellinger return -EINVAL; 1956c66ac9dbSNicholas Bellinger } 1957c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 1958c66ac9dbSNicholas Bellinger printk(KERN_ERR "Illegal value for alua_tg_pt_write_md:" 1959c66ac9dbSNicholas Bellinger " %lu\n", tmp); 1960c66ac9dbSNicholas Bellinger return -EINVAL; 1961c66ac9dbSNicholas Bellinger } 1962c66ac9dbSNicholas Bellinger lun->lun_sep->sep_tg_pt_secondary_write_md = (int)tmp; 1963c66ac9dbSNicholas Bellinger 1964c66ac9dbSNicholas Bellinger return count; 1965c66ac9dbSNicholas Bellinger } 1966c66ac9dbSNicholas Bellinger 1967c66ac9dbSNicholas Bellinger int core_setup_alua(struct se_device *dev, int force_pt) 1968c66ac9dbSNicholas Bellinger { 1969c66ac9dbSNicholas Bellinger struct se_subsystem_dev *su_dev = dev->se_sub_dev; 1970e3d6f909SAndy Grover struct t10_alua *alua = &su_dev->t10_alua; 1971c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 1972c66ac9dbSNicholas Bellinger /* 1973c66ac9dbSNicholas Bellinger * If this device is from Target_Core_Mod/pSCSI, use the ALUA logic 1974c66ac9dbSNicholas Bellinger * of the Underlying SCSI hardware. In Linux/SCSI terms, this can 1975c66ac9dbSNicholas Bellinger * cause a problem because libata and some SATA RAID HBAs appear 1976c66ac9dbSNicholas Bellinger * under Linux/SCSI, but emulate SCSI logic themselves. 1977c66ac9dbSNicholas Bellinger */ 1978e3d6f909SAndy Grover if (((dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) && 1979e3d6f909SAndy Grover !(dev->se_sub_dev->se_dev_attrib.emulate_alua)) || force_pt) { 1980c66ac9dbSNicholas Bellinger alua->alua_type = SPC_ALUA_PASSTHROUGH; 1981c66ac9dbSNicholas Bellinger alua->alua_state_check = &core_alua_state_check_nop; 1982c66ac9dbSNicholas Bellinger printk(KERN_INFO "%s: Using SPC_ALUA_PASSTHROUGH, no ALUA" 1983e3d6f909SAndy Grover " emulation\n", dev->transport->name); 1984c66ac9dbSNicholas Bellinger return 0; 1985c66ac9dbSNicholas Bellinger } 1986c66ac9dbSNicholas Bellinger /* 1987c66ac9dbSNicholas Bellinger * If SPC-3 or above is reported by real or emulated struct se_device, 1988c66ac9dbSNicholas Bellinger * use emulated ALUA. 1989c66ac9dbSNicholas Bellinger */ 1990e3d6f909SAndy Grover if (dev->transport->get_device_rev(dev) >= SCSI_3) { 1991c66ac9dbSNicholas Bellinger printk(KERN_INFO "%s: Enabling ALUA Emulation for SPC-3" 1992e3d6f909SAndy Grover " device\n", dev->transport->name); 1993c66ac9dbSNicholas Bellinger /* 199425985edcSLucas De Marchi * Associate this struct se_device with the default ALUA 1995c66ac9dbSNicholas Bellinger * LUN Group. 1996c66ac9dbSNicholas Bellinger */ 1997c66ac9dbSNicholas Bellinger lu_gp_mem = core_alua_allocate_lu_gp_mem(dev); 1998e3d6f909SAndy Grover if (IS_ERR(lu_gp_mem)) 1999e3d6f909SAndy Grover return PTR_ERR(lu_gp_mem); 2000c66ac9dbSNicholas Bellinger 2001c66ac9dbSNicholas Bellinger alua->alua_type = SPC3_ALUA_EMULATED; 2002c66ac9dbSNicholas Bellinger alua->alua_state_check = &core_alua_state_check; 2003c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 2004c66ac9dbSNicholas Bellinger __core_alua_attach_lu_gp_mem(lu_gp_mem, 2005e3d6f909SAndy Grover default_lu_gp); 2006c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 2007c66ac9dbSNicholas Bellinger 2008c66ac9dbSNicholas Bellinger printk(KERN_INFO "%s: Adding to default ALUA LU Group:" 2009c66ac9dbSNicholas Bellinger " core/alua/lu_gps/default_lu_gp\n", 2010e3d6f909SAndy Grover dev->transport->name); 2011c66ac9dbSNicholas Bellinger } else { 2012c66ac9dbSNicholas Bellinger alua->alua_type = SPC2_ALUA_DISABLED; 2013c66ac9dbSNicholas Bellinger alua->alua_state_check = &core_alua_state_check_nop; 2014c66ac9dbSNicholas Bellinger printk(KERN_INFO "%s: Disabling ALUA Emulation for SPC-2" 2015e3d6f909SAndy Grover " device\n", dev->transport->name); 2016c66ac9dbSNicholas Bellinger } 2017c66ac9dbSNicholas Bellinger 2018c66ac9dbSNicholas Bellinger return 0; 2019c66ac9dbSNicholas Bellinger } 2020