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 * 64c76251eSNicholas Bellinger * (c) Copyright 2009-2013 Datera, Inc. 7c66ac9dbSNicholas Bellinger * 8c66ac9dbSNicholas Bellinger * Nicholas A. Bellinger <nab@kernel.org> 9c66ac9dbSNicholas Bellinger * 10c66ac9dbSNicholas Bellinger * This program is free software; you can redistribute it and/or modify 11c66ac9dbSNicholas Bellinger * it under the terms of the GNU General Public License as published by 12c66ac9dbSNicholas Bellinger * the Free Software Foundation; either version 2 of the License, or 13c66ac9dbSNicholas Bellinger * (at your option) any later version. 14c66ac9dbSNicholas Bellinger * 15c66ac9dbSNicholas Bellinger * This program is distributed in the hope that it will be useful, 16c66ac9dbSNicholas Bellinger * but WITHOUT ANY WARRANTY; without even the implied warranty of 17c66ac9dbSNicholas Bellinger * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18c66ac9dbSNicholas Bellinger * GNU General Public License for more details. 19c66ac9dbSNicholas Bellinger * 20c66ac9dbSNicholas Bellinger * You should have received a copy of the GNU General Public License 21c66ac9dbSNicholas Bellinger * along with this program; if not, write to the Free Software 22c66ac9dbSNicholas Bellinger * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23c66ac9dbSNicholas Bellinger * 24c66ac9dbSNicholas Bellinger ******************************************************************************/ 25c66ac9dbSNicholas Bellinger 26c66ac9dbSNicholas Bellinger #include <linux/slab.h> 27c66ac9dbSNicholas Bellinger #include <linux/spinlock.h> 28c66ac9dbSNicholas Bellinger #include <linux/configfs.h> 29c53181afSPaul Gortmaker #include <linux/export.h> 300e9b10a9SAl Viro #include <linux/file.h> 31c66ac9dbSNicholas Bellinger #include <scsi/scsi.h> 32c66ac9dbSNicholas Bellinger #include <scsi/scsi_cmnd.h> 3333395fb8SRoland Dreier #include <asm/unaligned.h> 34c66ac9dbSNicholas Bellinger 35c66ac9dbSNicholas Bellinger #include <target/target_core_base.h> 36c4795fb2SChristoph Hellwig #include <target/target_core_backend.h> 37c4795fb2SChristoph Hellwig #include <target/target_core_fabric.h> 38c66ac9dbSNicholas Bellinger #include <target/target_core_configfs.h> 39c66ac9dbSNicholas Bellinger 40e26d99aeSChristoph Hellwig #include "target_core_internal.h" 41c66ac9dbSNicholas Bellinger #include "target_core_alua.h" 42c66ac9dbSNicholas Bellinger #include "target_core_ua.h" 43c66ac9dbSNicholas Bellinger 44de103c93SChristoph Hellwig static sense_reason_t 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, 47125d0119SHannes Reinecke struct se_port *port, int explicit, 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 */ 62de103c93SChristoph Hellwig sense_reason_t 63de103c93SChristoph Hellwig target_emulate_report_target_port_groups(struct se_cmd *cmd) 64c66ac9dbSNicholas Bellinger { 650fd97ccfSChristoph Hellwig struct se_device *dev = cmd->se_dev; 66c66ac9dbSNicholas Bellinger struct se_port *port; 67c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 68c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 6905d1c7c0SAndy Grover unsigned char *buf; 705b9a4d72SNicholas Bellinger u32 rd_len = 0, off; 715b9a4d72SNicholas Bellinger int ext_hdr = (cmd->t_task_cdb[1] & 0x20); 72de103c93SChristoph Hellwig 736b20fa9aSNicholas Bellinger /* 745b9a4d72SNicholas Bellinger * Skip over RESERVED area to first Target port group descriptor 755b9a4d72SNicholas Bellinger * depending on the PARAMETER DATA FORMAT type.. 766b20fa9aSNicholas Bellinger */ 775b9a4d72SNicholas Bellinger if (ext_hdr != 0) 785b9a4d72SNicholas Bellinger off = 8; 795b9a4d72SNicholas Bellinger else 805b9a4d72SNicholas Bellinger off = 4; 815b9a4d72SNicholas Bellinger 825b9a4d72SNicholas Bellinger if (cmd->data_length < off) { 835b9a4d72SNicholas Bellinger pr_warn("REPORT TARGET PORT GROUPS allocation length %u too" 845b9a4d72SNicholas Bellinger " small for %s header\n", cmd->data_length, 855b9a4d72SNicholas Bellinger (ext_hdr) ? "extended" : "normal"); 86de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 876b20fa9aSNicholas Bellinger } 884949314cSAndy Grover buf = transport_kmap_data_sg(cmd); 89de103c93SChristoph Hellwig if (!buf) 90de103c93SChristoph Hellwig return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 9105d1c7c0SAndy Grover 920fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 930fd97ccfSChristoph Hellwig list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, 94c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 95c66ac9dbSNicholas Bellinger /* 966b20fa9aSNicholas Bellinger * Check if the Target port group and Target port descriptor list 976b20fa9aSNicholas Bellinger * based on tg_pt_gp_members count will fit into the response payload. 986b20fa9aSNicholas Bellinger * Otherwise, bump rd_len to let the initiator know we have exceeded 996b20fa9aSNicholas Bellinger * the allocation length and the response is truncated. 1006b20fa9aSNicholas Bellinger */ 1016b20fa9aSNicholas Bellinger if ((off + 8 + (tg_pt_gp->tg_pt_gp_members * 4)) > 1026b20fa9aSNicholas Bellinger cmd->data_length) { 1036b20fa9aSNicholas Bellinger rd_len += 8 + (tg_pt_gp->tg_pt_gp_members * 4); 1046b20fa9aSNicholas Bellinger continue; 1056b20fa9aSNicholas Bellinger } 1066b20fa9aSNicholas Bellinger /* 107c66ac9dbSNicholas Bellinger * PREF: Preferred target port bit, determine if this 108c66ac9dbSNicholas Bellinger * bit should be set for port group. 109c66ac9dbSNicholas Bellinger */ 110c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_pref) 111c66ac9dbSNicholas Bellinger buf[off] = 0x80; 112c66ac9dbSNicholas Bellinger /* 113c66ac9dbSNicholas Bellinger * Set the ASYMMETRIC ACCESS State 114c66ac9dbSNicholas Bellinger */ 115c66ac9dbSNicholas Bellinger buf[off++] |= (atomic_read( 116c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_alua_access_state) & 0xff); 117c66ac9dbSNicholas Bellinger /* 118c66ac9dbSNicholas Bellinger * Set supported ASYMMETRIC ACCESS State bits 119c66ac9dbSNicholas Bellinger */ 120c66ac9dbSNicholas Bellinger buf[off] = 0x80; /* T_SUP */ 121c66ac9dbSNicholas Bellinger buf[off] |= 0x40; /* O_SUP */ 122c66ac9dbSNicholas Bellinger buf[off] |= 0x8; /* U_SUP */ 123c66ac9dbSNicholas Bellinger buf[off] |= 0x4; /* S_SUP */ 124c66ac9dbSNicholas Bellinger buf[off] |= 0x2; /* AN_SUP */ 125c66ac9dbSNicholas Bellinger buf[off++] |= 0x1; /* AO_SUP */ 126c66ac9dbSNicholas Bellinger /* 127c66ac9dbSNicholas Bellinger * TARGET PORT GROUP 128c66ac9dbSNicholas Bellinger */ 129c66ac9dbSNicholas Bellinger buf[off++] = ((tg_pt_gp->tg_pt_gp_id >> 8) & 0xff); 130c66ac9dbSNicholas Bellinger buf[off++] = (tg_pt_gp->tg_pt_gp_id & 0xff); 131c66ac9dbSNicholas Bellinger 132c66ac9dbSNicholas Bellinger off++; /* Skip over Reserved */ 133c66ac9dbSNicholas Bellinger /* 134c66ac9dbSNicholas Bellinger * STATUS CODE 135c66ac9dbSNicholas Bellinger */ 136c66ac9dbSNicholas Bellinger buf[off++] = (tg_pt_gp->tg_pt_gp_alua_access_status & 0xff); 137c66ac9dbSNicholas Bellinger /* 138c66ac9dbSNicholas Bellinger * Vendor Specific field 139c66ac9dbSNicholas Bellinger */ 140c66ac9dbSNicholas Bellinger buf[off++] = 0x00; 141c66ac9dbSNicholas Bellinger /* 142c66ac9dbSNicholas Bellinger * TARGET PORT COUNT 143c66ac9dbSNicholas Bellinger */ 144c66ac9dbSNicholas Bellinger buf[off++] = (tg_pt_gp->tg_pt_gp_members & 0xff); 145c66ac9dbSNicholas Bellinger rd_len += 8; 146c66ac9dbSNicholas Bellinger 147c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 148c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp_mem, &tg_pt_gp->tg_pt_gp_mem_list, 149c66ac9dbSNicholas Bellinger tg_pt_gp_mem_list) { 150c66ac9dbSNicholas Bellinger port = tg_pt_gp_mem->tg_pt; 151c66ac9dbSNicholas Bellinger /* 152c66ac9dbSNicholas Bellinger * Start Target Port descriptor format 153c66ac9dbSNicholas Bellinger * 154c66ac9dbSNicholas Bellinger * See spc4r17 section 6.2.7 Table 247 155c66ac9dbSNicholas Bellinger */ 156c66ac9dbSNicholas Bellinger off += 2; /* Skip over Obsolete */ 157c66ac9dbSNicholas Bellinger /* 158c66ac9dbSNicholas Bellinger * Set RELATIVE TARGET PORT IDENTIFIER 159c66ac9dbSNicholas Bellinger */ 160c66ac9dbSNicholas Bellinger buf[off++] = ((port->sep_rtpi >> 8) & 0xff); 161c66ac9dbSNicholas Bellinger buf[off++] = (port->sep_rtpi & 0xff); 162c66ac9dbSNicholas Bellinger rd_len += 4; 163c66ac9dbSNicholas Bellinger } 164c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 165c66ac9dbSNicholas Bellinger } 1660fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 167c66ac9dbSNicholas Bellinger /* 168c66ac9dbSNicholas Bellinger * Set the RETURN DATA LENGTH set in the header of the DataIN Payload 169c66ac9dbSNicholas Bellinger */ 1705b9a4d72SNicholas Bellinger put_unaligned_be32(rd_len, &buf[0]); 171c66ac9dbSNicholas Bellinger 1725b9a4d72SNicholas Bellinger /* 1735b9a4d72SNicholas Bellinger * Fill in the Extended header parameter data format if requested 1745b9a4d72SNicholas Bellinger */ 1755b9a4d72SNicholas Bellinger if (ext_hdr != 0) { 1765b9a4d72SNicholas Bellinger buf[4] = 0x10; 1775b9a4d72SNicholas Bellinger /* 178125d0119SHannes Reinecke * Set the implicit transition time (in seconds) for the application 1795b9a4d72SNicholas Bellinger * client to use as a base for it's transition timeout value. 1805b9a4d72SNicholas Bellinger * 1815b9a4d72SNicholas Bellinger * Use the current tg_pt_gp_mem -> tg_pt_gp membership from the LUN 1825b9a4d72SNicholas Bellinger * this CDB was received upon to determine this value individually 1835b9a4d72SNicholas Bellinger * for ALUA target port group. 1845b9a4d72SNicholas Bellinger */ 1855b9a4d72SNicholas Bellinger port = cmd->se_lun->lun_sep; 1865b9a4d72SNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 1875b9a4d72SNicholas Bellinger if (tg_pt_gp_mem) { 1885b9a4d72SNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1895b9a4d72SNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 1905b9a4d72SNicholas Bellinger if (tg_pt_gp) 191125d0119SHannes Reinecke buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs; 1925b9a4d72SNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1935b9a4d72SNicholas Bellinger } 1945b9a4d72SNicholas Bellinger } 1954949314cSAndy Grover transport_kunmap_data_sg(cmd); 19605d1c7c0SAndy Grover 1976bb35e00SChristoph Hellwig target_complete_cmd(cmd, GOOD); 198c66ac9dbSNicholas Bellinger return 0; 199c66ac9dbSNicholas Bellinger } 200c66ac9dbSNicholas Bellinger 201c66ac9dbSNicholas Bellinger /* 202125d0119SHannes Reinecke * SET_TARGET_PORT_GROUPS for explicit ALUA operation. 203c66ac9dbSNicholas Bellinger * 204c66ac9dbSNicholas Bellinger * See spc4r17 section 6.35 205c66ac9dbSNicholas Bellinger */ 206de103c93SChristoph Hellwig sense_reason_t 207de103c93SChristoph Hellwig target_emulate_set_target_port_groups(struct se_cmd *cmd) 208c66ac9dbSNicholas Bellinger { 2095951146dSAndy Grover struct se_device *dev = cmd->se_dev; 210e3d6f909SAndy Grover struct se_port *port, *l_port = cmd->se_lun->lun_sep; 211e3d6f909SAndy Grover struct se_node_acl *nacl = cmd->se_sess->se_node_acl; 212c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp; 213c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; 21405d1c7c0SAndy Grover unsigned char *buf; 21505d1c7c0SAndy Grover unsigned char *ptr; 216a0d50f62SHannes Reinecke sense_reason_t rc = TCM_NO_SENSE; 217c66ac9dbSNicholas Bellinger u32 len = 4; /* Skip over RESERVED area in header */ 218de103c93SChristoph Hellwig int alua_access_state, primary = 0; 219c66ac9dbSNicholas Bellinger u16 tg_pt_id, rtpi; 220c66ac9dbSNicholas Bellinger 221de103c93SChristoph Hellwig if (!l_port) 222de103c93SChristoph Hellwig return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 223de103c93SChristoph Hellwig 2240d7f1299SPaolo Bonzini if (cmd->data_length < 4) { 2250d7f1299SPaolo Bonzini pr_warn("SET TARGET PORT GROUPS parameter list length %u too" 2260d7f1299SPaolo Bonzini " small\n", cmd->data_length); 227de103c93SChristoph Hellwig return TCM_INVALID_PARAMETER_LIST; 2280d7f1299SPaolo Bonzini } 2290d7f1299SPaolo Bonzini 2304949314cSAndy Grover buf = transport_kmap_data_sg(cmd); 231de103c93SChristoph Hellwig if (!buf) 232de103c93SChristoph Hellwig return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 23305d1c7c0SAndy Grover 234c66ac9dbSNicholas Bellinger /* 235125d0119SHannes Reinecke * Determine if explicit ALUA via SET_TARGET_PORT_GROUPS is allowed 236c66ac9dbSNicholas Bellinger * for the local tg_pt_gp. 237c66ac9dbSNicholas Bellinger */ 238c66ac9dbSNicholas Bellinger l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; 2396708bb27SAndy Grover if (!l_tg_pt_gp_mem) { 2406708bb27SAndy Grover pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); 241de103c93SChristoph Hellwig rc = TCM_UNSUPPORTED_SCSI_OPCODE; 24205d1c7c0SAndy Grover goto out; 243c66ac9dbSNicholas Bellinger } 244c66ac9dbSNicholas Bellinger spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 245c66ac9dbSNicholas Bellinger l_tg_pt_gp = l_tg_pt_gp_mem->tg_pt_gp; 2466708bb27SAndy Grover if (!l_tg_pt_gp) { 247c66ac9dbSNicholas Bellinger spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 2486708bb27SAndy Grover pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); 249de103c93SChristoph Hellwig rc = TCM_UNSUPPORTED_SCSI_OPCODE; 25005d1c7c0SAndy Grover goto out; 251c66ac9dbSNicholas Bellinger } 252c66ac9dbSNicholas Bellinger spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 253c66ac9dbSNicholas Bellinger 254125d0119SHannes Reinecke if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) { 2556708bb27SAndy Grover pr_debug("Unable to process SET_TARGET_PORT_GROUPS" 256125d0119SHannes Reinecke " while TPGS_EXPLICIT_ALUA is disabled\n"); 257de103c93SChristoph Hellwig rc = TCM_UNSUPPORTED_SCSI_OPCODE; 25805d1c7c0SAndy Grover goto out; 259c66ac9dbSNicholas Bellinger } 260c66ac9dbSNicholas Bellinger 26105d1c7c0SAndy Grover ptr = &buf[4]; /* Skip over RESERVED area in header */ 26205d1c7c0SAndy Grover 263c66ac9dbSNicholas Bellinger while (len < cmd->data_length) { 264de103c93SChristoph Hellwig bool found = false; 265c66ac9dbSNicholas Bellinger alua_access_state = (ptr[0] & 0x0f); 266c66ac9dbSNicholas Bellinger /* 267c66ac9dbSNicholas Bellinger * Check the received ALUA access state, and determine if 268c66ac9dbSNicholas Bellinger * the state is a primary or secondary target port asymmetric 269c66ac9dbSNicholas Bellinger * access state. 270c66ac9dbSNicholas Bellinger */ 271c66ac9dbSNicholas Bellinger rc = core_alua_check_transition(alua_access_state, &primary); 272de103c93SChristoph Hellwig if (rc) { 273c66ac9dbSNicholas Bellinger /* 274c66ac9dbSNicholas Bellinger * If the SET TARGET PORT GROUPS attempts to establish 275c66ac9dbSNicholas Bellinger * an invalid combination of target port asymmetric 276c66ac9dbSNicholas Bellinger * access states or attempts to establish an 277c66ac9dbSNicholas Bellinger * unsupported target port asymmetric access state, 278c66ac9dbSNicholas Bellinger * then the command shall be terminated with CHECK 279c66ac9dbSNicholas Bellinger * CONDITION status, with the sense key set to ILLEGAL 280c66ac9dbSNicholas Bellinger * REQUEST, and the additional sense code set to INVALID 281c66ac9dbSNicholas Bellinger * FIELD IN PARAMETER LIST. 282c66ac9dbSNicholas Bellinger */ 28305d1c7c0SAndy Grover goto out; 284c66ac9dbSNicholas Bellinger } 285de103c93SChristoph Hellwig 286c66ac9dbSNicholas Bellinger /* 287c66ac9dbSNicholas Bellinger * If the ASYMMETRIC ACCESS STATE field (see table 267) 288c66ac9dbSNicholas Bellinger * specifies a primary target port asymmetric access state, 289c66ac9dbSNicholas Bellinger * then the TARGET PORT GROUP OR TARGET PORT field specifies 290c66ac9dbSNicholas Bellinger * a primary target port group for which the primary target 291c66ac9dbSNicholas Bellinger * port asymmetric access state shall be changed. If the 292c66ac9dbSNicholas Bellinger * ASYMMETRIC ACCESS STATE field specifies a secondary target 293c66ac9dbSNicholas Bellinger * port asymmetric access state, then the TARGET PORT GROUP OR 294c66ac9dbSNicholas Bellinger * TARGET PORT field specifies the relative target port 295c66ac9dbSNicholas Bellinger * identifier (see 3.1.120) of the target port for which the 296c66ac9dbSNicholas Bellinger * secondary target port asymmetric access state shall be 297c66ac9dbSNicholas Bellinger * changed. 298c66ac9dbSNicholas Bellinger */ 299c66ac9dbSNicholas Bellinger if (primary) { 30033395fb8SRoland Dreier tg_pt_id = get_unaligned_be16(ptr + 2); 301c66ac9dbSNicholas Bellinger /* 302c66ac9dbSNicholas Bellinger * Locate the matching target port group ID from 303c66ac9dbSNicholas Bellinger * the global tg_pt_gp list 304c66ac9dbSNicholas Bellinger */ 3050fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 306c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp, 3070fd97ccfSChristoph Hellwig &dev->t10_alua.tg_pt_gps_list, 308c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 3096708bb27SAndy Grover if (!tg_pt_gp->tg_pt_gp_valid_id) 310c66ac9dbSNicholas Bellinger continue; 311c66ac9dbSNicholas Bellinger 312c66ac9dbSNicholas Bellinger if (tg_pt_id != tg_pt_gp->tg_pt_gp_id) 313c66ac9dbSNicholas Bellinger continue; 314c66ac9dbSNicholas Bellinger 315c66ac9dbSNicholas Bellinger atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 316c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 317de103c93SChristoph Hellwig 3180fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 319c66ac9dbSNicholas Bellinger 320de103c93SChristoph Hellwig if (!core_alua_do_port_transition(tg_pt_gp, 321c66ac9dbSNicholas Bellinger dev, l_port, nacl, 322de103c93SChristoph Hellwig alua_access_state, 1)) 323de103c93SChristoph Hellwig found = true; 324c66ac9dbSNicholas Bellinger 3250fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 326c66ac9dbSNicholas Bellinger atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 327c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 328c66ac9dbSNicholas Bellinger break; 329c66ac9dbSNicholas Bellinger } 3300fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 331c66ac9dbSNicholas Bellinger } else { 332c66ac9dbSNicholas Bellinger /* 333f1ae05d5SHannes Reinecke * Extract the RELATIVE TARGET PORT IDENTIFIER to identify 334c66ac9dbSNicholas Bellinger * the Target Port in question for the the incoming 335c66ac9dbSNicholas Bellinger * SET_TARGET_PORT_GROUPS op. 336c66ac9dbSNicholas Bellinger */ 33733395fb8SRoland Dreier rtpi = get_unaligned_be16(ptr + 2); 338c66ac9dbSNicholas Bellinger /* 33935d1efe8SMasanari Iida * Locate the matching relative target port identifier 340c66ac9dbSNicholas Bellinger * for the struct se_device storage object. 341c66ac9dbSNicholas Bellinger */ 342c66ac9dbSNicholas Bellinger spin_lock(&dev->se_port_lock); 343c66ac9dbSNicholas Bellinger list_for_each_entry(port, &dev->dev_sep_list, 344c66ac9dbSNicholas Bellinger sep_list) { 345c66ac9dbSNicholas Bellinger if (port->sep_rtpi != rtpi) 346c66ac9dbSNicholas Bellinger continue; 347c66ac9dbSNicholas Bellinger 348c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 349de103c93SChristoph Hellwig 350c66ac9dbSNicholas Bellinger spin_unlock(&dev->se_port_lock); 351c66ac9dbSNicholas Bellinger 352de103c93SChristoph Hellwig if (!core_alua_set_tg_pt_secondary_state( 353de103c93SChristoph Hellwig tg_pt_gp_mem, port, 1, 1)) 354de103c93SChristoph Hellwig found = true; 355c66ac9dbSNicholas Bellinger 356c66ac9dbSNicholas Bellinger spin_lock(&dev->se_port_lock); 357c66ac9dbSNicholas Bellinger break; 358c66ac9dbSNicholas Bellinger } 359c66ac9dbSNicholas Bellinger spin_unlock(&dev->se_port_lock); 36005d1c7c0SAndy Grover } 361de103c93SChristoph Hellwig 362de103c93SChristoph Hellwig if (!found) { 363de103c93SChristoph Hellwig rc = TCM_INVALID_PARAMETER_LIST; 364de103c93SChristoph Hellwig goto out; 365c66ac9dbSNicholas Bellinger } 366c66ac9dbSNicholas Bellinger 367c66ac9dbSNicholas Bellinger ptr += 4; 368c66ac9dbSNicholas Bellinger len += 4; 369c66ac9dbSNicholas Bellinger } 370c66ac9dbSNicholas Bellinger 37105d1c7c0SAndy Grover out: 3724949314cSAndy Grover transport_kunmap_data_sg(cmd); 37359e4f541SRoland Dreier if (!rc) 3746bb35e00SChristoph Hellwig target_complete_cmd(cmd, GOOD); 37559e4f541SRoland Dreier return rc; 376c66ac9dbSNicholas Bellinger } 377c66ac9dbSNicholas Bellinger 378c66ac9dbSNicholas Bellinger static inline int core_alua_state_nonoptimized( 379c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 380c66ac9dbSNicholas Bellinger unsigned char *cdb, 381c66ac9dbSNicholas Bellinger int nonop_delay_msecs, 382c66ac9dbSNicholas Bellinger u8 *alua_ascq) 383c66ac9dbSNicholas Bellinger { 384c66ac9dbSNicholas Bellinger /* 385c66ac9dbSNicholas Bellinger * Set SCF_ALUA_NON_OPTIMIZED here, this value will be checked 386c66ac9dbSNicholas Bellinger * later to determine if processing of this cmd needs to be 387c66ac9dbSNicholas Bellinger * temporarily delayed for the Active/NonOptimized primary access state. 388c66ac9dbSNicholas Bellinger */ 389c66ac9dbSNicholas Bellinger cmd->se_cmd_flags |= SCF_ALUA_NON_OPTIMIZED; 390c66ac9dbSNicholas Bellinger cmd->alua_nonop_delay = nonop_delay_msecs; 391c66ac9dbSNicholas Bellinger return 0; 392c66ac9dbSNicholas Bellinger } 393c66ac9dbSNicholas Bellinger 394c66ac9dbSNicholas Bellinger static inline int core_alua_state_standby( 395c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 396c66ac9dbSNicholas Bellinger unsigned char *cdb, 397c66ac9dbSNicholas Bellinger u8 *alua_ascq) 398c66ac9dbSNicholas Bellinger { 399c66ac9dbSNicholas Bellinger /* 400c66ac9dbSNicholas Bellinger * Allowed CDBs for ALUA_ACCESS_STATE_STANDBY as defined by 401c66ac9dbSNicholas Bellinger * spc4r17 section 5.9.2.4.4 402c66ac9dbSNicholas Bellinger */ 403c66ac9dbSNicholas Bellinger switch (cdb[0]) { 404c66ac9dbSNicholas Bellinger case INQUIRY: 405c66ac9dbSNicholas Bellinger case LOG_SELECT: 406c66ac9dbSNicholas Bellinger case LOG_SENSE: 407c66ac9dbSNicholas Bellinger case MODE_SELECT: 408c66ac9dbSNicholas Bellinger case MODE_SENSE: 409c66ac9dbSNicholas Bellinger case REPORT_LUNS: 410c66ac9dbSNicholas Bellinger case RECEIVE_DIAGNOSTIC: 411c66ac9dbSNicholas Bellinger case SEND_DIAGNOSTIC: 41230f359a6SNicholas Bellinger return 0; 413c66ac9dbSNicholas Bellinger case MAINTENANCE_IN: 414ba539743SNicholas Bellinger switch (cdb[1] & 0x1f) { 415c66ac9dbSNicholas Bellinger case MI_REPORT_TARGET_PGS: 416c66ac9dbSNicholas Bellinger return 0; 417c66ac9dbSNicholas Bellinger default: 418c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 419c66ac9dbSNicholas Bellinger return 1; 420c66ac9dbSNicholas Bellinger } 421c66ac9dbSNicholas Bellinger case MAINTENANCE_OUT: 422c66ac9dbSNicholas Bellinger switch (cdb[1]) { 423c66ac9dbSNicholas Bellinger case MO_SET_TARGET_PGS: 424c66ac9dbSNicholas Bellinger return 0; 425c66ac9dbSNicholas Bellinger default: 426c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 427c66ac9dbSNicholas Bellinger return 1; 428c66ac9dbSNicholas Bellinger } 429c66ac9dbSNicholas Bellinger case REQUEST_SENSE: 430c66ac9dbSNicholas Bellinger case PERSISTENT_RESERVE_IN: 431c66ac9dbSNicholas Bellinger case PERSISTENT_RESERVE_OUT: 432c66ac9dbSNicholas Bellinger case READ_BUFFER: 433c66ac9dbSNicholas Bellinger case WRITE_BUFFER: 434c66ac9dbSNicholas Bellinger return 0; 435c66ac9dbSNicholas Bellinger default: 436c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 437c66ac9dbSNicholas Bellinger return 1; 438c66ac9dbSNicholas Bellinger } 439c66ac9dbSNicholas Bellinger 440c66ac9dbSNicholas Bellinger return 0; 441c66ac9dbSNicholas Bellinger } 442c66ac9dbSNicholas Bellinger 443c66ac9dbSNicholas Bellinger static inline int core_alua_state_unavailable( 444c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 445c66ac9dbSNicholas Bellinger unsigned char *cdb, 446c66ac9dbSNicholas Bellinger u8 *alua_ascq) 447c66ac9dbSNicholas Bellinger { 448c66ac9dbSNicholas Bellinger /* 449c66ac9dbSNicholas Bellinger * Allowed CDBs for ALUA_ACCESS_STATE_UNAVAILABLE as defined by 450c66ac9dbSNicholas Bellinger * spc4r17 section 5.9.2.4.5 451c66ac9dbSNicholas Bellinger */ 452c66ac9dbSNicholas Bellinger switch (cdb[0]) { 453c66ac9dbSNicholas Bellinger case INQUIRY: 454c66ac9dbSNicholas Bellinger case REPORT_LUNS: 45530f359a6SNicholas Bellinger return 0; 456c66ac9dbSNicholas Bellinger case MAINTENANCE_IN: 457ba539743SNicholas Bellinger switch (cdb[1] & 0x1f) { 458c66ac9dbSNicholas Bellinger case MI_REPORT_TARGET_PGS: 459c66ac9dbSNicholas Bellinger return 0; 460c66ac9dbSNicholas Bellinger default: 461c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 462c66ac9dbSNicholas Bellinger return 1; 463c66ac9dbSNicholas Bellinger } 464c66ac9dbSNicholas Bellinger case MAINTENANCE_OUT: 465c66ac9dbSNicholas Bellinger switch (cdb[1]) { 466c66ac9dbSNicholas Bellinger case MO_SET_TARGET_PGS: 467c66ac9dbSNicholas Bellinger return 0; 468c66ac9dbSNicholas Bellinger default: 469c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 470c66ac9dbSNicholas Bellinger return 1; 471c66ac9dbSNicholas Bellinger } 472c66ac9dbSNicholas Bellinger case REQUEST_SENSE: 473c66ac9dbSNicholas Bellinger case READ_BUFFER: 474c66ac9dbSNicholas Bellinger case WRITE_BUFFER: 475c66ac9dbSNicholas Bellinger return 0; 476c66ac9dbSNicholas Bellinger default: 477c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 478c66ac9dbSNicholas Bellinger return 1; 479c66ac9dbSNicholas Bellinger } 480c66ac9dbSNicholas Bellinger 481c66ac9dbSNicholas Bellinger return 0; 482c66ac9dbSNicholas Bellinger } 483c66ac9dbSNicholas Bellinger 484c66ac9dbSNicholas Bellinger static inline int core_alua_state_transition( 485c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 486c66ac9dbSNicholas Bellinger unsigned char *cdb, 487c66ac9dbSNicholas Bellinger u8 *alua_ascq) 488c66ac9dbSNicholas Bellinger { 489c66ac9dbSNicholas Bellinger /* 490f1ae05d5SHannes Reinecke * Allowed CDBs for ALUA_ACCESS_STATE_TRANSITION as defined by 491c66ac9dbSNicholas Bellinger * spc4r17 section 5.9.2.5 492c66ac9dbSNicholas Bellinger */ 493c66ac9dbSNicholas Bellinger switch (cdb[0]) { 494c66ac9dbSNicholas Bellinger case INQUIRY: 495c66ac9dbSNicholas Bellinger case REPORT_LUNS: 49630f359a6SNicholas Bellinger return 0; 497c66ac9dbSNicholas Bellinger case MAINTENANCE_IN: 498ba539743SNicholas Bellinger switch (cdb[1] & 0x1f) { 499c66ac9dbSNicholas Bellinger case MI_REPORT_TARGET_PGS: 500c66ac9dbSNicholas Bellinger return 0; 501c66ac9dbSNicholas Bellinger default: 502c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_STATE_TRANSITION; 503c66ac9dbSNicholas Bellinger return 1; 504c66ac9dbSNicholas Bellinger } 505c66ac9dbSNicholas Bellinger case REQUEST_SENSE: 506c66ac9dbSNicholas Bellinger case READ_BUFFER: 507c66ac9dbSNicholas Bellinger case WRITE_BUFFER: 508c66ac9dbSNicholas Bellinger return 0; 509c66ac9dbSNicholas Bellinger default: 510c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_STATE_TRANSITION; 511c66ac9dbSNicholas Bellinger return 1; 512c66ac9dbSNicholas Bellinger } 513c66ac9dbSNicholas Bellinger 514c66ac9dbSNicholas Bellinger return 0; 515c66ac9dbSNicholas Bellinger } 516c66ac9dbSNicholas Bellinger 517c66ac9dbSNicholas Bellinger /* 518f1ae05d5SHannes Reinecke * return 1: Is used to signal LUN not accessible, and check condition/not ready 519c66ac9dbSNicholas Bellinger * return 0: Used to signal success 520f1ae05d5SHannes Reinecke * return -1: Used to signal failure, and invalid cdb field 521c66ac9dbSNicholas Bellinger */ 522de103c93SChristoph Hellwig sense_reason_t 523de103c93SChristoph Hellwig target_alua_state_check(struct se_cmd *cmd) 524c66ac9dbSNicholas Bellinger { 525c87fbd56SChristoph Hellwig struct se_device *dev = cmd->se_dev; 526c87fbd56SChristoph Hellwig unsigned char *cdb = cmd->t_task_cdb; 527e3d6f909SAndy Grover struct se_lun *lun = cmd->se_lun; 528c66ac9dbSNicholas Bellinger struct se_port *port = lun->lun_sep; 529c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 530c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 531c66ac9dbSNicholas Bellinger int out_alua_state, nonop_delay_msecs; 532c87fbd56SChristoph Hellwig u8 alua_ascq; 533c87fbd56SChristoph Hellwig int ret; 534c87fbd56SChristoph Hellwig 535c87fbd56SChristoph Hellwig if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) 536c87fbd56SChristoph Hellwig return 0; 537c87fbd56SChristoph Hellwig if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) 538c87fbd56SChristoph Hellwig return 0; 539c66ac9dbSNicholas Bellinger 5406708bb27SAndy Grover if (!port) 541c66ac9dbSNicholas Bellinger return 0; 542c66ac9dbSNicholas Bellinger /* 543c66ac9dbSNicholas Bellinger * First, check for a struct se_port specific secondary ALUA target port 544c66ac9dbSNicholas Bellinger * access state: OFFLINE 545c66ac9dbSNicholas Bellinger */ 546c66ac9dbSNicholas Bellinger if (atomic_read(&port->sep_tg_pt_secondary_offline)) { 5476708bb27SAndy Grover pr_debug("ALUA: Got secondary offline status for local" 548c66ac9dbSNicholas Bellinger " target port\n"); 549c87fbd56SChristoph Hellwig alua_ascq = ASCQ_04H_ALUA_OFFLINE; 550c87fbd56SChristoph Hellwig ret = 1; 551c87fbd56SChristoph Hellwig goto out; 552c66ac9dbSNicholas Bellinger } 553c66ac9dbSNicholas Bellinger /* 554c66ac9dbSNicholas Bellinger * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the 555c66ac9dbSNicholas Bellinger * ALUA target port group, to obtain current ALUA access state. 556c66ac9dbSNicholas Bellinger * Otherwise look for the underlying struct se_device association with 557c66ac9dbSNicholas Bellinger * a ALUA logical unit group. 558c66ac9dbSNicholas Bellinger */ 559c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 56089c12cc9SNicholas Bellinger if (!tg_pt_gp_mem) 56189c12cc9SNicholas Bellinger return 0; 56289c12cc9SNicholas Bellinger 563c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 564c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 565c66ac9dbSNicholas Bellinger out_alua_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); 566c66ac9dbSNicholas Bellinger nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs; 567c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 568c66ac9dbSNicholas Bellinger /* 56925985edcSLucas De Marchi * Process ALUA_ACCESS_STATE_ACTIVE_OPTMIZED in a separate conditional 57025985edcSLucas De Marchi * statement so the compiler knows explicitly to check this case first. 571c66ac9dbSNicholas Bellinger * For the Optimized ALUA access state case, we want to process the 572c66ac9dbSNicholas Bellinger * incoming fabric cmd ASAP.. 573c66ac9dbSNicholas Bellinger */ 574c66ac9dbSNicholas Bellinger if (out_alua_state == ALUA_ACCESS_STATE_ACTIVE_OPTMIZED) 575c66ac9dbSNicholas Bellinger return 0; 576c66ac9dbSNicholas Bellinger 577c66ac9dbSNicholas Bellinger switch (out_alua_state) { 578c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 579c87fbd56SChristoph Hellwig ret = core_alua_state_nonoptimized(cmd, cdb, 580c87fbd56SChristoph Hellwig nonop_delay_msecs, &alua_ascq); 581c87fbd56SChristoph Hellwig break; 582c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_STANDBY: 583c87fbd56SChristoph Hellwig ret = core_alua_state_standby(cmd, cdb, &alua_ascq); 584c87fbd56SChristoph Hellwig break; 585c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_UNAVAILABLE: 586c87fbd56SChristoph Hellwig ret = core_alua_state_unavailable(cmd, cdb, &alua_ascq); 587c87fbd56SChristoph Hellwig break; 588c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_TRANSITION: 589c87fbd56SChristoph Hellwig ret = core_alua_state_transition(cmd, cdb, &alua_ascq); 590c87fbd56SChristoph Hellwig break; 591c66ac9dbSNicholas Bellinger /* 592c66ac9dbSNicholas Bellinger * OFFLINE is a secondary ALUA target port group access state, that is 593c66ac9dbSNicholas Bellinger * handled above with struct se_port->sep_tg_pt_secondary_offline=1 594c66ac9dbSNicholas Bellinger */ 595c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_OFFLINE: 596c66ac9dbSNicholas Bellinger default: 5976708bb27SAndy Grover pr_err("Unknown ALUA access state: 0x%02x\n", 598c66ac9dbSNicholas Bellinger out_alua_state); 599de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 600c66ac9dbSNicholas Bellinger } 601c66ac9dbSNicholas Bellinger 602c87fbd56SChristoph Hellwig out: 603c87fbd56SChristoph Hellwig if (ret > 0) { 604c87fbd56SChristoph Hellwig /* 605c87fbd56SChristoph Hellwig * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; 606c87fbd56SChristoph Hellwig * The ALUA additional sense code qualifier (ASCQ) is determined 607c87fbd56SChristoph Hellwig * by the ALUA primary or secondary access state.. 608c87fbd56SChristoph Hellwig */ 609c87fbd56SChristoph Hellwig pr_debug("[%s]: ALUA TG Port not available, " 610c87fbd56SChristoph Hellwig "SenseKey: NOT_READY, ASC/ASCQ: " 611c87fbd56SChristoph Hellwig "0x04/0x%02x\n", 612c87fbd56SChristoph Hellwig cmd->se_tfo->get_fabric_name(), alua_ascq); 613c87fbd56SChristoph Hellwig 614c87fbd56SChristoph Hellwig cmd->scsi_asc = 0x04; 615c87fbd56SChristoph Hellwig cmd->scsi_ascq = alua_ascq; 616de103c93SChristoph Hellwig return TCM_CHECK_CONDITION_NOT_READY; 617c87fbd56SChristoph Hellwig } 618c87fbd56SChristoph Hellwig 619de103c93SChristoph Hellwig return 0; 620c66ac9dbSNicholas Bellinger } 621c66ac9dbSNicholas Bellinger 622c66ac9dbSNicholas Bellinger /* 623125d0119SHannes Reinecke * Check implicit and explicit ALUA state change request. 624c66ac9dbSNicholas Bellinger */ 625de103c93SChristoph Hellwig static sense_reason_t 626de103c93SChristoph Hellwig core_alua_check_transition(int state, int *primary) 627c66ac9dbSNicholas Bellinger { 628c66ac9dbSNicholas Bellinger switch (state) { 629c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: 630c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 631c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_STANDBY: 632c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_UNAVAILABLE: 633c66ac9dbSNicholas Bellinger /* 634c66ac9dbSNicholas Bellinger * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are 635c66ac9dbSNicholas Bellinger * defined as primary target port asymmetric access states. 636c66ac9dbSNicholas Bellinger */ 637c66ac9dbSNicholas Bellinger *primary = 1; 638c66ac9dbSNicholas Bellinger break; 639c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_OFFLINE: 640c66ac9dbSNicholas Bellinger /* 641c66ac9dbSNicholas Bellinger * OFFLINE state is defined as a secondary target port 642c66ac9dbSNicholas Bellinger * asymmetric access state. 643c66ac9dbSNicholas Bellinger */ 644c66ac9dbSNicholas Bellinger *primary = 0; 645c66ac9dbSNicholas Bellinger break; 646c66ac9dbSNicholas Bellinger default: 6476708bb27SAndy Grover pr_err("Unknown ALUA access state: 0x%02x\n", state); 648de103c93SChristoph Hellwig return TCM_INVALID_PARAMETER_LIST; 649c66ac9dbSNicholas Bellinger } 650c66ac9dbSNicholas Bellinger 651c66ac9dbSNicholas Bellinger return 0; 652c66ac9dbSNicholas Bellinger } 653c66ac9dbSNicholas Bellinger 654c66ac9dbSNicholas Bellinger static char *core_alua_dump_state(int state) 655c66ac9dbSNicholas Bellinger { 656c66ac9dbSNicholas Bellinger switch (state) { 657c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_OPTMIZED: 658c66ac9dbSNicholas Bellinger return "Active/Optimized"; 659c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 660c66ac9dbSNicholas Bellinger return "Active/NonOptimized"; 661c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_STANDBY: 662c66ac9dbSNicholas Bellinger return "Standby"; 663c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_UNAVAILABLE: 664c66ac9dbSNicholas Bellinger return "Unavailable"; 665c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_OFFLINE: 666c66ac9dbSNicholas Bellinger return "Offline"; 667c66ac9dbSNicholas Bellinger default: 668c66ac9dbSNicholas Bellinger return "Unknown"; 669c66ac9dbSNicholas Bellinger } 670c66ac9dbSNicholas Bellinger 671c66ac9dbSNicholas Bellinger return NULL; 672c66ac9dbSNicholas Bellinger } 673c66ac9dbSNicholas Bellinger 674c66ac9dbSNicholas Bellinger char *core_alua_dump_status(int status) 675c66ac9dbSNicholas Bellinger { 676c66ac9dbSNicholas Bellinger switch (status) { 677c66ac9dbSNicholas Bellinger case ALUA_STATUS_NONE: 678c66ac9dbSNicholas Bellinger return "None"; 679125d0119SHannes Reinecke case ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG: 680125d0119SHannes Reinecke return "Altered by Explicit STPG"; 681125d0119SHannes Reinecke case ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA: 682125d0119SHannes Reinecke return "Altered by Implicit ALUA"; 683c66ac9dbSNicholas Bellinger default: 684c66ac9dbSNicholas Bellinger return "Unknown"; 685c66ac9dbSNicholas Bellinger } 686c66ac9dbSNicholas Bellinger 687c66ac9dbSNicholas Bellinger return NULL; 688c66ac9dbSNicholas Bellinger } 689c66ac9dbSNicholas Bellinger 690c66ac9dbSNicholas Bellinger /* 691c66ac9dbSNicholas Bellinger * Used by fabric modules to determine when we need to delay processing 692c66ac9dbSNicholas Bellinger * for the Active/NonOptimized paths.. 693c66ac9dbSNicholas Bellinger */ 694c66ac9dbSNicholas Bellinger int core_alua_check_nonop_delay( 695c66ac9dbSNicholas Bellinger struct se_cmd *cmd) 696c66ac9dbSNicholas Bellinger { 697c66ac9dbSNicholas Bellinger if (!(cmd->se_cmd_flags & SCF_ALUA_NON_OPTIMIZED)) 698c66ac9dbSNicholas Bellinger return 0; 699c66ac9dbSNicholas Bellinger if (in_interrupt()) 700c66ac9dbSNicholas Bellinger return 0; 701c66ac9dbSNicholas Bellinger /* 702c66ac9dbSNicholas Bellinger * The ALUA Active/NonOptimized access state delay can be disabled 703c66ac9dbSNicholas Bellinger * in via configfs with a value of zero 704c66ac9dbSNicholas Bellinger */ 7056708bb27SAndy Grover if (!cmd->alua_nonop_delay) 706c66ac9dbSNicholas Bellinger return 0; 707c66ac9dbSNicholas Bellinger /* 708c66ac9dbSNicholas Bellinger * struct se_cmd->alua_nonop_delay gets set by a target port group 709c66ac9dbSNicholas Bellinger * defined interval in core_alua_state_nonoptimized() 710c66ac9dbSNicholas Bellinger */ 711c66ac9dbSNicholas Bellinger msleep_interruptible(cmd->alua_nonop_delay); 712c66ac9dbSNicholas Bellinger return 0; 713c66ac9dbSNicholas Bellinger } 714c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_alua_check_nonop_delay); 715c66ac9dbSNicholas Bellinger 716c66ac9dbSNicholas Bellinger /* 717c66ac9dbSNicholas Bellinger * Called with tg_pt_gp->tg_pt_gp_md_mutex or tg_pt_gp_mem->sep_tg_pt_md_mutex 718c66ac9dbSNicholas Bellinger * 719c66ac9dbSNicholas Bellinger */ 720c66ac9dbSNicholas Bellinger static int core_alua_write_tpg_metadata( 721c66ac9dbSNicholas Bellinger const char *path, 722c66ac9dbSNicholas Bellinger unsigned char *md_buf, 723c66ac9dbSNicholas Bellinger u32 md_buf_len) 724c66ac9dbSNicholas Bellinger { 7250e9b10a9SAl Viro struct file *file = filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600); 7260e9b10a9SAl Viro int ret; 727c66ac9dbSNicholas Bellinger 7280e9b10a9SAl Viro if (IS_ERR(file)) { 7290e9b10a9SAl Viro pr_err("filp_open(%s) for ALUA metadata failed\n", path); 730c66ac9dbSNicholas Bellinger return -ENODEV; 731c66ac9dbSNicholas Bellinger } 7320e9b10a9SAl Viro ret = kernel_write(file, md_buf, md_buf_len, 0); 7330e9b10a9SAl Viro if (ret < 0) 7346708bb27SAndy Grover pr_err("Error writing ALUA metadata file: %s\n", path); 7350e9b10a9SAl Viro fput(file); 736f730f915SGera Kazakov return (ret < 0) ? -EIO : 0; 737c66ac9dbSNicholas Bellinger } 738c66ac9dbSNicholas Bellinger 739c66ac9dbSNicholas Bellinger /* 740c66ac9dbSNicholas Bellinger * Called with tg_pt_gp->tg_pt_gp_md_mutex held 741c66ac9dbSNicholas Bellinger */ 742c66ac9dbSNicholas Bellinger static int core_alua_update_tpg_primary_metadata( 743c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 744c66ac9dbSNicholas Bellinger int primary_state, 745c66ac9dbSNicholas Bellinger unsigned char *md_buf) 746c66ac9dbSNicholas Bellinger { 7470fd97ccfSChristoph Hellwig struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn; 748c66ac9dbSNicholas Bellinger char path[ALUA_METADATA_PATH_LEN]; 749c66ac9dbSNicholas Bellinger int len; 750c66ac9dbSNicholas Bellinger 751c66ac9dbSNicholas Bellinger memset(path, 0, ALUA_METADATA_PATH_LEN); 752c66ac9dbSNicholas Bellinger 753c66ac9dbSNicholas Bellinger len = snprintf(md_buf, tg_pt_gp->tg_pt_gp_md_buf_len, 754c66ac9dbSNicholas Bellinger "tg_pt_gp_id=%hu\n" 755c66ac9dbSNicholas Bellinger "alua_access_state=0x%02x\n" 756c66ac9dbSNicholas Bellinger "alua_access_status=0x%02x\n", 757c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id, primary_state, 758c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_status); 759c66ac9dbSNicholas Bellinger 760c66ac9dbSNicholas Bellinger snprintf(path, ALUA_METADATA_PATH_LEN, 761c66ac9dbSNicholas Bellinger "/var/target/alua/tpgs_%s/%s", &wwn->unit_serial[0], 762c66ac9dbSNicholas Bellinger config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item)); 763c66ac9dbSNicholas Bellinger 764c66ac9dbSNicholas Bellinger return core_alua_write_tpg_metadata(path, md_buf, len); 765c66ac9dbSNicholas Bellinger } 766c66ac9dbSNicholas Bellinger 767c66ac9dbSNicholas Bellinger static int core_alua_do_transition_tg_pt( 768c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 769c66ac9dbSNicholas Bellinger struct se_port *l_port, 770c66ac9dbSNicholas Bellinger struct se_node_acl *nacl, 771c66ac9dbSNicholas Bellinger unsigned char *md_buf, 772c66ac9dbSNicholas Bellinger int new_state, 773125d0119SHannes Reinecke int explicit) 774c66ac9dbSNicholas Bellinger { 775c66ac9dbSNicholas Bellinger struct se_dev_entry *se_deve; 776c66ac9dbSNicholas Bellinger struct se_lun_acl *lacl; 777c66ac9dbSNicholas Bellinger struct se_port *port; 778c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *mem; 779c66ac9dbSNicholas Bellinger int old_state = 0; 780c66ac9dbSNicholas Bellinger /* 781c66ac9dbSNicholas Bellinger * Save the old primary ALUA access state, and set the current state 782c66ac9dbSNicholas Bellinger * to ALUA_ACCESS_STATE_TRANSITION. 783c66ac9dbSNicholas Bellinger */ 784c66ac9dbSNicholas Bellinger old_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); 785c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, 786c66ac9dbSNicholas Bellinger ALUA_ACCESS_STATE_TRANSITION); 787125d0119SHannes Reinecke tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ? 788125d0119SHannes Reinecke ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : 789125d0119SHannes Reinecke ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; 790c66ac9dbSNicholas Bellinger /* 791c66ac9dbSNicholas Bellinger * Check for the optional ALUA primary state transition delay 792c66ac9dbSNicholas Bellinger */ 793c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0) 794c66ac9dbSNicholas Bellinger msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs); 795c66ac9dbSNicholas Bellinger 796c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 797c66ac9dbSNicholas Bellinger list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list, 798c66ac9dbSNicholas Bellinger tg_pt_gp_mem_list) { 799c66ac9dbSNicholas Bellinger port = mem->tg_pt; 800c66ac9dbSNicholas Bellinger /* 801c66ac9dbSNicholas Bellinger * After an implicit target port asymmetric access state 802c66ac9dbSNicholas Bellinger * change, a device server shall establish a unit attention 803c66ac9dbSNicholas Bellinger * condition for the initiator port associated with every I_T 804c66ac9dbSNicholas Bellinger * nexus with the additional sense code set to ASYMMETRIC 805f1ae05d5SHannes Reinecke * ACCESS STATE CHANGED. 806c66ac9dbSNicholas Bellinger * 807c66ac9dbSNicholas Bellinger * After an explicit target port asymmetric access state 808c66ac9dbSNicholas Bellinger * change, a device server shall establish a unit attention 809c66ac9dbSNicholas Bellinger * condition with the additional sense code set to ASYMMETRIC 810c66ac9dbSNicholas Bellinger * ACCESS STATE CHANGED for the initiator port associated with 811c66ac9dbSNicholas Bellinger * every I_T nexus other than the I_T nexus on which the SET 812c66ac9dbSNicholas Bellinger * TARGET PORT GROUPS command 813c66ac9dbSNicholas Bellinger */ 814c66ac9dbSNicholas Bellinger atomic_inc(&mem->tg_pt_gp_mem_ref_cnt); 815c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 816c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 817c66ac9dbSNicholas Bellinger 818c66ac9dbSNicholas Bellinger spin_lock_bh(&port->sep_alua_lock); 819c66ac9dbSNicholas Bellinger list_for_each_entry(se_deve, &port->sep_alua_list, 820c66ac9dbSNicholas Bellinger alua_port_list) { 821c66ac9dbSNicholas Bellinger lacl = se_deve->se_lun_acl; 822c66ac9dbSNicholas Bellinger /* 823c66ac9dbSNicholas Bellinger * se_deve->se_lun_acl pointer may be NULL for a 824125d0119SHannes Reinecke * entry created without explicit Node+MappedLUN ACLs 825c66ac9dbSNicholas Bellinger */ 8266708bb27SAndy Grover if (!lacl) 827c66ac9dbSNicholas Bellinger continue; 828c66ac9dbSNicholas Bellinger 829125d0119SHannes Reinecke if (explicit && 830c66ac9dbSNicholas Bellinger (nacl != NULL) && (nacl == lacl->se_lun_nacl) && 831c66ac9dbSNicholas Bellinger (l_port != NULL) && (l_port == port)) 832c66ac9dbSNicholas Bellinger continue; 833c66ac9dbSNicholas Bellinger 834c66ac9dbSNicholas Bellinger core_scsi3_ua_allocate(lacl->se_lun_nacl, 835c66ac9dbSNicholas Bellinger se_deve->mapped_lun, 0x2A, 836c66ac9dbSNicholas Bellinger ASCQ_2AH_ASYMMETRIC_ACCESS_STATE_CHANGED); 837c66ac9dbSNicholas Bellinger } 838c66ac9dbSNicholas Bellinger spin_unlock_bh(&port->sep_alua_lock); 839c66ac9dbSNicholas Bellinger 840c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 841c66ac9dbSNicholas Bellinger atomic_dec(&mem->tg_pt_gp_mem_ref_cnt); 842c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 843c66ac9dbSNicholas Bellinger } 844c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 845c66ac9dbSNicholas Bellinger /* 846c66ac9dbSNicholas Bellinger * Update the ALUA metadata buf that has been allocated in 847c66ac9dbSNicholas Bellinger * core_alua_do_port_transition(), this metadata will be written 848c66ac9dbSNicholas Bellinger * to struct file. 849c66ac9dbSNicholas Bellinger * 850c66ac9dbSNicholas Bellinger * Note that there is the case where we do not want to update the 851c66ac9dbSNicholas Bellinger * metadata when the saved metadata is being parsed in userspace 852c66ac9dbSNicholas Bellinger * when setting the existing port access state and access status. 853c66ac9dbSNicholas Bellinger * 854c66ac9dbSNicholas Bellinger * Also note that the failure to write out the ALUA metadata to 855c66ac9dbSNicholas Bellinger * struct file does NOT affect the actual ALUA transition. 856c66ac9dbSNicholas Bellinger */ 857c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_write_metadata) { 858c66ac9dbSNicholas Bellinger mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex); 859c66ac9dbSNicholas Bellinger core_alua_update_tpg_primary_metadata(tg_pt_gp, 860c66ac9dbSNicholas Bellinger new_state, md_buf); 861c66ac9dbSNicholas Bellinger mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex); 862c66ac9dbSNicholas Bellinger } 863c66ac9dbSNicholas Bellinger /* 864c66ac9dbSNicholas Bellinger * Set the current primary ALUA access state to the requested new state 865c66ac9dbSNicholas Bellinger */ 866c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, new_state); 867c66ac9dbSNicholas Bellinger 8686708bb27SAndy Grover pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu" 869125d0119SHannes Reinecke " from primary access state %s to %s\n", (explicit) ? "explicit" : 870125d0119SHannes Reinecke "implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), 871c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id, core_alua_dump_state(old_state), 872c66ac9dbSNicholas Bellinger core_alua_dump_state(new_state)); 873c66ac9dbSNicholas Bellinger 874c66ac9dbSNicholas Bellinger return 0; 875c66ac9dbSNicholas Bellinger } 876c66ac9dbSNicholas Bellinger 877c66ac9dbSNicholas Bellinger int core_alua_do_port_transition( 878c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *l_tg_pt_gp, 879c66ac9dbSNicholas Bellinger struct se_device *l_dev, 880c66ac9dbSNicholas Bellinger struct se_port *l_port, 881c66ac9dbSNicholas Bellinger struct se_node_acl *l_nacl, 882c66ac9dbSNicholas Bellinger int new_state, 883125d0119SHannes Reinecke int explicit) 884c66ac9dbSNicholas Bellinger { 885c66ac9dbSNicholas Bellinger struct se_device *dev; 886c66ac9dbSNicholas Bellinger struct se_port *port; 887c66ac9dbSNicholas Bellinger struct se_node_acl *nacl; 888c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 889c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; 890c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 891c66ac9dbSNicholas Bellinger unsigned char *md_buf; 892c66ac9dbSNicholas Bellinger int primary; 893c66ac9dbSNicholas Bellinger 894c66ac9dbSNicholas Bellinger if (core_alua_check_transition(new_state, &primary) != 0) 895c66ac9dbSNicholas Bellinger return -EINVAL; 896c66ac9dbSNicholas Bellinger 897c66ac9dbSNicholas Bellinger md_buf = kzalloc(l_tg_pt_gp->tg_pt_gp_md_buf_len, GFP_KERNEL); 8986708bb27SAndy Grover if (!md_buf) { 8996708bb27SAndy Grover pr_err("Unable to allocate buf for ALUA metadata\n"); 900c66ac9dbSNicholas Bellinger return -ENOMEM; 901c66ac9dbSNicholas Bellinger } 902c66ac9dbSNicholas Bellinger 903c66ac9dbSNicholas Bellinger local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem; 904c66ac9dbSNicholas Bellinger spin_lock(&local_lu_gp_mem->lu_gp_mem_lock); 905c66ac9dbSNicholas Bellinger lu_gp = local_lu_gp_mem->lu_gp; 906c66ac9dbSNicholas Bellinger atomic_inc(&lu_gp->lu_gp_ref_cnt); 907c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 908c66ac9dbSNicholas Bellinger spin_unlock(&local_lu_gp_mem->lu_gp_mem_lock); 909c66ac9dbSNicholas Bellinger /* 910c66ac9dbSNicholas Bellinger * For storage objects that are members of the 'default_lu_gp', 911c66ac9dbSNicholas Bellinger * we only do transition on the passed *l_tp_pt_gp, and not 912c66ac9dbSNicholas Bellinger * on all of the matching target port groups IDs in default_lu_gp. 913c66ac9dbSNicholas Bellinger */ 9146708bb27SAndy Grover if (!lu_gp->lu_gp_id) { 915c66ac9dbSNicholas Bellinger /* 916c66ac9dbSNicholas Bellinger * core_alua_do_transition_tg_pt() will always return 917c66ac9dbSNicholas Bellinger * success. 918c66ac9dbSNicholas Bellinger */ 919c66ac9dbSNicholas Bellinger core_alua_do_transition_tg_pt(l_tg_pt_gp, l_port, l_nacl, 920125d0119SHannes Reinecke md_buf, new_state, explicit); 921c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp->lu_gp_ref_cnt); 922c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 923c66ac9dbSNicholas Bellinger kfree(md_buf); 924c66ac9dbSNicholas Bellinger return 0; 925c66ac9dbSNicholas Bellinger } 926c66ac9dbSNicholas Bellinger /* 927c66ac9dbSNicholas Bellinger * For all other LU groups aside from 'default_lu_gp', walk all of 928c66ac9dbSNicholas Bellinger * the associated storage objects looking for a matching target port 929c66ac9dbSNicholas Bellinger * group ID from the local target port group. 930c66ac9dbSNicholas Bellinger */ 931c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 932c66ac9dbSNicholas Bellinger list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, 933c66ac9dbSNicholas Bellinger lu_gp_mem_list) { 934c66ac9dbSNicholas Bellinger 935c66ac9dbSNicholas Bellinger dev = lu_gp_mem->lu_gp_mem_dev; 936c66ac9dbSNicholas Bellinger atomic_inc(&lu_gp_mem->lu_gp_mem_ref_cnt); 937c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 938c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 939c66ac9dbSNicholas Bellinger 9400fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 941c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp, 9420fd97ccfSChristoph Hellwig &dev->t10_alua.tg_pt_gps_list, 943c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 944c66ac9dbSNicholas Bellinger 9456708bb27SAndy Grover if (!tg_pt_gp->tg_pt_gp_valid_id) 946c66ac9dbSNicholas Bellinger continue; 947c66ac9dbSNicholas Bellinger /* 948c66ac9dbSNicholas Bellinger * If the target behavior port asymmetric access state 949f1ae05d5SHannes Reinecke * is changed for any target port group accessible via 950c66ac9dbSNicholas Bellinger * a logical unit within a LU group, the target port 951c66ac9dbSNicholas Bellinger * behavior group asymmetric access states for the same 952c66ac9dbSNicholas Bellinger * target port group accessible via other logical units 953c66ac9dbSNicholas Bellinger * in that LU group will also change. 954c66ac9dbSNicholas Bellinger */ 955c66ac9dbSNicholas Bellinger if (l_tg_pt_gp->tg_pt_gp_id != tg_pt_gp->tg_pt_gp_id) 956c66ac9dbSNicholas Bellinger continue; 957c66ac9dbSNicholas Bellinger 958c66ac9dbSNicholas Bellinger if (l_tg_pt_gp == tg_pt_gp) { 959c66ac9dbSNicholas Bellinger port = l_port; 960c66ac9dbSNicholas Bellinger nacl = l_nacl; 961c66ac9dbSNicholas Bellinger } else { 962c66ac9dbSNicholas Bellinger port = NULL; 963c66ac9dbSNicholas Bellinger nacl = NULL; 964c66ac9dbSNicholas Bellinger } 965c66ac9dbSNicholas Bellinger atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 966c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 9670fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 968c66ac9dbSNicholas Bellinger /* 969c66ac9dbSNicholas Bellinger * core_alua_do_transition_tg_pt() will always return 970c66ac9dbSNicholas Bellinger * success. 971c66ac9dbSNicholas Bellinger */ 972c66ac9dbSNicholas Bellinger core_alua_do_transition_tg_pt(tg_pt_gp, port, 973125d0119SHannes Reinecke nacl, md_buf, new_state, explicit); 974c66ac9dbSNicholas Bellinger 9750fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 976c66ac9dbSNicholas Bellinger atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 977c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 978c66ac9dbSNicholas Bellinger } 9790fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 980c66ac9dbSNicholas Bellinger 981c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 982c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp_mem->lu_gp_mem_ref_cnt); 983c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 984c66ac9dbSNicholas Bellinger } 985c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 986c66ac9dbSNicholas Bellinger 9876708bb27SAndy Grover pr_debug("Successfully processed LU Group: %s all ALUA TG PT" 988c66ac9dbSNicholas Bellinger " Group IDs: %hu %s transition to primary state: %s\n", 989c66ac9dbSNicholas Bellinger config_item_name(&lu_gp->lu_gp_group.cg_item), 990125d0119SHannes Reinecke l_tg_pt_gp->tg_pt_gp_id, (explicit) ? "explicit" : "implicit", 991c66ac9dbSNicholas Bellinger core_alua_dump_state(new_state)); 992c66ac9dbSNicholas Bellinger 993c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp->lu_gp_ref_cnt); 994c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 995c66ac9dbSNicholas Bellinger kfree(md_buf); 996c66ac9dbSNicholas Bellinger return 0; 997c66ac9dbSNicholas Bellinger } 998c66ac9dbSNicholas Bellinger 999c66ac9dbSNicholas Bellinger /* 1000c66ac9dbSNicholas Bellinger * Called with tg_pt_gp_mem->sep_tg_pt_md_mutex held 1001c66ac9dbSNicholas Bellinger */ 1002c66ac9dbSNicholas Bellinger static int core_alua_update_tpg_secondary_metadata( 1003c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 1004c66ac9dbSNicholas Bellinger struct se_port *port, 1005c66ac9dbSNicholas Bellinger unsigned char *md_buf, 1006c66ac9dbSNicholas Bellinger u32 md_buf_len) 1007c66ac9dbSNicholas Bellinger { 1008c66ac9dbSNicholas Bellinger struct se_portal_group *se_tpg = port->sep_tpg; 1009c66ac9dbSNicholas Bellinger char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN]; 1010c66ac9dbSNicholas Bellinger int len; 1011c66ac9dbSNicholas Bellinger 1012c66ac9dbSNicholas Bellinger memset(path, 0, ALUA_METADATA_PATH_LEN); 1013c66ac9dbSNicholas Bellinger memset(wwn, 0, ALUA_SECONDARY_METADATA_WWN_LEN); 1014c66ac9dbSNicholas Bellinger 1015c66ac9dbSNicholas Bellinger len = snprintf(wwn, ALUA_SECONDARY_METADATA_WWN_LEN, "%s", 1016e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg)); 1017c66ac9dbSNicholas Bellinger 1018e3d6f909SAndy Grover if (se_tpg->se_tpg_tfo->tpg_get_tag != NULL) 1019c66ac9dbSNicholas Bellinger snprintf(wwn+len, ALUA_SECONDARY_METADATA_WWN_LEN-len, "+%hu", 1020e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); 1021c66ac9dbSNicholas Bellinger 1022c66ac9dbSNicholas Bellinger len = snprintf(md_buf, md_buf_len, "alua_tg_pt_offline=%d\n" 1023c66ac9dbSNicholas Bellinger "alua_tg_pt_status=0x%02x\n", 1024c66ac9dbSNicholas Bellinger atomic_read(&port->sep_tg_pt_secondary_offline), 1025c66ac9dbSNicholas Bellinger port->sep_tg_pt_secondary_stat); 1026c66ac9dbSNicholas Bellinger 1027c66ac9dbSNicholas Bellinger snprintf(path, ALUA_METADATA_PATH_LEN, "/var/target/alua/%s/%s/lun_%u", 1028e3d6f909SAndy Grover se_tpg->se_tpg_tfo->get_fabric_name(), wwn, 1029c66ac9dbSNicholas Bellinger port->sep_lun->unpacked_lun); 1030c66ac9dbSNicholas Bellinger 1031c66ac9dbSNicholas Bellinger return core_alua_write_tpg_metadata(path, md_buf, len); 1032c66ac9dbSNicholas Bellinger } 1033c66ac9dbSNicholas Bellinger 1034c66ac9dbSNicholas Bellinger static int core_alua_set_tg_pt_secondary_state( 1035c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 1036c66ac9dbSNicholas Bellinger struct se_port *port, 1037125d0119SHannes Reinecke int explicit, 1038c66ac9dbSNicholas Bellinger int offline) 1039c66ac9dbSNicholas Bellinger { 1040c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1041c66ac9dbSNicholas Bellinger unsigned char *md_buf; 1042c66ac9dbSNicholas Bellinger u32 md_buf_len; 1043c66ac9dbSNicholas Bellinger int trans_delay_msecs; 1044c66ac9dbSNicholas Bellinger 1045c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1046c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 10476708bb27SAndy Grover if (!tg_pt_gp) { 1048c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 10496708bb27SAndy Grover pr_err("Unable to complete secondary state" 1050c66ac9dbSNicholas Bellinger " transition\n"); 1051e3d6f909SAndy Grover return -EINVAL; 1052c66ac9dbSNicholas Bellinger } 1053c66ac9dbSNicholas Bellinger trans_delay_msecs = tg_pt_gp->tg_pt_gp_trans_delay_msecs; 1054c66ac9dbSNicholas Bellinger /* 1055c66ac9dbSNicholas Bellinger * Set the secondary ALUA target port access state to OFFLINE 1056c66ac9dbSNicholas Bellinger * or release the previously secondary state for struct se_port 1057c66ac9dbSNicholas Bellinger */ 1058c66ac9dbSNicholas Bellinger if (offline) 1059c66ac9dbSNicholas Bellinger atomic_set(&port->sep_tg_pt_secondary_offline, 1); 1060c66ac9dbSNicholas Bellinger else 1061c66ac9dbSNicholas Bellinger atomic_set(&port->sep_tg_pt_secondary_offline, 0); 1062c66ac9dbSNicholas Bellinger 1063c66ac9dbSNicholas Bellinger md_buf_len = tg_pt_gp->tg_pt_gp_md_buf_len; 1064125d0119SHannes Reinecke port->sep_tg_pt_secondary_stat = (explicit) ? 1065125d0119SHannes Reinecke ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : 1066125d0119SHannes Reinecke ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; 1067c66ac9dbSNicholas Bellinger 10686708bb27SAndy Grover pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu" 1069125d0119SHannes Reinecke " to secondary access state: %s\n", (explicit) ? "explicit" : 1070125d0119SHannes Reinecke "implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), 1071c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE"); 1072c66ac9dbSNicholas Bellinger 1073c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1074c66ac9dbSNicholas Bellinger /* 1075c66ac9dbSNicholas Bellinger * Do the optional transition delay after we set the secondary 1076c66ac9dbSNicholas Bellinger * ALUA access state. 1077c66ac9dbSNicholas Bellinger */ 1078c66ac9dbSNicholas Bellinger if (trans_delay_msecs != 0) 1079c66ac9dbSNicholas Bellinger msleep_interruptible(trans_delay_msecs); 1080c66ac9dbSNicholas Bellinger /* 1081c66ac9dbSNicholas Bellinger * See if we need to update the ALUA fabric port metadata for 1082c66ac9dbSNicholas Bellinger * secondary state and status 1083c66ac9dbSNicholas Bellinger */ 1084c66ac9dbSNicholas Bellinger if (port->sep_tg_pt_secondary_write_md) { 1085c66ac9dbSNicholas Bellinger md_buf = kzalloc(md_buf_len, GFP_KERNEL); 10866708bb27SAndy Grover if (!md_buf) { 10876708bb27SAndy Grover pr_err("Unable to allocate md_buf for" 1088c66ac9dbSNicholas Bellinger " secondary ALUA access metadata\n"); 1089e3d6f909SAndy Grover return -ENOMEM; 1090c66ac9dbSNicholas Bellinger } 1091c66ac9dbSNicholas Bellinger mutex_lock(&port->sep_tg_pt_md_mutex); 1092c66ac9dbSNicholas Bellinger core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port, 1093c66ac9dbSNicholas Bellinger md_buf, md_buf_len); 1094c66ac9dbSNicholas Bellinger mutex_unlock(&port->sep_tg_pt_md_mutex); 1095c66ac9dbSNicholas Bellinger 1096c66ac9dbSNicholas Bellinger kfree(md_buf); 1097c66ac9dbSNicholas Bellinger } 1098c66ac9dbSNicholas Bellinger 1099c66ac9dbSNicholas Bellinger return 0; 1100c66ac9dbSNicholas Bellinger } 1101c66ac9dbSNicholas Bellinger 1102c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp * 1103c66ac9dbSNicholas Bellinger core_alua_allocate_lu_gp(const char *name, int def_group) 1104c66ac9dbSNicholas Bellinger { 1105c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1106c66ac9dbSNicholas Bellinger 1107c66ac9dbSNicholas Bellinger lu_gp = kmem_cache_zalloc(t10_alua_lu_gp_cache, GFP_KERNEL); 11086708bb27SAndy Grover if (!lu_gp) { 11096708bb27SAndy Grover pr_err("Unable to allocate struct t10_alua_lu_gp\n"); 11106eab04a8SJustin P. Mattock return ERR_PTR(-ENOMEM); 1111c66ac9dbSNicholas Bellinger } 1112e3d6f909SAndy Grover INIT_LIST_HEAD(&lu_gp->lu_gp_node); 1113c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lu_gp->lu_gp_mem_list); 1114c66ac9dbSNicholas Bellinger spin_lock_init(&lu_gp->lu_gp_lock); 1115c66ac9dbSNicholas Bellinger atomic_set(&lu_gp->lu_gp_ref_cnt, 0); 1116c66ac9dbSNicholas Bellinger 1117c66ac9dbSNicholas Bellinger if (def_group) { 1118e3d6f909SAndy Grover lu_gp->lu_gp_id = alua_lu_gps_counter++; 1119c66ac9dbSNicholas Bellinger lu_gp->lu_gp_valid_id = 1; 1120e3d6f909SAndy Grover alua_lu_gps_count++; 1121c66ac9dbSNicholas Bellinger } 1122c66ac9dbSNicholas Bellinger 1123c66ac9dbSNicholas Bellinger return lu_gp; 1124c66ac9dbSNicholas Bellinger } 1125c66ac9dbSNicholas Bellinger 1126c66ac9dbSNicholas Bellinger int core_alua_set_lu_gp_id(struct t10_alua_lu_gp *lu_gp, u16 lu_gp_id) 1127c66ac9dbSNicholas Bellinger { 1128c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp_tmp; 1129c66ac9dbSNicholas Bellinger u16 lu_gp_id_tmp; 1130c66ac9dbSNicholas Bellinger /* 1131c66ac9dbSNicholas Bellinger * The lu_gp->lu_gp_id may only be set once.. 1132c66ac9dbSNicholas Bellinger */ 1133c66ac9dbSNicholas Bellinger if (lu_gp->lu_gp_valid_id) { 11346708bb27SAndy Grover pr_warn("ALUA LU Group already has a valid ID," 1135c66ac9dbSNicholas Bellinger " ignoring request\n"); 1136e3d6f909SAndy Grover return -EINVAL; 1137c66ac9dbSNicholas Bellinger } 1138c66ac9dbSNicholas Bellinger 1139e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1140e3d6f909SAndy Grover if (alua_lu_gps_count == 0x0000ffff) { 11416708bb27SAndy Grover pr_err("Maximum ALUA alua_lu_gps_count:" 1142c66ac9dbSNicholas Bellinger " 0x0000ffff reached\n"); 1143e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1144c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_lu_gp_cache, lu_gp); 1145e3d6f909SAndy Grover return -ENOSPC; 1146c66ac9dbSNicholas Bellinger } 1147c66ac9dbSNicholas Bellinger again: 1148c66ac9dbSNicholas Bellinger lu_gp_id_tmp = (lu_gp_id != 0) ? lu_gp_id : 1149e3d6f909SAndy Grover alua_lu_gps_counter++; 1150c66ac9dbSNicholas Bellinger 1151e3d6f909SAndy Grover list_for_each_entry(lu_gp_tmp, &lu_gps_list, lu_gp_node) { 1152c66ac9dbSNicholas Bellinger if (lu_gp_tmp->lu_gp_id == lu_gp_id_tmp) { 11536708bb27SAndy Grover if (!lu_gp_id) 1154c66ac9dbSNicholas Bellinger goto again; 1155c66ac9dbSNicholas Bellinger 11566708bb27SAndy Grover pr_warn("ALUA Logical Unit Group ID: %hu" 1157c66ac9dbSNicholas Bellinger " already exists, ignoring request\n", 1158c66ac9dbSNicholas Bellinger lu_gp_id); 1159e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1160e3d6f909SAndy Grover return -EINVAL; 1161c66ac9dbSNicholas Bellinger } 1162c66ac9dbSNicholas Bellinger } 1163c66ac9dbSNicholas Bellinger 1164c66ac9dbSNicholas Bellinger lu_gp->lu_gp_id = lu_gp_id_tmp; 1165c66ac9dbSNicholas Bellinger lu_gp->lu_gp_valid_id = 1; 1166e3d6f909SAndy Grover list_add_tail(&lu_gp->lu_gp_node, &lu_gps_list); 1167e3d6f909SAndy Grover alua_lu_gps_count++; 1168e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1169c66ac9dbSNicholas Bellinger 1170c66ac9dbSNicholas Bellinger return 0; 1171c66ac9dbSNicholas Bellinger } 1172c66ac9dbSNicholas Bellinger 1173c66ac9dbSNicholas Bellinger static struct t10_alua_lu_gp_member * 1174c66ac9dbSNicholas Bellinger core_alua_allocate_lu_gp_mem(struct se_device *dev) 1175c66ac9dbSNicholas Bellinger { 1176c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 1177c66ac9dbSNicholas Bellinger 1178c66ac9dbSNicholas Bellinger lu_gp_mem = kmem_cache_zalloc(t10_alua_lu_gp_mem_cache, GFP_KERNEL); 11796708bb27SAndy Grover if (!lu_gp_mem) { 11806708bb27SAndy Grover pr_err("Unable to allocate struct t10_alua_lu_gp_member\n"); 1181c66ac9dbSNicholas Bellinger return ERR_PTR(-ENOMEM); 1182c66ac9dbSNicholas Bellinger } 1183c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lu_gp_mem->lu_gp_mem_list); 1184c66ac9dbSNicholas Bellinger spin_lock_init(&lu_gp_mem->lu_gp_mem_lock); 1185c66ac9dbSNicholas Bellinger atomic_set(&lu_gp_mem->lu_gp_mem_ref_cnt, 0); 1186c66ac9dbSNicholas Bellinger 1187c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_mem_dev = dev; 1188c66ac9dbSNicholas Bellinger dev->dev_alua_lu_gp_mem = lu_gp_mem; 1189c66ac9dbSNicholas Bellinger 1190c66ac9dbSNicholas Bellinger return lu_gp_mem; 1191c66ac9dbSNicholas Bellinger } 1192c66ac9dbSNicholas Bellinger 1193c66ac9dbSNicholas Bellinger void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp) 1194c66ac9dbSNicholas Bellinger { 1195c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, *lu_gp_mem_tmp; 1196c66ac9dbSNicholas Bellinger /* 1197c66ac9dbSNicholas Bellinger * Once we have reached this point, config_item_put() has 1198c66ac9dbSNicholas Bellinger * already been called from target_core_alua_drop_lu_gp(). 1199c66ac9dbSNicholas Bellinger * 1200c66ac9dbSNicholas Bellinger * Here, we remove the *lu_gp from the global list so that 1201c66ac9dbSNicholas Bellinger * no associations can be made while we are releasing 1202c66ac9dbSNicholas Bellinger * struct t10_alua_lu_gp. 1203c66ac9dbSNicholas Bellinger */ 1204e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1205e3d6f909SAndy Grover list_del(&lu_gp->lu_gp_node); 1206e3d6f909SAndy Grover alua_lu_gps_count--; 1207e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1208c66ac9dbSNicholas Bellinger /* 1209c66ac9dbSNicholas Bellinger * Allow struct t10_alua_lu_gp * referenced by core_alua_get_lu_gp_by_name() 1210c66ac9dbSNicholas Bellinger * in target_core_configfs.c:target_core_store_alua_lu_gp() to be 1211c66ac9dbSNicholas Bellinger * released with core_alua_put_lu_gp_from_name() 1212c66ac9dbSNicholas Bellinger */ 1213c66ac9dbSNicholas Bellinger while (atomic_read(&lu_gp->lu_gp_ref_cnt)) 1214c66ac9dbSNicholas Bellinger cpu_relax(); 1215c66ac9dbSNicholas Bellinger /* 1216c66ac9dbSNicholas Bellinger * Release reference to struct t10_alua_lu_gp * from all associated 1217c66ac9dbSNicholas Bellinger * struct se_device. 1218c66ac9dbSNicholas Bellinger */ 1219c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1220c66ac9dbSNicholas Bellinger list_for_each_entry_safe(lu_gp_mem, lu_gp_mem_tmp, 1221c66ac9dbSNicholas Bellinger &lu_gp->lu_gp_mem_list, lu_gp_mem_list) { 1222c66ac9dbSNicholas Bellinger if (lu_gp_mem->lu_gp_assoc) { 1223c66ac9dbSNicholas Bellinger list_del(&lu_gp_mem->lu_gp_mem_list); 1224c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members--; 1225c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 0; 1226c66ac9dbSNicholas Bellinger } 1227c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1228c66ac9dbSNicholas Bellinger /* 1229c66ac9dbSNicholas Bellinger * 123025985edcSLucas De Marchi * lu_gp_mem is associated with a single 1231c66ac9dbSNicholas Bellinger * struct se_device->dev_alua_lu_gp_mem, and is released when 1232c66ac9dbSNicholas Bellinger * struct se_device is released via core_alua_free_lu_gp_mem(). 1233c66ac9dbSNicholas Bellinger * 1234c66ac9dbSNicholas Bellinger * If the passed lu_gp does NOT match the default_lu_gp, assume 1235f1ae05d5SHannes Reinecke * we want to re-associate a given lu_gp_mem with default_lu_gp. 1236c66ac9dbSNicholas Bellinger */ 1237c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 1238e3d6f909SAndy Grover if (lu_gp != default_lu_gp) 1239c66ac9dbSNicholas Bellinger __core_alua_attach_lu_gp_mem(lu_gp_mem, 1240e3d6f909SAndy Grover default_lu_gp); 1241c66ac9dbSNicholas Bellinger else 1242c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = NULL; 1243c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 1244c66ac9dbSNicholas Bellinger 1245c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1246c66ac9dbSNicholas Bellinger } 1247c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1248c66ac9dbSNicholas Bellinger 1249c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_lu_gp_cache, lu_gp); 1250c66ac9dbSNicholas Bellinger } 1251c66ac9dbSNicholas Bellinger 1252c66ac9dbSNicholas Bellinger void core_alua_free_lu_gp_mem(struct se_device *dev) 1253c66ac9dbSNicholas Bellinger { 1254c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1255c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 1256c66ac9dbSNicholas Bellinger 1257c66ac9dbSNicholas Bellinger lu_gp_mem = dev->dev_alua_lu_gp_mem; 12586708bb27SAndy Grover if (!lu_gp_mem) 1259c66ac9dbSNicholas Bellinger return; 1260c66ac9dbSNicholas Bellinger 1261c66ac9dbSNicholas Bellinger while (atomic_read(&lu_gp_mem->lu_gp_mem_ref_cnt)) 1262c66ac9dbSNicholas Bellinger cpu_relax(); 1263c66ac9dbSNicholas Bellinger 1264c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 1265c66ac9dbSNicholas Bellinger lu_gp = lu_gp_mem->lu_gp; 12666708bb27SAndy Grover if (lu_gp) { 1267c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1268c66ac9dbSNicholas Bellinger if (lu_gp_mem->lu_gp_assoc) { 1269c66ac9dbSNicholas Bellinger list_del(&lu_gp_mem->lu_gp_mem_list); 1270c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members--; 1271c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 0; 1272c66ac9dbSNicholas Bellinger } 1273c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1274c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = NULL; 1275c66ac9dbSNicholas Bellinger } 1276c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 1277c66ac9dbSNicholas Bellinger 1278c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_lu_gp_mem_cache, lu_gp_mem); 1279c66ac9dbSNicholas Bellinger } 1280c66ac9dbSNicholas Bellinger 1281c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *core_alua_get_lu_gp_by_name(const char *name) 1282c66ac9dbSNicholas Bellinger { 1283c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1284c66ac9dbSNicholas Bellinger struct config_item *ci; 1285c66ac9dbSNicholas Bellinger 1286e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1287e3d6f909SAndy Grover list_for_each_entry(lu_gp, &lu_gps_list, lu_gp_node) { 12886708bb27SAndy Grover if (!lu_gp->lu_gp_valid_id) 1289c66ac9dbSNicholas Bellinger continue; 1290c66ac9dbSNicholas Bellinger ci = &lu_gp->lu_gp_group.cg_item; 12916708bb27SAndy Grover if (!strcmp(config_item_name(ci), name)) { 1292c66ac9dbSNicholas Bellinger atomic_inc(&lu_gp->lu_gp_ref_cnt); 1293e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1294c66ac9dbSNicholas Bellinger return lu_gp; 1295c66ac9dbSNicholas Bellinger } 1296c66ac9dbSNicholas Bellinger } 1297e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1298c66ac9dbSNicholas Bellinger 1299c66ac9dbSNicholas Bellinger return NULL; 1300c66ac9dbSNicholas Bellinger } 1301c66ac9dbSNicholas Bellinger 1302c66ac9dbSNicholas Bellinger void core_alua_put_lu_gp_from_name(struct t10_alua_lu_gp *lu_gp) 1303c66ac9dbSNicholas Bellinger { 1304e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1305c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp->lu_gp_ref_cnt); 1306e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1307c66ac9dbSNicholas Bellinger } 1308c66ac9dbSNicholas Bellinger 1309c66ac9dbSNicholas Bellinger /* 1310c66ac9dbSNicholas Bellinger * Called with struct t10_alua_lu_gp_member->lu_gp_mem_lock 1311c66ac9dbSNicholas Bellinger */ 1312c66ac9dbSNicholas Bellinger void __core_alua_attach_lu_gp_mem( 1313c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, 1314c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp) 1315c66ac9dbSNicholas Bellinger { 1316c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1317c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = lu_gp; 1318c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 1; 1319c66ac9dbSNicholas Bellinger list_add_tail(&lu_gp_mem->lu_gp_mem_list, &lu_gp->lu_gp_mem_list); 1320c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members++; 1321c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1322c66ac9dbSNicholas Bellinger } 1323c66ac9dbSNicholas Bellinger 1324c66ac9dbSNicholas Bellinger /* 1325c66ac9dbSNicholas Bellinger * Called with struct t10_alua_lu_gp_member->lu_gp_mem_lock 1326c66ac9dbSNicholas Bellinger */ 1327c66ac9dbSNicholas Bellinger void __core_alua_drop_lu_gp_mem( 1328c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, 1329c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp) 1330c66ac9dbSNicholas Bellinger { 1331c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1332c66ac9dbSNicholas Bellinger list_del(&lu_gp_mem->lu_gp_mem_list); 1333c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = NULL; 1334c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 0; 1335c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members--; 1336c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1337c66ac9dbSNicholas Bellinger } 1338c66ac9dbSNicholas Bellinger 13390fd97ccfSChristoph Hellwig struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev, 13400fd97ccfSChristoph Hellwig const char *name, int def_group) 1341c66ac9dbSNicholas Bellinger { 1342c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1343c66ac9dbSNicholas Bellinger 1344c66ac9dbSNicholas Bellinger tg_pt_gp = kmem_cache_zalloc(t10_alua_tg_pt_gp_cache, GFP_KERNEL); 13456708bb27SAndy Grover if (!tg_pt_gp) { 13466708bb27SAndy Grover pr_err("Unable to allocate struct t10_alua_tg_pt_gp\n"); 1347c66ac9dbSNicholas Bellinger return NULL; 1348c66ac9dbSNicholas Bellinger } 1349c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_list); 1350c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_mem_list); 1351c66ac9dbSNicholas Bellinger mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); 1352c66ac9dbSNicholas Bellinger spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); 1353c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); 13540fd97ccfSChristoph Hellwig tg_pt_gp->tg_pt_gp_dev = dev; 1355c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_md_buf_len = ALUA_MD_BUF_LEN; 1356c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, 1357c66ac9dbSNicholas Bellinger ALUA_ACCESS_STATE_ACTIVE_OPTMIZED); 1358c66ac9dbSNicholas Bellinger /* 1359125d0119SHannes Reinecke * Enable both explicit and implicit ALUA support by default 1360c66ac9dbSNicholas Bellinger */ 1361c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = 1362125d0119SHannes Reinecke TPGS_EXPLICIT_ALUA | TPGS_IMPLICIT_ALUA; 1363c66ac9dbSNicholas Bellinger /* 1364c66ac9dbSNicholas Bellinger * Set the default Active/NonOptimized Delay in milliseconds 1365c66ac9dbSNicholas Bellinger */ 1366c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS; 1367c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS; 1368125d0119SHannes Reinecke tg_pt_gp->tg_pt_gp_implicit_trans_secs = ALUA_DEFAULT_IMPLICIT_TRANS_SECS; 1369c66ac9dbSNicholas Bellinger 1370c66ac9dbSNicholas Bellinger if (def_group) { 13710fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1372c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id = 13730fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_counter++; 1374c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_valid_id = 1; 13750fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_count++; 1376c66ac9dbSNicholas Bellinger list_add_tail(&tg_pt_gp->tg_pt_gp_list, 13770fd97ccfSChristoph Hellwig &dev->t10_alua.tg_pt_gps_list); 13780fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1379c66ac9dbSNicholas Bellinger } 1380c66ac9dbSNicholas Bellinger 1381c66ac9dbSNicholas Bellinger return tg_pt_gp; 1382c66ac9dbSNicholas Bellinger } 1383c66ac9dbSNicholas Bellinger 1384c66ac9dbSNicholas Bellinger int core_alua_set_tg_pt_gp_id( 1385c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1386c66ac9dbSNicholas Bellinger u16 tg_pt_gp_id) 1387c66ac9dbSNicholas Bellinger { 13880fd97ccfSChristoph Hellwig struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; 1389c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp_tmp; 1390c66ac9dbSNicholas Bellinger u16 tg_pt_gp_id_tmp; 13910fd97ccfSChristoph Hellwig 1392c66ac9dbSNicholas Bellinger /* 1393c66ac9dbSNicholas Bellinger * The tg_pt_gp->tg_pt_gp_id may only be set once.. 1394c66ac9dbSNicholas Bellinger */ 1395c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_valid_id) { 13966708bb27SAndy Grover pr_warn("ALUA TG PT Group already has a valid ID," 1397c66ac9dbSNicholas Bellinger " ignoring request\n"); 1398e3d6f909SAndy Grover return -EINVAL; 1399c66ac9dbSNicholas Bellinger } 1400c66ac9dbSNicholas Bellinger 14010fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 14020fd97ccfSChristoph Hellwig if (dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) { 14036708bb27SAndy Grover pr_err("Maximum ALUA alua_tg_pt_gps_count:" 1404c66ac9dbSNicholas Bellinger " 0x0000ffff reached\n"); 14050fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1406c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); 1407e3d6f909SAndy Grover return -ENOSPC; 1408c66ac9dbSNicholas Bellinger } 1409c66ac9dbSNicholas Bellinger again: 1410c66ac9dbSNicholas Bellinger tg_pt_gp_id_tmp = (tg_pt_gp_id != 0) ? tg_pt_gp_id : 14110fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_counter++; 1412c66ac9dbSNicholas Bellinger 14130fd97ccfSChristoph Hellwig list_for_each_entry(tg_pt_gp_tmp, &dev->t10_alua.tg_pt_gps_list, 1414c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 1415c66ac9dbSNicholas Bellinger if (tg_pt_gp_tmp->tg_pt_gp_id == tg_pt_gp_id_tmp) { 14166708bb27SAndy Grover if (!tg_pt_gp_id) 1417c66ac9dbSNicholas Bellinger goto again; 1418c66ac9dbSNicholas Bellinger 14196708bb27SAndy Grover pr_err("ALUA Target Port Group ID: %hu already" 1420c66ac9dbSNicholas Bellinger " exists, ignoring request\n", tg_pt_gp_id); 14210fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1422e3d6f909SAndy Grover return -EINVAL; 1423c66ac9dbSNicholas Bellinger } 1424c66ac9dbSNicholas Bellinger } 1425c66ac9dbSNicholas Bellinger 1426c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id = tg_pt_gp_id_tmp; 1427c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_valid_id = 1; 1428c66ac9dbSNicholas Bellinger list_add_tail(&tg_pt_gp->tg_pt_gp_list, 14290fd97ccfSChristoph Hellwig &dev->t10_alua.tg_pt_gps_list); 14300fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_count++; 14310fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1432c66ac9dbSNicholas Bellinger 1433c66ac9dbSNicholas Bellinger return 0; 1434c66ac9dbSNicholas Bellinger } 1435c66ac9dbSNicholas Bellinger 1436c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( 1437c66ac9dbSNicholas Bellinger struct se_port *port) 1438c66ac9dbSNicholas Bellinger { 1439c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1440c66ac9dbSNicholas Bellinger 1441c66ac9dbSNicholas Bellinger tg_pt_gp_mem = kmem_cache_zalloc(t10_alua_tg_pt_gp_mem_cache, 1442c66ac9dbSNicholas Bellinger GFP_KERNEL); 14436708bb27SAndy Grover if (!tg_pt_gp_mem) { 14446708bb27SAndy Grover pr_err("Unable to allocate struct t10_alua_tg_pt_gp_member\n"); 1445c66ac9dbSNicholas Bellinger return ERR_PTR(-ENOMEM); 1446c66ac9dbSNicholas Bellinger } 1447c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1448c66ac9dbSNicholas Bellinger spin_lock_init(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1449c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt, 0); 1450c66ac9dbSNicholas Bellinger 1451c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt = port; 1452c66ac9dbSNicholas Bellinger port->sep_alua_tg_pt_gp_mem = tg_pt_gp_mem; 1453c66ac9dbSNicholas Bellinger 1454c66ac9dbSNicholas Bellinger return tg_pt_gp_mem; 1455c66ac9dbSNicholas Bellinger } 1456c66ac9dbSNicholas Bellinger 1457c66ac9dbSNicholas Bellinger void core_alua_free_tg_pt_gp( 1458c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1459c66ac9dbSNicholas Bellinger { 14600fd97ccfSChristoph Hellwig struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; 1461c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *tg_pt_gp_mem_tmp; 14620fd97ccfSChristoph Hellwig 1463c66ac9dbSNicholas Bellinger /* 1464c66ac9dbSNicholas Bellinger * Once we have reached this point, config_item_put() has already 1465c66ac9dbSNicholas Bellinger * been called from target_core_alua_drop_tg_pt_gp(). 1466c66ac9dbSNicholas Bellinger * 1467c66ac9dbSNicholas Bellinger * Here we remove *tg_pt_gp from the global list so that 1468f1ae05d5SHannes Reinecke * no associations *OR* explicit ALUA via SET_TARGET_PORT_GROUPS 1469c66ac9dbSNicholas Bellinger * can be made while we are releasing struct t10_alua_tg_pt_gp. 1470c66ac9dbSNicholas Bellinger */ 14710fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1472c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp->tg_pt_gp_list); 14730fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_counter--; 14740fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 14750fd97ccfSChristoph Hellwig 1476c66ac9dbSNicholas Bellinger /* 1477c66ac9dbSNicholas Bellinger * Allow a struct t10_alua_tg_pt_gp_member * referenced by 1478c66ac9dbSNicholas Bellinger * core_alua_get_tg_pt_gp_by_name() in 1479c66ac9dbSNicholas Bellinger * target_core_configfs.c:target_core_store_alua_tg_pt_gp() 1480c66ac9dbSNicholas Bellinger * to be released with core_alua_put_tg_pt_gp_from_name(). 1481c66ac9dbSNicholas Bellinger */ 1482c66ac9dbSNicholas Bellinger while (atomic_read(&tg_pt_gp->tg_pt_gp_ref_cnt)) 1483c66ac9dbSNicholas Bellinger cpu_relax(); 14840fd97ccfSChristoph Hellwig 1485c66ac9dbSNicholas Bellinger /* 1486c66ac9dbSNicholas Bellinger * Release reference to struct t10_alua_tg_pt_gp from all associated 1487c66ac9dbSNicholas Bellinger * struct se_port. 1488c66ac9dbSNicholas Bellinger */ 1489c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1490c66ac9dbSNicholas Bellinger list_for_each_entry_safe(tg_pt_gp_mem, tg_pt_gp_mem_tmp, 1491c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_mem_list, tg_pt_gp_mem_list) { 1492c66ac9dbSNicholas Bellinger if (tg_pt_gp_mem->tg_pt_gp_assoc) { 1493c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1494c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members--; 1495c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 0; 1496c66ac9dbSNicholas Bellinger } 1497c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1498c66ac9dbSNicholas Bellinger /* 149925985edcSLucas De Marchi * tg_pt_gp_mem is associated with a single 1500c66ac9dbSNicholas Bellinger * se_port->sep_alua_tg_pt_gp_mem, and is released via 1501c66ac9dbSNicholas Bellinger * core_alua_free_tg_pt_gp_mem(). 1502c66ac9dbSNicholas Bellinger * 1503c66ac9dbSNicholas Bellinger * If the passed tg_pt_gp does NOT match the default_tg_pt_gp, 1504f1ae05d5SHannes Reinecke * assume we want to re-associate a given tg_pt_gp_mem with 1505c66ac9dbSNicholas Bellinger * default_tg_pt_gp. 1506c66ac9dbSNicholas Bellinger */ 1507c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 15080fd97ccfSChristoph Hellwig if (tg_pt_gp != dev->t10_alua.default_tg_pt_gp) { 1509c66ac9dbSNicholas Bellinger __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, 15100fd97ccfSChristoph Hellwig dev->t10_alua.default_tg_pt_gp); 1511c66ac9dbSNicholas Bellinger } else 1512c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = NULL; 1513c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1514c66ac9dbSNicholas Bellinger 1515c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1516c66ac9dbSNicholas Bellinger } 1517c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1518c66ac9dbSNicholas Bellinger 1519c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); 1520c66ac9dbSNicholas Bellinger } 1521c66ac9dbSNicholas Bellinger 1522c66ac9dbSNicholas Bellinger void core_alua_free_tg_pt_gp_mem(struct se_port *port) 1523c66ac9dbSNicholas Bellinger { 1524c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1525c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1526c66ac9dbSNicholas Bellinger 1527c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 15286708bb27SAndy Grover if (!tg_pt_gp_mem) 1529c66ac9dbSNicholas Bellinger return; 1530c66ac9dbSNicholas Bellinger 1531c66ac9dbSNicholas Bellinger while (atomic_read(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt)) 1532c66ac9dbSNicholas Bellinger cpu_relax(); 1533c66ac9dbSNicholas Bellinger 1534c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1535c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 15366708bb27SAndy Grover if (tg_pt_gp) { 1537c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1538c66ac9dbSNicholas Bellinger if (tg_pt_gp_mem->tg_pt_gp_assoc) { 1539c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1540c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members--; 1541c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 0; 1542c66ac9dbSNicholas Bellinger } 1543c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1544c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = NULL; 1545c66ac9dbSNicholas Bellinger } 1546c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1547c66ac9dbSNicholas Bellinger 1548c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_tg_pt_gp_mem_cache, tg_pt_gp_mem); 1549c66ac9dbSNicholas Bellinger } 1550c66ac9dbSNicholas Bellinger 1551c66ac9dbSNicholas Bellinger static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( 15520fd97ccfSChristoph Hellwig struct se_device *dev, const char *name) 1553c66ac9dbSNicholas Bellinger { 1554c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1555c66ac9dbSNicholas Bellinger struct config_item *ci; 1556c66ac9dbSNicholas Bellinger 15570fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 15580fd97ccfSChristoph Hellwig list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, 1559c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 15606708bb27SAndy Grover if (!tg_pt_gp->tg_pt_gp_valid_id) 1561c66ac9dbSNicholas Bellinger continue; 1562c66ac9dbSNicholas Bellinger ci = &tg_pt_gp->tg_pt_gp_group.cg_item; 15636708bb27SAndy Grover if (!strcmp(config_item_name(ci), name)) { 1564c66ac9dbSNicholas Bellinger atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 15650fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1566c66ac9dbSNicholas Bellinger return tg_pt_gp; 1567c66ac9dbSNicholas Bellinger } 1568c66ac9dbSNicholas Bellinger } 15690fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1570c66ac9dbSNicholas Bellinger 1571c66ac9dbSNicholas Bellinger return NULL; 1572c66ac9dbSNicholas Bellinger } 1573c66ac9dbSNicholas Bellinger 1574c66ac9dbSNicholas Bellinger static void core_alua_put_tg_pt_gp_from_name( 1575c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1576c66ac9dbSNicholas Bellinger { 15770fd97ccfSChristoph Hellwig struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; 1578c66ac9dbSNicholas Bellinger 15790fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1580c66ac9dbSNicholas Bellinger atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 15810fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1582c66ac9dbSNicholas Bellinger } 1583c66ac9dbSNicholas Bellinger 1584c66ac9dbSNicholas Bellinger /* 1585c66ac9dbSNicholas Bellinger * Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held 1586c66ac9dbSNicholas Bellinger */ 1587c66ac9dbSNicholas Bellinger void __core_alua_attach_tg_pt_gp_mem( 1588c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 1589c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1590c66ac9dbSNicholas Bellinger { 1591c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1592c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = tg_pt_gp; 1593c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 1; 1594c66ac9dbSNicholas Bellinger list_add_tail(&tg_pt_gp_mem->tg_pt_gp_mem_list, 1595c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_mem_list); 1596c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members++; 1597c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1598c66ac9dbSNicholas Bellinger } 1599c66ac9dbSNicholas Bellinger 1600c66ac9dbSNicholas Bellinger /* 1601c66ac9dbSNicholas Bellinger * Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held 1602c66ac9dbSNicholas Bellinger */ 1603c66ac9dbSNicholas Bellinger static void __core_alua_drop_tg_pt_gp_mem( 1604c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 1605c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1606c66ac9dbSNicholas Bellinger { 1607c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1608c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1609c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = NULL; 1610c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 0; 1611c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members--; 1612c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1613c66ac9dbSNicholas Bellinger } 1614c66ac9dbSNicholas Bellinger 1615c66ac9dbSNicholas Bellinger ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page) 1616c66ac9dbSNicholas Bellinger { 1617c66ac9dbSNicholas Bellinger struct config_item *tg_pt_ci; 1618c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1619c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1620c66ac9dbSNicholas Bellinger ssize_t len = 0; 1621c66ac9dbSNicholas Bellinger 1622c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 16236708bb27SAndy Grover if (!tg_pt_gp_mem) 1624c66ac9dbSNicholas Bellinger return len; 1625c66ac9dbSNicholas Bellinger 1626c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1627c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 16286708bb27SAndy Grover if (tg_pt_gp) { 1629c66ac9dbSNicholas Bellinger tg_pt_ci = &tg_pt_gp->tg_pt_gp_group.cg_item; 1630c66ac9dbSNicholas Bellinger len += sprintf(page, "TG Port Alias: %s\nTG Port Group ID:" 1631c66ac9dbSNicholas Bellinger " %hu\nTG Port Primary Access State: %s\nTG Port " 1632c66ac9dbSNicholas Bellinger "Primary Access Status: %s\nTG Port Secondary Access" 1633c66ac9dbSNicholas Bellinger " State: %s\nTG Port Secondary Access Status: %s\n", 1634c66ac9dbSNicholas Bellinger config_item_name(tg_pt_ci), tg_pt_gp->tg_pt_gp_id, 1635c66ac9dbSNicholas Bellinger core_alua_dump_state(atomic_read( 1636c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_alua_access_state)), 1637c66ac9dbSNicholas Bellinger core_alua_dump_status( 1638c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_status), 1639c66ac9dbSNicholas Bellinger (atomic_read(&port->sep_tg_pt_secondary_offline)) ? 1640c66ac9dbSNicholas Bellinger "Offline" : "None", 1641c66ac9dbSNicholas Bellinger core_alua_dump_status(port->sep_tg_pt_secondary_stat)); 1642c66ac9dbSNicholas Bellinger } 1643c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1644c66ac9dbSNicholas Bellinger 1645c66ac9dbSNicholas Bellinger return len; 1646c66ac9dbSNicholas Bellinger } 1647c66ac9dbSNicholas Bellinger 1648c66ac9dbSNicholas Bellinger ssize_t core_alua_store_tg_pt_gp_info( 1649c66ac9dbSNicholas Bellinger struct se_port *port, 1650c66ac9dbSNicholas Bellinger const char *page, 1651c66ac9dbSNicholas Bellinger size_t count) 1652c66ac9dbSNicholas Bellinger { 1653c66ac9dbSNicholas Bellinger struct se_portal_group *tpg; 1654c66ac9dbSNicholas Bellinger struct se_lun *lun; 16550fd97ccfSChristoph Hellwig struct se_device *dev = port->sep_lun->lun_se_dev; 1656c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL; 1657c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1658c66ac9dbSNicholas Bellinger unsigned char buf[TG_PT_GROUP_NAME_BUF]; 1659c66ac9dbSNicholas Bellinger int move = 0; 1660c66ac9dbSNicholas Bellinger 1661c66ac9dbSNicholas Bellinger tpg = port->sep_tpg; 1662c66ac9dbSNicholas Bellinger lun = port->sep_lun; 1663c66ac9dbSNicholas Bellinger 1664c87fbd56SChristoph Hellwig tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 1665c87fbd56SChristoph Hellwig if (!tg_pt_gp_mem) 1666c87fbd56SChristoph Hellwig return 0; 1667c66ac9dbSNicholas Bellinger 1668c66ac9dbSNicholas Bellinger if (count > TG_PT_GROUP_NAME_BUF) { 16696708bb27SAndy Grover pr_err("ALUA Target Port Group alias too large!\n"); 1670c66ac9dbSNicholas Bellinger return -EINVAL; 1671c66ac9dbSNicholas Bellinger } 1672c66ac9dbSNicholas Bellinger memset(buf, 0, TG_PT_GROUP_NAME_BUF); 1673c66ac9dbSNicholas Bellinger memcpy(buf, page, count); 1674c66ac9dbSNicholas Bellinger /* 1675c66ac9dbSNicholas Bellinger * Any ALUA target port group alias besides "NULL" means we will be 1676c66ac9dbSNicholas Bellinger * making a new group association. 1677c66ac9dbSNicholas Bellinger */ 1678c66ac9dbSNicholas Bellinger if (strcmp(strstrip(buf), "NULL")) { 1679c66ac9dbSNicholas Bellinger /* 1680c66ac9dbSNicholas Bellinger * core_alua_get_tg_pt_gp_by_name() will increment reference to 1681c66ac9dbSNicholas Bellinger * struct t10_alua_tg_pt_gp. This reference is released with 1682c66ac9dbSNicholas Bellinger * core_alua_put_tg_pt_gp_from_name() below. 1683c66ac9dbSNicholas Bellinger */ 16840fd97ccfSChristoph Hellwig tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(dev, 1685c66ac9dbSNicholas Bellinger strstrip(buf)); 16866708bb27SAndy Grover if (!tg_pt_gp_new) 1687c66ac9dbSNicholas Bellinger return -ENODEV; 1688c66ac9dbSNicholas Bellinger } 1689c66ac9dbSNicholas Bellinger 1690c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1691c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 16926708bb27SAndy Grover if (tg_pt_gp) { 1693c66ac9dbSNicholas Bellinger /* 1694c66ac9dbSNicholas Bellinger * Clearing an existing tg_pt_gp association, and replacing 1695c66ac9dbSNicholas Bellinger * with the default_tg_pt_gp. 1696c66ac9dbSNicholas Bellinger */ 16976708bb27SAndy Grover if (!tg_pt_gp_new) { 16986708bb27SAndy Grover pr_debug("Target_Core_ConfigFS: Moving" 1699c66ac9dbSNicholas Bellinger " %s/tpgt_%hu/%s from ALUA Target Port Group:" 1700c66ac9dbSNicholas Bellinger " alua/%s, ID: %hu back to" 1701c66ac9dbSNicholas Bellinger " default_tg_pt_gp\n", 1702e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_wwn(tpg), 1703e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), 1704c66ac9dbSNicholas Bellinger config_item_name(&lun->lun_group.cg_item), 1705c66ac9dbSNicholas Bellinger config_item_name( 1706c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_group.cg_item), 1707c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id); 1708c66ac9dbSNicholas Bellinger 1709c66ac9dbSNicholas Bellinger __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); 1710c66ac9dbSNicholas Bellinger __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, 17110fd97ccfSChristoph Hellwig dev->t10_alua.default_tg_pt_gp); 1712c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1713c66ac9dbSNicholas Bellinger 1714c66ac9dbSNicholas Bellinger return count; 1715c66ac9dbSNicholas Bellinger } 1716c66ac9dbSNicholas Bellinger /* 1717c66ac9dbSNicholas Bellinger * Removing existing association of tg_pt_gp_mem with tg_pt_gp 1718c66ac9dbSNicholas Bellinger */ 1719c66ac9dbSNicholas Bellinger __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); 1720c66ac9dbSNicholas Bellinger move = 1; 1721c66ac9dbSNicholas Bellinger } 1722c66ac9dbSNicholas Bellinger /* 1723c66ac9dbSNicholas Bellinger * Associate tg_pt_gp_mem with tg_pt_gp_new. 1724c66ac9dbSNicholas Bellinger */ 1725c66ac9dbSNicholas Bellinger __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp_new); 1726c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 17276708bb27SAndy Grover pr_debug("Target_Core_ConfigFS: %s %s/tpgt_%hu/%s to ALUA" 1728c66ac9dbSNicholas Bellinger " Target Port Group: alua/%s, ID: %hu\n", (move) ? 1729e3d6f909SAndy Grover "Moving" : "Adding", tpg->se_tpg_tfo->tpg_get_wwn(tpg), 1730e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), 1731c66ac9dbSNicholas Bellinger config_item_name(&lun->lun_group.cg_item), 1732c66ac9dbSNicholas Bellinger config_item_name(&tg_pt_gp_new->tg_pt_gp_group.cg_item), 1733c66ac9dbSNicholas Bellinger tg_pt_gp_new->tg_pt_gp_id); 1734c66ac9dbSNicholas Bellinger 1735c66ac9dbSNicholas Bellinger core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new); 1736c66ac9dbSNicholas Bellinger return count; 1737c66ac9dbSNicholas Bellinger } 1738c66ac9dbSNicholas Bellinger 1739c66ac9dbSNicholas Bellinger ssize_t core_alua_show_access_type( 1740c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1741c66ac9dbSNicholas Bellinger char *page) 1742c66ac9dbSNicholas Bellinger { 1743125d0119SHannes Reinecke if ((tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA) && 1744125d0119SHannes Reinecke (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)) 1745125d0119SHannes Reinecke return sprintf(page, "Implicit and Explicit\n"); 1746125d0119SHannes Reinecke else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA) 1747125d0119SHannes Reinecke return sprintf(page, "Implicit\n"); 1748125d0119SHannes Reinecke else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA) 1749125d0119SHannes Reinecke return sprintf(page, "Explicit\n"); 1750c66ac9dbSNicholas Bellinger else 1751c66ac9dbSNicholas Bellinger return sprintf(page, "None\n"); 1752c66ac9dbSNicholas Bellinger } 1753c66ac9dbSNicholas Bellinger 1754c66ac9dbSNicholas Bellinger ssize_t core_alua_store_access_type( 1755c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1756c66ac9dbSNicholas Bellinger const char *page, 1757c66ac9dbSNicholas Bellinger size_t count) 1758c66ac9dbSNicholas Bellinger { 1759c66ac9dbSNicholas Bellinger unsigned long tmp; 1760c66ac9dbSNicholas Bellinger int ret; 1761c66ac9dbSNicholas Bellinger 176257103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 1763c66ac9dbSNicholas Bellinger if (ret < 0) { 17646708bb27SAndy Grover pr_err("Unable to extract alua_access_type\n"); 176557103d7fSJingoo Han return ret; 1766c66ac9dbSNicholas Bellinger } 1767c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1) && (tmp != 2) && (tmp != 3)) { 17686708bb27SAndy Grover pr_err("Illegal value for alua_access_type:" 1769c66ac9dbSNicholas Bellinger " %lu\n", tmp); 1770c66ac9dbSNicholas Bellinger return -EINVAL; 1771c66ac9dbSNicholas Bellinger } 1772c66ac9dbSNicholas Bellinger if (tmp == 3) 1773c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = 1774125d0119SHannes Reinecke TPGS_IMPLICIT_ALUA | TPGS_EXPLICIT_ALUA; 1775c66ac9dbSNicholas Bellinger else if (tmp == 2) 1776125d0119SHannes Reinecke tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_EXPLICIT_ALUA; 1777c66ac9dbSNicholas Bellinger else if (tmp == 1) 1778125d0119SHannes Reinecke tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_IMPLICIT_ALUA; 1779c66ac9dbSNicholas Bellinger else 1780c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = 0; 1781c66ac9dbSNicholas Bellinger 1782c66ac9dbSNicholas Bellinger return count; 1783c66ac9dbSNicholas Bellinger } 1784c66ac9dbSNicholas Bellinger 1785c66ac9dbSNicholas Bellinger ssize_t core_alua_show_nonop_delay_msecs( 1786c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1787c66ac9dbSNicholas Bellinger char *page) 1788c66ac9dbSNicholas Bellinger { 1789c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_nonop_delay_msecs); 1790c66ac9dbSNicholas Bellinger } 1791c66ac9dbSNicholas Bellinger 1792c66ac9dbSNicholas Bellinger ssize_t core_alua_store_nonop_delay_msecs( 1793c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1794c66ac9dbSNicholas Bellinger const char *page, 1795c66ac9dbSNicholas Bellinger size_t count) 1796c66ac9dbSNicholas Bellinger { 1797c66ac9dbSNicholas Bellinger unsigned long tmp; 1798c66ac9dbSNicholas Bellinger int ret; 1799c66ac9dbSNicholas Bellinger 180057103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 1801c66ac9dbSNicholas Bellinger if (ret < 0) { 18026708bb27SAndy Grover pr_err("Unable to extract nonop_delay_msecs\n"); 180357103d7fSJingoo Han return ret; 1804c66ac9dbSNicholas Bellinger } 1805c66ac9dbSNicholas Bellinger if (tmp > ALUA_MAX_NONOP_DELAY_MSECS) { 18066708bb27SAndy Grover pr_err("Passed nonop_delay_msecs: %lu, exceeds" 1807c66ac9dbSNicholas Bellinger " ALUA_MAX_NONOP_DELAY_MSECS: %d\n", tmp, 1808c66ac9dbSNicholas Bellinger ALUA_MAX_NONOP_DELAY_MSECS); 1809c66ac9dbSNicholas Bellinger return -EINVAL; 1810c66ac9dbSNicholas Bellinger } 1811c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_nonop_delay_msecs = (int)tmp; 1812c66ac9dbSNicholas Bellinger 1813c66ac9dbSNicholas Bellinger return count; 1814c66ac9dbSNicholas Bellinger } 1815c66ac9dbSNicholas Bellinger 1816c66ac9dbSNicholas Bellinger ssize_t core_alua_show_trans_delay_msecs( 1817c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1818c66ac9dbSNicholas Bellinger char *page) 1819c66ac9dbSNicholas Bellinger { 1820c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_trans_delay_msecs); 1821c66ac9dbSNicholas Bellinger } 1822c66ac9dbSNicholas Bellinger 1823c66ac9dbSNicholas Bellinger ssize_t core_alua_store_trans_delay_msecs( 1824c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1825c66ac9dbSNicholas Bellinger const char *page, 1826c66ac9dbSNicholas Bellinger size_t count) 1827c66ac9dbSNicholas Bellinger { 1828c66ac9dbSNicholas Bellinger unsigned long tmp; 1829c66ac9dbSNicholas Bellinger int ret; 1830c66ac9dbSNicholas Bellinger 183157103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 1832c66ac9dbSNicholas Bellinger if (ret < 0) { 18336708bb27SAndy Grover pr_err("Unable to extract trans_delay_msecs\n"); 183457103d7fSJingoo Han return ret; 1835c66ac9dbSNicholas Bellinger } 1836c66ac9dbSNicholas Bellinger if (tmp > ALUA_MAX_TRANS_DELAY_MSECS) { 18376708bb27SAndy Grover pr_err("Passed trans_delay_msecs: %lu, exceeds" 1838c66ac9dbSNicholas Bellinger " ALUA_MAX_TRANS_DELAY_MSECS: %d\n", tmp, 1839c66ac9dbSNicholas Bellinger ALUA_MAX_TRANS_DELAY_MSECS); 1840c66ac9dbSNicholas Bellinger return -EINVAL; 1841c66ac9dbSNicholas Bellinger } 1842c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_trans_delay_msecs = (int)tmp; 1843c66ac9dbSNicholas Bellinger 1844c66ac9dbSNicholas Bellinger return count; 1845c66ac9dbSNicholas Bellinger } 1846c66ac9dbSNicholas Bellinger 1847125d0119SHannes Reinecke ssize_t core_alua_show_implicit_trans_secs( 18485b9a4d72SNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 18495b9a4d72SNicholas Bellinger char *page) 18505b9a4d72SNicholas Bellinger { 1851125d0119SHannes Reinecke return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implicit_trans_secs); 18525b9a4d72SNicholas Bellinger } 18535b9a4d72SNicholas Bellinger 1854125d0119SHannes Reinecke ssize_t core_alua_store_implicit_trans_secs( 18555b9a4d72SNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 18565b9a4d72SNicholas Bellinger const char *page, 18575b9a4d72SNicholas Bellinger size_t count) 18585b9a4d72SNicholas Bellinger { 18595b9a4d72SNicholas Bellinger unsigned long tmp; 18605b9a4d72SNicholas Bellinger int ret; 18615b9a4d72SNicholas Bellinger 186257103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 18635b9a4d72SNicholas Bellinger if (ret < 0) { 1864125d0119SHannes Reinecke pr_err("Unable to extract implicit_trans_secs\n"); 186557103d7fSJingoo Han return ret; 18665b9a4d72SNicholas Bellinger } 1867125d0119SHannes Reinecke if (tmp > ALUA_MAX_IMPLICIT_TRANS_SECS) { 1868125d0119SHannes Reinecke pr_err("Passed implicit_trans_secs: %lu, exceeds" 1869125d0119SHannes Reinecke " ALUA_MAX_IMPLICIT_TRANS_SECS: %d\n", tmp, 1870125d0119SHannes Reinecke ALUA_MAX_IMPLICIT_TRANS_SECS); 18715b9a4d72SNicholas Bellinger return -EINVAL; 18725b9a4d72SNicholas Bellinger } 1873125d0119SHannes Reinecke tg_pt_gp->tg_pt_gp_implicit_trans_secs = (int)tmp; 18745b9a4d72SNicholas Bellinger 18755b9a4d72SNicholas Bellinger return count; 18765b9a4d72SNicholas Bellinger } 18775b9a4d72SNicholas Bellinger 1878c66ac9dbSNicholas Bellinger ssize_t core_alua_show_preferred_bit( 1879c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1880c66ac9dbSNicholas Bellinger char *page) 1881c66ac9dbSNicholas Bellinger { 1882c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_pref); 1883c66ac9dbSNicholas Bellinger } 1884c66ac9dbSNicholas Bellinger 1885c66ac9dbSNicholas Bellinger ssize_t core_alua_store_preferred_bit( 1886c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1887c66ac9dbSNicholas Bellinger const char *page, 1888c66ac9dbSNicholas Bellinger size_t count) 1889c66ac9dbSNicholas Bellinger { 1890c66ac9dbSNicholas Bellinger unsigned long tmp; 1891c66ac9dbSNicholas Bellinger int ret; 1892c66ac9dbSNicholas Bellinger 189357103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 1894c66ac9dbSNicholas Bellinger if (ret < 0) { 18956708bb27SAndy Grover pr_err("Unable to extract preferred ALUA value\n"); 189657103d7fSJingoo Han return ret; 1897c66ac9dbSNicholas Bellinger } 1898c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 18996708bb27SAndy Grover pr_err("Illegal value for preferred ALUA: %lu\n", tmp); 1900c66ac9dbSNicholas Bellinger return -EINVAL; 1901c66ac9dbSNicholas Bellinger } 1902c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_pref = (int)tmp; 1903c66ac9dbSNicholas Bellinger 1904c66ac9dbSNicholas Bellinger return count; 1905c66ac9dbSNicholas Bellinger } 1906c66ac9dbSNicholas Bellinger 1907c66ac9dbSNicholas Bellinger ssize_t core_alua_show_offline_bit(struct se_lun *lun, char *page) 1908c66ac9dbSNicholas Bellinger { 19096708bb27SAndy Grover if (!lun->lun_sep) 1910c66ac9dbSNicholas Bellinger return -ENODEV; 1911c66ac9dbSNicholas Bellinger 1912c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", 1913c66ac9dbSNicholas Bellinger atomic_read(&lun->lun_sep->sep_tg_pt_secondary_offline)); 1914c66ac9dbSNicholas Bellinger } 1915c66ac9dbSNicholas Bellinger 1916c66ac9dbSNicholas Bellinger ssize_t core_alua_store_offline_bit( 1917c66ac9dbSNicholas Bellinger struct se_lun *lun, 1918c66ac9dbSNicholas Bellinger const char *page, 1919c66ac9dbSNicholas Bellinger size_t count) 1920c66ac9dbSNicholas Bellinger { 1921c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1922c66ac9dbSNicholas Bellinger unsigned long tmp; 1923c66ac9dbSNicholas Bellinger int ret; 1924c66ac9dbSNicholas Bellinger 19256708bb27SAndy Grover if (!lun->lun_sep) 1926c66ac9dbSNicholas Bellinger return -ENODEV; 1927c66ac9dbSNicholas Bellinger 192857103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 1929c66ac9dbSNicholas Bellinger if (ret < 0) { 19306708bb27SAndy Grover pr_err("Unable to extract alua_tg_pt_offline value\n"); 193157103d7fSJingoo Han return ret; 1932c66ac9dbSNicholas Bellinger } 1933c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 19346708bb27SAndy Grover pr_err("Illegal value for alua_tg_pt_offline: %lu\n", 1935c66ac9dbSNicholas Bellinger tmp); 1936c66ac9dbSNicholas Bellinger return -EINVAL; 1937c66ac9dbSNicholas Bellinger } 1938c66ac9dbSNicholas Bellinger tg_pt_gp_mem = lun->lun_sep->sep_alua_tg_pt_gp_mem; 19396708bb27SAndy Grover if (!tg_pt_gp_mem) { 19406708bb27SAndy Grover pr_err("Unable to locate *tg_pt_gp_mem\n"); 1941c66ac9dbSNicholas Bellinger return -EINVAL; 1942c66ac9dbSNicholas Bellinger } 1943c66ac9dbSNicholas Bellinger 1944c66ac9dbSNicholas Bellinger ret = core_alua_set_tg_pt_secondary_state(tg_pt_gp_mem, 1945c66ac9dbSNicholas Bellinger lun->lun_sep, 0, (int)tmp); 1946c66ac9dbSNicholas Bellinger if (ret < 0) 1947c66ac9dbSNicholas Bellinger return -EINVAL; 1948c66ac9dbSNicholas Bellinger 1949c66ac9dbSNicholas Bellinger return count; 1950c66ac9dbSNicholas Bellinger } 1951c66ac9dbSNicholas Bellinger 1952c66ac9dbSNicholas Bellinger ssize_t core_alua_show_secondary_status( 1953c66ac9dbSNicholas Bellinger struct se_lun *lun, 1954c66ac9dbSNicholas Bellinger char *page) 1955c66ac9dbSNicholas Bellinger { 1956c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", lun->lun_sep->sep_tg_pt_secondary_stat); 1957c66ac9dbSNicholas Bellinger } 1958c66ac9dbSNicholas Bellinger 1959c66ac9dbSNicholas Bellinger ssize_t core_alua_store_secondary_status( 1960c66ac9dbSNicholas Bellinger struct se_lun *lun, 1961c66ac9dbSNicholas Bellinger const char *page, 1962c66ac9dbSNicholas Bellinger size_t count) 1963c66ac9dbSNicholas Bellinger { 1964c66ac9dbSNicholas Bellinger unsigned long tmp; 1965c66ac9dbSNicholas Bellinger int ret; 1966c66ac9dbSNicholas Bellinger 196757103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 1968c66ac9dbSNicholas Bellinger if (ret < 0) { 19696708bb27SAndy Grover pr_err("Unable to extract alua_tg_pt_status\n"); 197057103d7fSJingoo Han return ret; 1971c66ac9dbSNicholas Bellinger } 1972c66ac9dbSNicholas Bellinger if ((tmp != ALUA_STATUS_NONE) && 1973125d0119SHannes Reinecke (tmp != ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) && 1974125d0119SHannes Reinecke (tmp != ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA)) { 19756708bb27SAndy Grover pr_err("Illegal value for alua_tg_pt_status: %lu\n", 1976c66ac9dbSNicholas Bellinger tmp); 1977c66ac9dbSNicholas Bellinger return -EINVAL; 1978c66ac9dbSNicholas Bellinger } 1979c66ac9dbSNicholas Bellinger lun->lun_sep->sep_tg_pt_secondary_stat = (int)tmp; 1980c66ac9dbSNicholas Bellinger 1981c66ac9dbSNicholas Bellinger return count; 1982c66ac9dbSNicholas Bellinger } 1983c66ac9dbSNicholas Bellinger 1984c66ac9dbSNicholas Bellinger ssize_t core_alua_show_secondary_write_metadata( 1985c66ac9dbSNicholas Bellinger struct se_lun *lun, 1986c66ac9dbSNicholas Bellinger char *page) 1987c66ac9dbSNicholas Bellinger { 1988c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", 1989c66ac9dbSNicholas Bellinger lun->lun_sep->sep_tg_pt_secondary_write_md); 1990c66ac9dbSNicholas Bellinger } 1991c66ac9dbSNicholas Bellinger 1992c66ac9dbSNicholas Bellinger ssize_t core_alua_store_secondary_write_metadata( 1993c66ac9dbSNicholas Bellinger struct se_lun *lun, 1994c66ac9dbSNicholas Bellinger const char *page, 1995c66ac9dbSNicholas Bellinger size_t count) 1996c66ac9dbSNicholas Bellinger { 1997c66ac9dbSNicholas Bellinger unsigned long tmp; 1998c66ac9dbSNicholas Bellinger int ret; 1999c66ac9dbSNicholas Bellinger 200057103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 2001c66ac9dbSNicholas Bellinger if (ret < 0) { 20026708bb27SAndy Grover pr_err("Unable to extract alua_tg_pt_write_md\n"); 200357103d7fSJingoo Han return ret; 2004c66ac9dbSNicholas Bellinger } 2005c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 20066708bb27SAndy Grover pr_err("Illegal value for alua_tg_pt_write_md:" 2007c66ac9dbSNicholas Bellinger " %lu\n", tmp); 2008c66ac9dbSNicholas Bellinger return -EINVAL; 2009c66ac9dbSNicholas Bellinger } 2010c66ac9dbSNicholas Bellinger lun->lun_sep->sep_tg_pt_secondary_write_md = (int)tmp; 2011c66ac9dbSNicholas Bellinger 2012c66ac9dbSNicholas Bellinger return count; 2013c66ac9dbSNicholas Bellinger } 2014c66ac9dbSNicholas Bellinger 20150fd97ccfSChristoph Hellwig int core_setup_alua(struct se_device *dev) 2016c66ac9dbSNicholas Bellinger { 2017c87fbd56SChristoph Hellwig if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV && 2018c87fbd56SChristoph Hellwig !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) { 2019c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 20200fd97ccfSChristoph Hellwig 2021c66ac9dbSNicholas Bellinger /* 202225985edcSLucas De Marchi * Associate this struct se_device with the default ALUA 2023c66ac9dbSNicholas Bellinger * LUN Group. 2024c66ac9dbSNicholas Bellinger */ 2025c66ac9dbSNicholas Bellinger lu_gp_mem = core_alua_allocate_lu_gp_mem(dev); 2026e3d6f909SAndy Grover if (IS_ERR(lu_gp_mem)) 2027e3d6f909SAndy Grover return PTR_ERR(lu_gp_mem); 2028c66ac9dbSNicholas Bellinger 2029c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 2030c66ac9dbSNicholas Bellinger __core_alua_attach_lu_gp_mem(lu_gp_mem, 2031e3d6f909SAndy Grover default_lu_gp); 2032c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 2033c66ac9dbSNicholas Bellinger 20346708bb27SAndy Grover pr_debug("%s: Adding to default ALUA LU Group:" 2035c66ac9dbSNicholas Bellinger " core/alua/lu_gps/default_lu_gp\n", 2036e3d6f909SAndy Grover dev->transport->name); 2037c66ac9dbSNicholas Bellinger } 2038c66ac9dbSNicholas Bellinger 2039c66ac9dbSNicholas Bellinger return 0; 2040c66ac9dbSNicholas Bellinger } 2041