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 44bb91c1a0SHannes Reinecke static sense_reason_t core_alua_check_transition(int state, int valid, 45bb91c1a0SHannes Reinecke int *primary); 46c66ac9dbSNicholas Bellinger static int core_alua_set_tg_pt_secondary_state( 47c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 48125d0119SHannes Reinecke struct se_port *port, int explicit, int offline); 49c66ac9dbSNicholas Bellinger 50bb91c1a0SHannes Reinecke static char *core_alua_dump_state(int state); 51bb91c1a0SHannes Reinecke 52e3d6f909SAndy Grover static u16 alua_lu_gps_counter; 53e3d6f909SAndy Grover static u32 alua_lu_gps_count; 54e3d6f909SAndy Grover 55e3d6f909SAndy Grover static DEFINE_SPINLOCK(lu_gps_lock); 56e3d6f909SAndy Grover static LIST_HEAD(lu_gps_list); 57e3d6f909SAndy Grover 58e3d6f909SAndy Grover struct t10_alua_lu_gp *default_lu_gp; 59e3d6f909SAndy Grover 60c66ac9dbSNicholas Bellinger /* 61c66094bfSHannes Reinecke * REPORT REFERRALS 62c66094bfSHannes Reinecke * 63c66094bfSHannes Reinecke * See sbc3r35 section 5.23 64c66094bfSHannes Reinecke */ 65c66094bfSHannes Reinecke sense_reason_t 66c66094bfSHannes Reinecke target_emulate_report_referrals(struct se_cmd *cmd) 67c66094bfSHannes Reinecke { 68c66094bfSHannes Reinecke struct se_device *dev = cmd->se_dev; 69c66094bfSHannes Reinecke struct t10_alua_lba_map *map; 70c66094bfSHannes Reinecke struct t10_alua_lba_map_member *map_mem; 71c66094bfSHannes Reinecke unsigned char *buf; 72c66094bfSHannes Reinecke u32 rd_len = 0, off; 73c66094bfSHannes Reinecke 74c66094bfSHannes Reinecke if (cmd->data_length < 4) { 75c66094bfSHannes Reinecke pr_warn("REPORT REFERRALS allocation length %u too" 76c66094bfSHannes Reinecke " small\n", cmd->data_length); 77c66094bfSHannes Reinecke return TCM_INVALID_CDB_FIELD; 78c66094bfSHannes Reinecke } 79c66094bfSHannes Reinecke 80c66094bfSHannes Reinecke buf = transport_kmap_data_sg(cmd); 81c66094bfSHannes Reinecke if (!buf) 82c66094bfSHannes Reinecke return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 83c66094bfSHannes Reinecke 84c66094bfSHannes Reinecke off = 4; 85c66094bfSHannes Reinecke spin_lock(&dev->t10_alua.lba_map_lock); 86c66094bfSHannes Reinecke if (list_empty(&dev->t10_alua.lba_map_list)) { 87c66094bfSHannes Reinecke spin_unlock(&dev->t10_alua.lba_map_lock); 88c66094bfSHannes Reinecke transport_kunmap_data_sg(cmd); 89c66094bfSHannes Reinecke 90c66094bfSHannes Reinecke return TCM_UNSUPPORTED_SCSI_OPCODE; 91c66094bfSHannes Reinecke } 92c66094bfSHannes Reinecke 93c66094bfSHannes Reinecke list_for_each_entry(map, &dev->t10_alua.lba_map_list, 94c66094bfSHannes Reinecke lba_map_list) { 95c66094bfSHannes Reinecke int desc_num = off + 3; 96c66094bfSHannes Reinecke int pg_num; 97c66094bfSHannes Reinecke 98c66094bfSHannes Reinecke off += 4; 9938edd724SHannes Reinecke if (cmd->data_length > off) 100c66094bfSHannes Reinecke put_unaligned_be64(map->lba_map_first_lba, &buf[off]); 101c66094bfSHannes Reinecke off += 8; 10238edd724SHannes Reinecke if (cmd->data_length > off) 103c66094bfSHannes Reinecke put_unaligned_be64(map->lba_map_last_lba, &buf[off]); 104c66094bfSHannes Reinecke off += 8; 105c66094bfSHannes Reinecke rd_len += 20; 106c66094bfSHannes Reinecke pg_num = 0; 107c66094bfSHannes Reinecke list_for_each_entry(map_mem, &map->lba_map_mem_list, 108c66094bfSHannes Reinecke lba_map_mem_list) { 10938edd724SHannes Reinecke int alua_state = map_mem->lba_map_mem_alua_state; 11038edd724SHannes Reinecke int alua_pg_id = map_mem->lba_map_mem_alua_pg_id; 11138edd724SHannes Reinecke 11238edd724SHannes Reinecke if (cmd->data_length > off) 11338edd724SHannes Reinecke buf[off] = alua_state & 0x0f; 11438edd724SHannes Reinecke off += 2; 11538edd724SHannes Reinecke if (cmd->data_length > off) 11638edd724SHannes Reinecke buf[off] = (alua_pg_id >> 8) & 0xff; 117c66094bfSHannes Reinecke off++; 11838edd724SHannes Reinecke if (cmd->data_length > off) 11938edd724SHannes Reinecke buf[off] = (alua_pg_id & 0xff); 12038edd724SHannes Reinecke off++; 121c66094bfSHannes Reinecke rd_len += 4; 122c66094bfSHannes Reinecke pg_num++; 123c66094bfSHannes Reinecke } 12438edd724SHannes Reinecke if (cmd->data_length > desc_num) 125c66094bfSHannes Reinecke buf[desc_num] = pg_num; 126c66094bfSHannes Reinecke } 127c66094bfSHannes Reinecke spin_unlock(&dev->t10_alua.lba_map_lock); 128c66094bfSHannes Reinecke 129c66094bfSHannes Reinecke /* 130c66094bfSHannes Reinecke * Set the RETURN DATA LENGTH set in the header of the DataIN Payload 131c66094bfSHannes Reinecke */ 132c66094bfSHannes Reinecke put_unaligned_be16(rd_len, &buf[2]); 133c66094bfSHannes Reinecke 134c66094bfSHannes Reinecke transport_kunmap_data_sg(cmd); 135c66094bfSHannes Reinecke 136c66094bfSHannes Reinecke target_complete_cmd(cmd, GOOD); 137c66094bfSHannes Reinecke return 0; 138c66094bfSHannes Reinecke } 139c66094bfSHannes Reinecke 140c66094bfSHannes Reinecke /* 141c66ac9dbSNicholas Bellinger * REPORT_TARGET_PORT_GROUPS 142c66ac9dbSNicholas Bellinger * 143c66ac9dbSNicholas Bellinger * See spc4r17 section 6.27 144c66ac9dbSNicholas Bellinger */ 145de103c93SChristoph Hellwig sense_reason_t 146de103c93SChristoph Hellwig target_emulate_report_target_port_groups(struct se_cmd *cmd) 147c66ac9dbSNicholas Bellinger { 1480fd97ccfSChristoph Hellwig struct se_device *dev = cmd->se_dev; 149c66ac9dbSNicholas Bellinger struct se_port *port; 150c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 151c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 15205d1c7c0SAndy Grover unsigned char *buf; 1535b9a4d72SNicholas Bellinger u32 rd_len = 0, off; 1545b9a4d72SNicholas Bellinger int ext_hdr = (cmd->t_task_cdb[1] & 0x20); 155de103c93SChristoph Hellwig 1566b20fa9aSNicholas Bellinger /* 1575b9a4d72SNicholas Bellinger * Skip over RESERVED area to first Target port group descriptor 1585b9a4d72SNicholas Bellinger * depending on the PARAMETER DATA FORMAT type.. 1596b20fa9aSNicholas Bellinger */ 1605b9a4d72SNicholas Bellinger if (ext_hdr != 0) 1615b9a4d72SNicholas Bellinger off = 8; 1625b9a4d72SNicholas Bellinger else 1635b9a4d72SNicholas Bellinger off = 4; 1645b9a4d72SNicholas Bellinger 1655b9a4d72SNicholas Bellinger if (cmd->data_length < off) { 1665b9a4d72SNicholas Bellinger pr_warn("REPORT TARGET PORT GROUPS allocation length %u too" 1675b9a4d72SNicholas Bellinger " small for %s header\n", cmd->data_length, 1685b9a4d72SNicholas Bellinger (ext_hdr) ? "extended" : "normal"); 169de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 1706b20fa9aSNicholas Bellinger } 1714949314cSAndy Grover buf = transport_kmap_data_sg(cmd); 172de103c93SChristoph Hellwig if (!buf) 173de103c93SChristoph Hellwig return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 17405d1c7c0SAndy Grover 1750fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1760fd97ccfSChristoph Hellwig list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, 177c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 178c66ac9dbSNicholas Bellinger /* 1796b20fa9aSNicholas Bellinger * Check if the Target port group and Target port descriptor list 1806b20fa9aSNicholas Bellinger * based on tg_pt_gp_members count will fit into the response payload. 1816b20fa9aSNicholas Bellinger * Otherwise, bump rd_len to let the initiator know we have exceeded 1826b20fa9aSNicholas Bellinger * the allocation length and the response is truncated. 1836b20fa9aSNicholas Bellinger */ 1846b20fa9aSNicholas Bellinger if ((off + 8 + (tg_pt_gp->tg_pt_gp_members * 4)) > 1856b20fa9aSNicholas Bellinger cmd->data_length) { 1866b20fa9aSNicholas Bellinger rd_len += 8 + (tg_pt_gp->tg_pt_gp_members * 4); 1876b20fa9aSNicholas Bellinger continue; 1886b20fa9aSNicholas Bellinger } 1896b20fa9aSNicholas Bellinger /* 190c66ac9dbSNicholas Bellinger * PREF: Preferred target port bit, determine if this 191c66ac9dbSNicholas Bellinger * bit should be set for port group. 192c66ac9dbSNicholas Bellinger */ 193c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_pref) 194c66ac9dbSNicholas Bellinger buf[off] = 0x80; 195c66ac9dbSNicholas Bellinger /* 196c66ac9dbSNicholas Bellinger * Set the ASYMMETRIC ACCESS State 197c66ac9dbSNicholas Bellinger */ 198c66ac9dbSNicholas Bellinger buf[off++] |= (atomic_read( 199c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_alua_access_state) & 0xff); 200c66ac9dbSNicholas Bellinger /* 201c66ac9dbSNicholas Bellinger * Set supported ASYMMETRIC ACCESS State bits 202c66ac9dbSNicholas Bellinger */ 203c0dc941eSHannes Reinecke buf[off++] |= tg_pt_gp->tg_pt_gp_alua_supported_states; 204c66ac9dbSNicholas Bellinger /* 205c66ac9dbSNicholas Bellinger * TARGET PORT GROUP 206c66ac9dbSNicholas Bellinger */ 207c66ac9dbSNicholas Bellinger buf[off++] = ((tg_pt_gp->tg_pt_gp_id >> 8) & 0xff); 208c66ac9dbSNicholas Bellinger buf[off++] = (tg_pt_gp->tg_pt_gp_id & 0xff); 209c66ac9dbSNicholas Bellinger 210c66ac9dbSNicholas Bellinger off++; /* Skip over Reserved */ 211c66ac9dbSNicholas Bellinger /* 212c66ac9dbSNicholas Bellinger * STATUS CODE 213c66ac9dbSNicholas Bellinger */ 214c66ac9dbSNicholas Bellinger buf[off++] = (tg_pt_gp->tg_pt_gp_alua_access_status & 0xff); 215c66ac9dbSNicholas Bellinger /* 216c66ac9dbSNicholas Bellinger * Vendor Specific field 217c66ac9dbSNicholas Bellinger */ 218c66ac9dbSNicholas Bellinger buf[off++] = 0x00; 219c66ac9dbSNicholas Bellinger /* 220c66ac9dbSNicholas Bellinger * TARGET PORT COUNT 221c66ac9dbSNicholas Bellinger */ 222c66ac9dbSNicholas Bellinger buf[off++] = (tg_pt_gp->tg_pt_gp_members & 0xff); 223c66ac9dbSNicholas Bellinger rd_len += 8; 224c66ac9dbSNicholas Bellinger 225c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 226c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp_mem, &tg_pt_gp->tg_pt_gp_mem_list, 227c66ac9dbSNicholas Bellinger tg_pt_gp_mem_list) { 228c66ac9dbSNicholas Bellinger port = tg_pt_gp_mem->tg_pt; 229c66ac9dbSNicholas Bellinger /* 230c66ac9dbSNicholas Bellinger * Start Target Port descriptor format 231c66ac9dbSNicholas Bellinger * 232c66ac9dbSNicholas Bellinger * See spc4r17 section 6.2.7 Table 247 233c66ac9dbSNicholas Bellinger */ 234c66ac9dbSNicholas Bellinger off += 2; /* Skip over Obsolete */ 235c66ac9dbSNicholas Bellinger /* 236c66ac9dbSNicholas Bellinger * Set RELATIVE TARGET PORT IDENTIFIER 237c66ac9dbSNicholas Bellinger */ 238c66ac9dbSNicholas Bellinger buf[off++] = ((port->sep_rtpi >> 8) & 0xff); 239c66ac9dbSNicholas Bellinger buf[off++] = (port->sep_rtpi & 0xff); 240c66ac9dbSNicholas Bellinger rd_len += 4; 241c66ac9dbSNicholas Bellinger } 242c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 243c66ac9dbSNicholas Bellinger } 2440fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 245c66ac9dbSNicholas Bellinger /* 246c66ac9dbSNicholas Bellinger * Set the RETURN DATA LENGTH set in the header of the DataIN Payload 247c66ac9dbSNicholas Bellinger */ 2485b9a4d72SNicholas Bellinger put_unaligned_be32(rd_len, &buf[0]); 249c66ac9dbSNicholas Bellinger 2505b9a4d72SNicholas Bellinger /* 2515b9a4d72SNicholas Bellinger * Fill in the Extended header parameter data format if requested 2525b9a4d72SNicholas Bellinger */ 2535b9a4d72SNicholas Bellinger if (ext_hdr != 0) { 2545b9a4d72SNicholas Bellinger buf[4] = 0x10; 2555b9a4d72SNicholas Bellinger /* 256125d0119SHannes Reinecke * Set the implicit transition time (in seconds) for the application 2575b9a4d72SNicholas Bellinger * client to use as a base for it's transition timeout value. 2585b9a4d72SNicholas Bellinger * 2595b9a4d72SNicholas Bellinger * Use the current tg_pt_gp_mem -> tg_pt_gp membership from the LUN 2605b9a4d72SNicholas Bellinger * this CDB was received upon to determine this value individually 2615b9a4d72SNicholas Bellinger * for ALUA target port group. 2625b9a4d72SNicholas Bellinger */ 2635b9a4d72SNicholas Bellinger port = cmd->se_lun->lun_sep; 2645b9a4d72SNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 2655b9a4d72SNicholas Bellinger if (tg_pt_gp_mem) { 2665b9a4d72SNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 2675b9a4d72SNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 2685b9a4d72SNicholas Bellinger if (tg_pt_gp) 269125d0119SHannes Reinecke buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs; 2705b9a4d72SNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 2715b9a4d72SNicholas Bellinger } 2725b9a4d72SNicholas Bellinger } 2734949314cSAndy Grover transport_kunmap_data_sg(cmd); 27405d1c7c0SAndy Grover 2756bb35e00SChristoph Hellwig target_complete_cmd(cmd, GOOD); 276c66ac9dbSNicholas Bellinger return 0; 277c66ac9dbSNicholas Bellinger } 278c66ac9dbSNicholas Bellinger 279c66ac9dbSNicholas Bellinger /* 280125d0119SHannes Reinecke * SET_TARGET_PORT_GROUPS for explicit ALUA operation. 281c66ac9dbSNicholas Bellinger * 282c66ac9dbSNicholas Bellinger * See spc4r17 section 6.35 283c66ac9dbSNicholas Bellinger */ 284de103c93SChristoph Hellwig sense_reason_t 285de103c93SChristoph Hellwig target_emulate_set_target_port_groups(struct se_cmd *cmd) 286c66ac9dbSNicholas Bellinger { 2875951146dSAndy Grover struct se_device *dev = cmd->se_dev; 288e3d6f909SAndy Grover struct se_port *port, *l_port = cmd->se_lun->lun_sep; 289e3d6f909SAndy Grover struct se_node_acl *nacl = cmd->se_sess->se_node_acl; 290c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp; 291c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; 29205d1c7c0SAndy Grover unsigned char *buf; 29305d1c7c0SAndy Grover unsigned char *ptr; 294a0d50f62SHannes Reinecke sense_reason_t rc = TCM_NO_SENSE; 295c66ac9dbSNicholas Bellinger u32 len = 4; /* Skip over RESERVED area in header */ 296bb91c1a0SHannes Reinecke int alua_access_state, primary = 0, valid_states; 297c66ac9dbSNicholas Bellinger u16 tg_pt_id, rtpi; 298c66ac9dbSNicholas Bellinger 299de103c93SChristoph Hellwig if (!l_port) 300de103c93SChristoph Hellwig return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 301de103c93SChristoph Hellwig 3020d7f1299SPaolo Bonzini if (cmd->data_length < 4) { 3030d7f1299SPaolo Bonzini pr_warn("SET TARGET PORT GROUPS parameter list length %u too" 3040d7f1299SPaolo Bonzini " small\n", cmd->data_length); 305de103c93SChristoph Hellwig return TCM_INVALID_PARAMETER_LIST; 3060d7f1299SPaolo Bonzini } 3070d7f1299SPaolo Bonzini 3084949314cSAndy Grover buf = transport_kmap_data_sg(cmd); 309de103c93SChristoph Hellwig if (!buf) 310de103c93SChristoph Hellwig return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 31105d1c7c0SAndy Grover 312c66ac9dbSNicholas Bellinger /* 313125d0119SHannes Reinecke * Determine if explicit ALUA via SET_TARGET_PORT_GROUPS is allowed 314c66ac9dbSNicholas Bellinger * for the local tg_pt_gp. 315c66ac9dbSNicholas Bellinger */ 316c66ac9dbSNicholas Bellinger l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; 3176708bb27SAndy Grover if (!l_tg_pt_gp_mem) { 3186708bb27SAndy Grover pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); 319de103c93SChristoph Hellwig rc = TCM_UNSUPPORTED_SCSI_OPCODE; 32005d1c7c0SAndy Grover goto out; 321c66ac9dbSNicholas Bellinger } 322c66ac9dbSNicholas Bellinger spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 323c66ac9dbSNicholas Bellinger l_tg_pt_gp = l_tg_pt_gp_mem->tg_pt_gp; 3246708bb27SAndy Grover if (!l_tg_pt_gp) { 325c66ac9dbSNicholas Bellinger spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 3266708bb27SAndy Grover pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); 327de103c93SChristoph Hellwig rc = TCM_UNSUPPORTED_SCSI_OPCODE; 32805d1c7c0SAndy Grover goto out; 329c66ac9dbSNicholas Bellinger } 330c66ac9dbSNicholas Bellinger spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); 331c66ac9dbSNicholas Bellinger 332125d0119SHannes Reinecke if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) { 3336708bb27SAndy Grover pr_debug("Unable to process SET_TARGET_PORT_GROUPS" 334125d0119SHannes Reinecke " while TPGS_EXPLICIT_ALUA is disabled\n"); 335de103c93SChristoph Hellwig rc = TCM_UNSUPPORTED_SCSI_OPCODE; 33605d1c7c0SAndy Grover goto out; 337c66ac9dbSNicholas Bellinger } 338bb91c1a0SHannes Reinecke valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states; 339c66ac9dbSNicholas Bellinger 34005d1c7c0SAndy Grover ptr = &buf[4]; /* Skip over RESERVED area in header */ 34105d1c7c0SAndy Grover 342c66ac9dbSNicholas Bellinger while (len < cmd->data_length) { 343de103c93SChristoph Hellwig bool found = false; 344c66ac9dbSNicholas Bellinger alua_access_state = (ptr[0] & 0x0f); 345c66ac9dbSNicholas Bellinger /* 346c66ac9dbSNicholas Bellinger * Check the received ALUA access state, and determine if 347c66ac9dbSNicholas Bellinger * the state is a primary or secondary target port asymmetric 348c66ac9dbSNicholas Bellinger * access state. 349c66ac9dbSNicholas Bellinger */ 350bb91c1a0SHannes Reinecke rc = core_alua_check_transition(alua_access_state, 351bb91c1a0SHannes Reinecke valid_states, &primary); 352de103c93SChristoph Hellwig if (rc) { 353c66ac9dbSNicholas Bellinger /* 354c66ac9dbSNicholas Bellinger * If the SET TARGET PORT GROUPS attempts to establish 355c66ac9dbSNicholas Bellinger * an invalid combination of target port asymmetric 356c66ac9dbSNicholas Bellinger * access states or attempts to establish an 357c66ac9dbSNicholas Bellinger * unsupported target port asymmetric access state, 358c66ac9dbSNicholas Bellinger * then the command shall be terminated with CHECK 359c66ac9dbSNicholas Bellinger * CONDITION status, with the sense key set to ILLEGAL 360c66ac9dbSNicholas Bellinger * REQUEST, and the additional sense code set to INVALID 361c66ac9dbSNicholas Bellinger * FIELD IN PARAMETER LIST. 362c66ac9dbSNicholas Bellinger */ 36305d1c7c0SAndy Grover goto out; 364c66ac9dbSNicholas Bellinger } 365de103c93SChristoph Hellwig 366c66ac9dbSNicholas Bellinger /* 367c66ac9dbSNicholas Bellinger * If the ASYMMETRIC ACCESS STATE field (see table 267) 368c66ac9dbSNicholas Bellinger * specifies a primary target port asymmetric access state, 369c66ac9dbSNicholas Bellinger * then the TARGET PORT GROUP OR TARGET PORT field specifies 370c66ac9dbSNicholas Bellinger * a primary target port group for which the primary target 371c66ac9dbSNicholas Bellinger * port asymmetric access state shall be changed. If the 372c66ac9dbSNicholas Bellinger * ASYMMETRIC ACCESS STATE field specifies a secondary target 373c66ac9dbSNicholas Bellinger * port asymmetric access state, then the TARGET PORT GROUP OR 374c66ac9dbSNicholas Bellinger * TARGET PORT field specifies the relative target port 375c66ac9dbSNicholas Bellinger * identifier (see 3.1.120) of the target port for which the 376c66ac9dbSNicholas Bellinger * secondary target port asymmetric access state shall be 377c66ac9dbSNicholas Bellinger * changed. 378c66ac9dbSNicholas Bellinger */ 379c66ac9dbSNicholas Bellinger if (primary) { 38033395fb8SRoland Dreier tg_pt_id = get_unaligned_be16(ptr + 2); 381c66ac9dbSNicholas Bellinger /* 382c66ac9dbSNicholas Bellinger * Locate the matching target port group ID from 383c66ac9dbSNicholas Bellinger * the global tg_pt_gp list 384c66ac9dbSNicholas Bellinger */ 3850fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 386c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp, 3870fd97ccfSChristoph Hellwig &dev->t10_alua.tg_pt_gps_list, 388c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 3896708bb27SAndy Grover if (!tg_pt_gp->tg_pt_gp_valid_id) 390c66ac9dbSNicholas Bellinger continue; 391c66ac9dbSNicholas Bellinger 392c66ac9dbSNicholas Bellinger if (tg_pt_id != tg_pt_gp->tg_pt_gp_id) 393c66ac9dbSNicholas Bellinger continue; 394c66ac9dbSNicholas Bellinger 395c66ac9dbSNicholas Bellinger atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 396c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 397de103c93SChristoph Hellwig 3980fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 399c66ac9dbSNicholas Bellinger 400de103c93SChristoph Hellwig if (!core_alua_do_port_transition(tg_pt_gp, 401c66ac9dbSNicholas Bellinger dev, l_port, nacl, 402de103c93SChristoph Hellwig alua_access_state, 1)) 403de103c93SChristoph Hellwig found = true; 404c66ac9dbSNicholas Bellinger 4050fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 406c66ac9dbSNicholas Bellinger atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 407c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 408c66ac9dbSNicholas Bellinger break; 409c66ac9dbSNicholas Bellinger } 4100fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 411c66ac9dbSNicholas Bellinger } else { 412c66ac9dbSNicholas Bellinger /* 413f1ae05d5SHannes Reinecke * Extract the RELATIVE TARGET PORT IDENTIFIER to identify 414c66ac9dbSNicholas Bellinger * the Target Port in question for the the incoming 415c66ac9dbSNicholas Bellinger * SET_TARGET_PORT_GROUPS op. 416c66ac9dbSNicholas Bellinger */ 41733395fb8SRoland Dreier rtpi = get_unaligned_be16(ptr + 2); 418c66ac9dbSNicholas Bellinger /* 41935d1efe8SMasanari Iida * Locate the matching relative target port identifier 420c66ac9dbSNicholas Bellinger * for the struct se_device storage object. 421c66ac9dbSNicholas Bellinger */ 422c66ac9dbSNicholas Bellinger spin_lock(&dev->se_port_lock); 423c66ac9dbSNicholas Bellinger list_for_each_entry(port, &dev->dev_sep_list, 424c66ac9dbSNicholas Bellinger sep_list) { 425c66ac9dbSNicholas Bellinger if (port->sep_rtpi != rtpi) 426c66ac9dbSNicholas Bellinger continue; 427c66ac9dbSNicholas Bellinger 428c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 429de103c93SChristoph Hellwig 430c66ac9dbSNicholas Bellinger spin_unlock(&dev->se_port_lock); 431c66ac9dbSNicholas Bellinger 432de103c93SChristoph Hellwig if (!core_alua_set_tg_pt_secondary_state( 433de103c93SChristoph Hellwig tg_pt_gp_mem, port, 1, 1)) 434de103c93SChristoph Hellwig found = true; 435c66ac9dbSNicholas Bellinger 436c66ac9dbSNicholas Bellinger spin_lock(&dev->se_port_lock); 437c66ac9dbSNicholas Bellinger break; 438c66ac9dbSNicholas Bellinger } 439c66ac9dbSNicholas Bellinger spin_unlock(&dev->se_port_lock); 44005d1c7c0SAndy Grover } 441de103c93SChristoph Hellwig 442de103c93SChristoph Hellwig if (!found) { 443de103c93SChristoph Hellwig rc = TCM_INVALID_PARAMETER_LIST; 444de103c93SChristoph Hellwig goto out; 445c66ac9dbSNicholas Bellinger } 446c66ac9dbSNicholas Bellinger 447c66ac9dbSNicholas Bellinger ptr += 4; 448c66ac9dbSNicholas Bellinger len += 4; 449c66ac9dbSNicholas Bellinger } 450c66ac9dbSNicholas Bellinger 45105d1c7c0SAndy Grover out: 4524949314cSAndy Grover transport_kunmap_data_sg(cmd); 45359e4f541SRoland Dreier if (!rc) 4546bb35e00SChristoph Hellwig target_complete_cmd(cmd, GOOD); 45559e4f541SRoland Dreier return rc; 456c66ac9dbSNicholas Bellinger } 457c66ac9dbSNicholas Bellinger 458c66ac9dbSNicholas Bellinger static inline int core_alua_state_nonoptimized( 459c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 460c66ac9dbSNicholas Bellinger unsigned char *cdb, 461c66ac9dbSNicholas Bellinger int nonop_delay_msecs, 462c66ac9dbSNicholas Bellinger u8 *alua_ascq) 463c66ac9dbSNicholas Bellinger { 464c66ac9dbSNicholas Bellinger /* 465c66ac9dbSNicholas Bellinger * Set SCF_ALUA_NON_OPTIMIZED here, this value will be checked 466c66ac9dbSNicholas Bellinger * later to determine if processing of this cmd needs to be 467c66ac9dbSNicholas Bellinger * temporarily delayed for the Active/NonOptimized primary access state. 468c66ac9dbSNicholas Bellinger */ 469c66ac9dbSNicholas Bellinger cmd->se_cmd_flags |= SCF_ALUA_NON_OPTIMIZED; 470c66ac9dbSNicholas Bellinger cmd->alua_nonop_delay = nonop_delay_msecs; 471c66ac9dbSNicholas Bellinger return 0; 472c66ac9dbSNicholas Bellinger } 473c66ac9dbSNicholas Bellinger 474c66094bfSHannes Reinecke static inline int core_alua_state_lba_dependent( 475c66094bfSHannes Reinecke struct se_cmd *cmd, 476c66094bfSHannes Reinecke struct t10_alua_tg_pt_gp *tg_pt_gp, 477c66094bfSHannes Reinecke u8 *alua_ascq) 478c66094bfSHannes Reinecke { 479c66094bfSHannes Reinecke struct se_device *dev = cmd->se_dev; 480c66094bfSHannes Reinecke u64 segment_size, segment_mult, sectors, lba; 481c66094bfSHannes Reinecke 482c66094bfSHannes Reinecke /* Only need to check for cdb actually containing LBAs */ 483c66094bfSHannes Reinecke if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB)) 484c66094bfSHannes Reinecke return 0; 485c66094bfSHannes Reinecke 486c66094bfSHannes Reinecke spin_lock(&dev->t10_alua.lba_map_lock); 487c66094bfSHannes Reinecke segment_size = dev->t10_alua.lba_map_segment_size; 488c66094bfSHannes Reinecke segment_mult = dev->t10_alua.lba_map_segment_multiplier; 489c66094bfSHannes Reinecke sectors = cmd->data_length / dev->dev_attrib.block_size; 490c66094bfSHannes Reinecke 491c66094bfSHannes Reinecke lba = cmd->t_task_lba; 492c66094bfSHannes Reinecke while (lba < cmd->t_task_lba + sectors) { 493c66094bfSHannes Reinecke struct t10_alua_lba_map *cur_map = NULL, *map; 494c66094bfSHannes Reinecke struct t10_alua_lba_map_member *map_mem; 495c66094bfSHannes Reinecke 496c66094bfSHannes Reinecke list_for_each_entry(map, &dev->t10_alua.lba_map_list, 497c66094bfSHannes Reinecke lba_map_list) { 498c66094bfSHannes Reinecke u64 start_lba, last_lba; 499c66094bfSHannes Reinecke u64 first_lba = map->lba_map_first_lba; 500c66094bfSHannes Reinecke 501c66094bfSHannes Reinecke if (segment_mult) { 502c66094bfSHannes Reinecke u64 tmp = lba; 503cdf55949SNicholas Bellinger start_lba = do_div(tmp, segment_size * segment_mult); 504c66094bfSHannes Reinecke 505c66094bfSHannes Reinecke last_lba = first_lba + segment_size - 1; 506c66094bfSHannes Reinecke if (start_lba >= first_lba && 507c66094bfSHannes Reinecke start_lba <= last_lba) { 508c66094bfSHannes Reinecke lba += segment_size; 509c66094bfSHannes Reinecke cur_map = map; 510c66094bfSHannes Reinecke break; 511c66094bfSHannes Reinecke } 512c66094bfSHannes Reinecke } else { 513c66094bfSHannes Reinecke last_lba = map->lba_map_last_lba; 514c66094bfSHannes Reinecke if (lba >= first_lba && lba <= last_lba) { 515c66094bfSHannes Reinecke lba = last_lba + 1; 516c66094bfSHannes Reinecke cur_map = map; 517c66094bfSHannes Reinecke break; 518c66094bfSHannes Reinecke } 519c66094bfSHannes Reinecke } 520c66094bfSHannes Reinecke } 521c66094bfSHannes Reinecke if (!cur_map) { 522c66094bfSHannes Reinecke spin_unlock(&dev->t10_alua.lba_map_lock); 523c66094bfSHannes Reinecke *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 524c66094bfSHannes Reinecke return 1; 525c66094bfSHannes Reinecke } 526c66094bfSHannes Reinecke list_for_each_entry(map_mem, &cur_map->lba_map_mem_list, 527c66094bfSHannes Reinecke lba_map_mem_list) { 528c66094bfSHannes Reinecke if (map_mem->lba_map_mem_alua_pg_id != 529c66094bfSHannes Reinecke tg_pt_gp->tg_pt_gp_id) 530c66094bfSHannes Reinecke continue; 531c66094bfSHannes Reinecke switch(map_mem->lba_map_mem_alua_state) { 532c66094bfSHannes Reinecke case ALUA_ACCESS_STATE_STANDBY: 533c66094bfSHannes Reinecke spin_unlock(&dev->t10_alua.lba_map_lock); 534c66094bfSHannes Reinecke *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 535c66094bfSHannes Reinecke return 1; 536c66094bfSHannes Reinecke case ALUA_ACCESS_STATE_UNAVAILABLE: 537c66094bfSHannes Reinecke spin_unlock(&dev->t10_alua.lba_map_lock); 538c66094bfSHannes Reinecke *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 539c66094bfSHannes Reinecke return 1; 540c66094bfSHannes Reinecke default: 541c66094bfSHannes Reinecke break; 542c66094bfSHannes Reinecke } 543c66094bfSHannes Reinecke } 544c66094bfSHannes Reinecke } 545c66094bfSHannes Reinecke spin_unlock(&dev->t10_alua.lba_map_lock); 546c66094bfSHannes Reinecke return 0; 547c66094bfSHannes Reinecke } 548c66094bfSHannes Reinecke 549c66ac9dbSNicholas Bellinger static inline int core_alua_state_standby( 550c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 551c66ac9dbSNicholas Bellinger unsigned char *cdb, 552c66ac9dbSNicholas Bellinger u8 *alua_ascq) 553c66ac9dbSNicholas Bellinger { 554c66ac9dbSNicholas Bellinger /* 555c66ac9dbSNicholas Bellinger * Allowed CDBs for ALUA_ACCESS_STATE_STANDBY as defined by 556c66ac9dbSNicholas Bellinger * spc4r17 section 5.9.2.4.4 557c66ac9dbSNicholas Bellinger */ 558c66ac9dbSNicholas Bellinger switch (cdb[0]) { 559c66ac9dbSNicholas Bellinger case INQUIRY: 560c66ac9dbSNicholas Bellinger case LOG_SELECT: 561c66ac9dbSNicholas Bellinger case LOG_SENSE: 562c66ac9dbSNicholas Bellinger case MODE_SELECT: 563c66ac9dbSNicholas Bellinger case MODE_SENSE: 564c66ac9dbSNicholas Bellinger case REPORT_LUNS: 565c66ac9dbSNicholas Bellinger case RECEIVE_DIAGNOSTIC: 566c66ac9dbSNicholas Bellinger case SEND_DIAGNOSTIC: 56730f359a6SNicholas Bellinger return 0; 568c66ac9dbSNicholas Bellinger case MAINTENANCE_IN: 569ba539743SNicholas Bellinger switch (cdb[1] & 0x1f) { 570c66ac9dbSNicholas Bellinger case MI_REPORT_TARGET_PGS: 571c66ac9dbSNicholas Bellinger return 0; 572c66ac9dbSNicholas Bellinger default: 573c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 574c66ac9dbSNicholas Bellinger return 1; 575c66ac9dbSNicholas Bellinger } 576c66ac9dbSNicholas Bellinger case MAINTENANCE_OUT: 577c66ac9dbSNicholas Bellinger switch (cdb[1]) { 578c66ac9dbSNicholas Bellinger case MO_SET_TARGET_PGS: 579c66ac9dbSNicholas Bellinger return 0; 580c66ac9dbSNicholas Bellinger default: 581c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 582c66ac9dbSNicholas Bellinger return 1; 583c66ac9dbSNicholas Bellinger } 584c66ac9dbSNicholas Bellinger case REQUEST_SENSE: 585c66ac9dbSNicholas Bellinger case PERSISTENT_RESERVE_IN: 586c66ac9dbSNicholas Bellinger case PERSISTENT_RESERVE_OUT: 587c66ac9dbSNicholas Bellinger case READ_BUFFER: 588c66ac9dbSNicholas Bellinger case WRITE_BUFFER: 589c66ac9dbSNicholas Bellinger return 0; 590c66ac9dbSNicholas Bellinger default: 591c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_STANDBY; 592c66ac9dbSNicholas Bellinger return 1; 593c66ac9dbSNicholas Bellinger } 594c66ac9dbSNicholas Bellinger 595c66ac9dbSNicholas Bellinger return 0; 596c66ac9dbSNicholas Bellinger } 597c66ac9dbSNicholas Bellinger 598c66ac9dbSNicholas Bellinger static inline int core_alua_state_unavailable( 599c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 600c66ac9dbSNicholas Bellinger unsigned char *cdb, 601c66ac9dbSNicholas Bellinger u8 *alua_ascq) 602c66ac9dbSNicholas Bellinger { 603c66ac9dbSNicholas Bellinger /* 604c66ac9dbSNicholas Bellinger * Allowed CDBs for ALUA_ACCESS_STATE_UNAVAILABLE as defined by 605c66ac9dbSNicholas Bellinger * spc4r17 section 5.9.2.4.5 606c66ac9dbSNicholas Bellinger */ 607c66ac9dbSNicholas Bellinger switch (cdb[0]) { 608c66ac9dbSNicholas Bellinger case INQUIRY: 609c66ac9dbSNicholas Bellinger case REPORT_LUNS: 61030f359a6SNicholas Bellinger return 0; 611c66ac9dbSNicholas Bellinger case MAINTENANCE_IN: 612ba539743SNicholas Bellinger switch (cdb[1] & 0x1f) { 613c66ac9dbSNicholas Bellinger case MI_REPORT_TARGET_PGS: 614c66ac9dbSNicholas Bellinger return 0; 615c66ac9dbSNicholas Bellinger default: 616c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 617c66ac9dbSNicholas Bellinger return 1; 618c66ac9dbSNicholas Bellinger } 619c66ac9dbSNicholas Bellinger case MAINTENANCE_OUT: 620c66ac9dbSNicholas Bellinger switch (cdb[1]) { 621c66ac9dbSNicholas Bellinger case MO_SET_TARGET_PGS: 622c66ac9dbSNicholas Bellinger return 0; 623c66ac9dbSNicholas Bellinger default: 624c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 625c66ac9dbSNicholas Bellinger return 1; 626c66ac9dbSNicholas Bellinger } 627c66ac9dbSNicholas Bellinger case REQUEST_SENSE: 628c66ac9dbSNicholas Bellinger case READ_BUFFER: 629c66ac9dbSNicholas Bellinger case WRITE_BUFFER: 630c66ac9dbSNicholas Bellinger return 0; 631c66ac9dbSNicholas Bellinger default: 632c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_TG_PT_UNAVAILABLE; 633c66ac9dbSNicholas Bellinger return 1; 634c66ac9dbSNicholas Bellinger } 635c66ac9dbSNicholas Bellinger 636c66ac9dbSNicholas Bellinger return 0; 637c66ac9dbSNicholas Bellinger } 638c66ac9dbSNicholas Bellinger 639c66ac9dbSNicholas Bellinger static inline int core_alua_state_transition( 640c66ac9dbSNicholas Bellinger struct se_cmd *cmd, 641c66ac9dbSNicholas Bellinger unsigned char *cdb, 642c66ac9dbSNicholas Bellinger u8 *alua_ascq) 643c66ac9dbSNicholas Bellinger { 644c66ac9dbSNicholas Bellinger /* 645f1ae05d5SHannes Reinecke * Allowed CDBs for ALUA_ACCESS_STATE_TRANSITION as defined by 646c66ac9dbSNicholas Bellinger * spc4r17 section 5.9.2.5 647c66ac9dbSNicholas Bellinger */ 648c66ac9dbSNicholas Bellinger switch (cdb[0]) { 649c66ac9dbSNicholas Bellinger case INQUIRY: 650c66ac9dbSNicholas Bellinger case REPORT_LUNS: 65130f359a6SNicholas Bellinger return 0; 652c66ac9dbSNicholas Bellinger case MAINTENANCE_IN: 653ba539743SNicholas Bellinger switch (cdb[1] & 0x1f) { 654c66ac9dbSNicholas Bellinger case MI_REPORT_TARGET_PGS: 655c66ac9dbSNicholas Bellinger return 0; 656c66ac9dbSNicholas Bellinger default: 657c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_STATE_TRANSITION; 658c66ac9dbSNicholas Bellinger return 1; 659c66ac9dbSNicholas Bellinger } 660c66ac9dbSNicholas Bellinger case REQUEST_SENSE: 661c66ac9dbSNicholas Bellinger case READ_BUFFER: 662c66ac9dbSNicholas Bellinger case WRITE_BUFFER: 663c66ac9dbSNicholas Bellinger return 0; 664c66ac9dbSNicholas Bellinger default: 665c66ac9dbSNicholas Bellinger *alua_ascq = ASCQ_04H_ALUA_STATE_TRANSITION; 666c66ac9dbSNicholas Bellinger return 1; 667c66ac9dbSNicholas Bellinger } 668c66ac9dbSNicholas Bellinger 669c66ac9dbSNicholas Bellinger return 0; 670c66ac9dbSNicholas Bellinger } 671c66ac9dbSNicholas Bellinger 672c66ac9dbSNicholas Bellinger /* 673f1ae05d5SHannes Reinecke * return 1: Is used to signal LUN not accessible, and check condition/not ready 674c66ac9dbSNicholas Bellinger * return 0: Used to signal success 675f1ae05d5SHannes Reinecke * return -1: Used to signal failure, and invalid cdb field 676c66ac9dbSNicholas Bellinger */ 677de103c93SChristoph Hellwig sense_reason_t 678de103c93SChristoph Hellwig target_alua_state_check(struct se_cmd *cmd) 679c66ac9dbSNicholas Bellinger { 680c87fbd56SChristoph Hellwig struct se_device *dev = cmd->se_dev; 681c87fbd56SChristoph Hellwig unsigned char *cdb = cmd->t_task_cdb; 682e3d6f909SAndy Grover struct se_lun *lun = cmd->se_lun; 683c66ac9dbSNicholas Bellinger struct se_port *port = lun->lun_sep; 684c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 685c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 686c66ac9dbSNicholas Bellinger int out_alua_state, nonop_delay_msecs; 687c87fbd56SChristoph Hellwig u8 alua_ascq; 688c87fbd56SChristoph Hellwig int ret; 689c87fbd56SChristoph Hellwig 690c87fbd56SChristoph Hellwig if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) 691c87fbd56SChristoph Hellwig return 0; 692c87fbd56SChristoph Hellwig if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) 693c87fbd56SChristoph Hellwig return 0; 694c66ac9dbSNicholas Bellinger 6956708bb27SAndy Grover if (!port) 696c66ac9dbSNicholas Bellinger return 0; 697c66ac9dbSNicholas Bellinger /* 698c66ac9dbSNicholas Bellinger * First, check for a struct se_port specific secondary ALUA target port 699c66ac9dbSNicholas Bellinger * access state: OFFLINE 700c66ac9dbSNicholas Bellinger */ 701c66ac9dbSNicholas Bellinger if (atomic_read(&port->sep_tg_pt_secondary_offline)) { 7026708bb27SAndy Grover pr_debug("ALUA: Got secondary offline status for local" 703c66ac9dbSNicholas Bellinger " target port\n"); 704c87fbd56SChristoph Hellwig alua_ascq = ASCQ_04H_ALUA_OFFLINE; 705c87fbd56SChristoph Hellwig ret = 1; 706c87fbd56SChristoph Hellwig goto out; 707c66ac9dbSNicholas Bellinger } 708c66ac9dbSNicholas Bellinger /* 709c66ac9dbSNicholas Bellinger * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the 710c66ac9dbSNicholas Bellinger * ALUA target port group, to obtain current ALUA access state. 711c66ac9dbSNicholas Bellinger * Otherwise look for the underlying struct se_device association with 712c66ac9dbSNicholas Bellinger * a ALUA logical unit group. 713c66ac9dbSNicholas Bellinger */ 714c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 71589c12cc9SNicholas Bellinger if (!tg_pt_gp_mem) 71689c12cc9SNicholas Bellinger return 0; 71789c12cc9SNicholas Bellinger 718c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 719c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 720c66ac9dbSNicholas Bellinger out_alua_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); 721c66ac9dbSNicholas Bellinger nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs; 722c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 723c66ac9dbSNicholas Bellinger /* 72473f3bf51SHannes Reinecke * Process ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED in a separate conditional 72525985edcSLucas De Marchi * statement so the compiler knows explicitly to check this case first. 726c66ac9dbSNicholas Bellinger * For the Optimized ALUA access state case, we want to process the 727c66ac9dbSNicholas Bellinger * incoming fabric cmd ASAP.. 728c66ac9dbSNicholas Bellinger */ 72973f3bf51SHannes Reinecke if (out_alua_state == ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED) 730c66ac9dbSNicholas Bellinger return 0; 731c66ac9dbSNicholas Bellinger 732c66ac9dbSNicholas Bellinger switch (out_alua_state) { 733c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 734c87fbd56SChristoph Hellwig ret = core_alua_state_nonoptimized(cmd, cdb, 735c87fbd56SChristoph Hellwig nonop_delay_msecs, &alua_ascq); 736c87fbd56SChristoph Hellwig break; 737c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_STANDBY: 738c87fbd56SChristoph Hellwig ret = core_alua_state_standby(cmd, cdb, &alua_ascq); 739c87fbd56SChristoph Hellwig break; 740c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_UNAVAILABLE: 741c87fbd56SChristoph Hellwig ret = core_alua_state_unavailable(cmd, cdb, &alua_ascq); 742c87fbd56SChristoph Hellwig break; 743c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_TRANSITION: 744c87fbd56SChristoph Hellwig ret = core_alua_state_transition(cmd, cdb, &alua_ascq); 745c87fbd56SChristoph Hellwig break; 746c66094bfSHannes Reinecke case ALUA_ACCESS_STATE_LBA_DEPENDENT: 747c66094bfSHannes Reinecke ret = core_alua_state_lba_dependent(cmd, tg_pt_gp, &alua_ascq); 748c66094bfSHannes Reinecke break; 749c66ac9dbSNicholas Bellinger /* 750c66ac9dbSNicholas Bellinger * OFFLINE is a secondary ALUA target port group access state, that is 751c66ac9dbSNicholas Bellinger * handled above with struct se_port->sep_tg_pt_secondary_offline=1 752c66ac9dbSNicholas Bellinger */ 753c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_OFFLINE: 754c66ac9dbSNicholas Bellinger default: 7556708bb27SAndy Grover pr_err("Unknown ALUA access state: 0x%02x\n", 756c66ac9dbSNicholas Bellinger out_alua_state); 757de103c93SChristoph Hellwig return TCM_INVALID_CDB_FIELD; 758c66ac9dbSNicholas Bellinger } 759c66ac9dbSNicholas Bellinger 760c87fbd56SChristoph Hellwig out: 761c87fbd56SChristoph Hellwig if (ret > 0) { 762c87fbd56SChristoph Hellwig /* 763c87fbd56SChristoph Hellwig * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; 764c87fbd56SChristoph Hellwig * The ALUA additional sense code qualifier (ASCQ) is determined 765c87fbd56SChristoph Hellwig * by the ALUA primary or secondary access state.. 766c87fbd56SChristoph Hellwig */ 767c87fbd56SChristoph Hellwig pr_debug("[%s]: ALUA TG Port not available, " 768c87fbd56SChristoph Hellwig "SenseKey: NOT_READY, ASC/ASCQ: " 769c87fbd56SChristoph Hellwig "0x04/0x%02x\n", 770c87fbd56SChristoph Hellwig cmd->se_tfo->get_fabric_name(), alua_ascq); 771c87fbd56SChristoph Hellwig 772c87fbd56SChristoph Hellwig cmd->scsi_asc = 0x04; 773c87fbd56SChristoph Hellwig cmd->scsi_ascq = alua_ascq; 774de103c93SChristoph Hellwig return TCM_CHECK_CONDITION_NOT_READY; 775c87fbd56SChristoph Hellwig } 776c87fbd56SChristoph Hellwig 777de103c93SChristoph Hellwig return 0; 778c66ac9dbSNicholas Bellinger } 779c66ac9dbSNicholas Bellinger 780c66ac9dbSNicholas Bellinger /* 781125d0119SHannes Reinecke * Check implicit and explicit ALUA state change request. 782c66ac9dbSNicholas Bellinger */ 783de103c93SChristoph Hellwig static sense_reason_t 784bb91c1a0SHannes Reinecke core_alua_check_transition(int state, int valid, int *primary) 785c66ac9dbSNicholas Bellinger { 786c66ac9dbSNicholas Bellinger /* 787c66ac9dbSNicholas Bellinger * OPTIMIZED, NON-OPTIMIZED, STANDBY and UNAVAILABLE are 788c66ac9dbSNicholas Bellinger * defined as primary target port asymmetric access states. 789c66ac9dbSNicholas Bellinger */ 790bb91c1a0SHannes Reinecke switch (state) { 791bb91c1a0SHannes Reinecke case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED: 792bb91c1a0SHannes Reinecke if (!(valid & ALUA_AO_SUP)) 793bb91c1a0SHannes Reinecke goto not_supported; 794bb91c1a0SHannes Reinecke *primary = 1; 795bb91c1a0SHannes Reinecke break; 796bb91c1a0SHannes Reinecke case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 797bb91c1a0SHannes Reinecke if (!(valid & ALUA_AN_SUP)) 798bb91c1a0SHannes Reinecke goto not_supported; 799bb91c1a0SHannes Reinecke *primary = 1; 800bb91c1a0SHannes Reinecke break; 801bb91c1a0SHannes Reinecke case ALUA_ACCESS_STATE_STANDBY: 802bb91c1a0SHannes Reinecke if (!(valid & ALUA_S_SUP)) 803bb91c1a0SHannes Reinecke goto not_supported; 804bb91c1a0SHannes Reinecke *primary = 1; 805bb91c1a0SHannes Reinecke break; 806bb91c1a0SHannes Reinecke case ALUA_ACCESS_STATE_UNAVAILABLE: 807bb91c1a0SHannes Reinecke if (!(valid & ALUA_U_SUP)) 808bb91c1a0SHannes Reinecke goto not_supported; 809c66ac9dbSNicholas Bellinger *primary = 1; 810c66ac9dbSNicholas Bellinger break; 811c66094bfSHannes Reinecke case ALUA_ACCESS_STATE_LBA_DEPENDENT: 812c66094bfSHannes Reinecke if (!(valid & ALUA_LBD_SUP)) 813c66094bfSHannes Reinecke goto not_supported; 814c66094bfSHannes Reinecke *primary = 1; 815c66094bfSHannes Reinecke break; 816c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_OFFLINE: 817c66ac9dbSNicholas Bellinger /* 818c66ac9dbSNicholas Bellinger * OFFLINE state is defined as a secondary target port 819c66ac9dbSNicholas Bellinger * asymmetric access state. 820c66ac9dbSNicholas Bellinger */ 821bb91c1a0SHannes Reinecke if (!(valid & ALUA_O_SUP)) 822bb91c1a0SHannes Reinecke goto not_supported; 823c66ac9dbSNicholas Bellinger *primary = 0; 824c66ac9dbSNicholas Bellinger break; 825bb91c1a0SHannes Reinecke case ALUA_ACCESS_STATE_TRANSITION: 826bb91c1a0SHannes Reinecke /* 827bb91c1a0SHannes Reinecke * Transitioning is set internally, and 828bb91c1a0SHannes Reinecke * cannot be selected manually. 829bb91c1a0SHannes Reinecke */ 830bb91c1a0SHannes Reinecke goto not_supported; 831c66ac9dbSNicholas Bellinger default: 8326708bb27SAndy Grover pr_err("Unknown ALUA access state: 0x%02x\n", state); 833de103c93SChristoph Hellwig return TCM_INVALID_PARAMETER_LIST; 834c66ac9dbSNicholas Bellinger } 835c66ac9dbSNicholas Bellinger 836c66ac9dbSNicholas Bellinger return 0; 837bb91c1a0SHannes Reinecke 838bb91c1a0SHannes Reinecke not_supported: 839bb91c1a0SHannes Reinecke pr_err("ALUA access state %s not supported", 840bb91c1a0SHannes Reinecke core_alua_dump_state(state)); 841bb91c1a0SHannes Reinecke return TCM_INVALID_PARAMETER_LIST; 842c66ac9dbSNicholas Bellinger } 843c66ac9dbSNicholas Bellinger 844c66ac9dbSNicholas Bellinger static char *core_alua_dump_state(int state) 845c66ac9dbSNicholas Bellinger { 846c66ac9dbSNicholas Bellinger switch (state) { 84773f3bf51SHannes Reinecke case ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED: 848c66ac9dbSNicholas Bellinger return "Active/Optimized"; 849c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_ACTIVE_NON_OPTIMIZED: 850c66ac9dbSNicholas Bellinger return "Active/NonOptimized"; 851c66094bfSHannes Reinecke case ALUA_ACCESS_STATE_LBA_DEPENDENT: 852c66094bfSHannes Reinecke return "LBA Dependent"; 853c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_STANDBY: 854c66ac9dbSNicholas Bellinger return "Standby"; 855c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_UNAVAILABLE: 856c66ac9dbSNicholas Bellinger return "Unavailable"; 857c66ac9dbSNicholas Bellinger case ALUA_ACCESS_STATE_OFFLINE: 858c66ac9dbSNicholas Bellinger return "Offline"; 859bb91c1a0SHannes Reinecke case ALUA_ACCESS_STATE_TRANSITION: 860bb91c1a0SHannes Reinecke return "Transitioning"; 861c66ac9dbSNicholas Bellinger default: 862c66ac9dbSNicholas Bellinger return "Unknown"; 863c66ac9dbSNicholas Bellinger } 864c66ac9dbSNicholas Bellinger 865c66ac9dbSNicholas Bellinger return NULL; 866c66ac9dbSNicholas Bellinger } 867c66ac9dbSNicholas Bellinger 868c66ac9dbSNicholas Bellinger char *core_alua_dump_status(int status) 869c66ac9dbSNicholas Bellinger { 870c66ac9dbSNicholas Bellinger switch (status) { 871c66ac9dbSNicholas Bellinger case ALUA_STATUS_NONE: 872c66ac9dbSNicholas Bellinger return "None"; 873125d0119SHannes Reinecke case ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG: 874125d0119SHannes Reinecke return "Altered by Explicit STPG"; 875125d0119SHannes Reinecke case ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA: 876125d0119SHannes Reinecke return "Altered by Implicit ALUA"; 877c66ac9dbSNicholas Bellinger default: 878c66ac9dbSNicholas Bellinger return "Unknown"; 879c66ac9dbSNicholas Bellinger } 880c66ac9dbSNicholas Bellinger 881c66ac9dbSNicholas Bellinger return NULL; 882c66ac9dbSNicholas Bellinger } 883c66ac9dbSNicholas Bellinger 884c66ac9dbSNicholas Bellinger /* 885c66ac9dbSNicholas Bellinger * Used by fabric modules to determine when we need to delay processing 886c66ac9dbSNicholas Bellinger * for the Active/NonOptimized paths.. 887c66ac9dbSNicholas Bellinger */ 888c66ac9dbSNicholas Bellinger int core_alua_check_nonop_delay( 889c66ac9dbSNicholas Bellinger struct se_cmd *cmd) 890c66ac9dbSNicholas Bellinger { 891c66ac9dbSNicholas Bellinger if (!(cmd->se_cmd_flags & SCF_ALUA_NON_OPTIMIZED)) 892c66ac9dbSNicholas Bellinger return 0; 893c66ac9dbSNicholas Bellinger if (in_interrupt()) 894c66ac9dbSNicholas Bellinger return 0; 895c66ac9dbSNicholas Bellinger /* 896c66ac9dbSNicholas Bellinger * The ALUA Active/NonOptimized access state delay can be disabled 897c66ac9dbSNicholas Bellinger * in via configfs with a value of zero 898c66ac9dbSNicholas Bellinger */ 8996708bb27SAndy Grover if (!cmd->alua_nonop_delay) 900c66ac9dbSNicholas Bellinger return 0; 901c66ac9dbSNicholas Bellinger /* 902c66ac9dbSNicholas Bellinger * struct se_cmd->alua_nonop_delay gets set by a target port group 903c66ac9dbSNicholas Bellinger * defined interval in core_alua_state_nonoptimized() 904c66ac9dbSNicholas Bellinger */ 905c66ac9dbSNicholas Bellinger msleep_interruptible(cmd->alua_nonop_delay); 906c66ac9dbSNicholas Bellinger return 0; 907c66ac9dbSNicholas Bellinger } 908c66ac9dbSNicholas Bellinger EXPORT_SYMBOL(core_alua_check_nonop_delay); 909c66ac9dbSNicholas Bellinger 910c66ac9dbSNicholas Bellinger /* 911c66ac9dbSNicholas Bellinger * Called with tg_pt_gp->tg_pt_gp_md_mutex or tg_pt_gp_mem->sep_tg_pt_md_mutex 912c66ac9dbSNicholas Bellinger * 913c66ac9dbSNicholas Bellinger */ 914c66ac9dbSNicholas Bellinger static int core_alua_write_tpg_metadata( 915c66ac9dbSNicholas Bellinger const char *path, 916c66ac9dbSNicholas Bellinger unsigned char *md_buf, 917c66ac9dbSNicholas Bellinger u32 md_buf_len) 918c66ac9dbSNicholas Bellinger { 9190e9b10a9SAl Viro struct file *file = filp_open(path, O_RDWR | O_CREAT | O_TRUNC, 0600); 9200e9b10a9SAl Viro int ret; 921c66ac9dbSNicholas Bellinger 9220e9b10a9SAl Viro if (IS_ERR(file)) { 9230e9b10a9SAl Viro pr_err("filp_open(%s) for ALUA metadata failed\n", path); 924c66ac9dbSNicholas Bellinger return -ENODEV; 925c66ac9dbSNicholas Bellinger } 9260e9b10a9SAl Viro ret = kernel_write(file, md_buf, md_buf_len, 0); 9270e9b10a9SAl Viro if (ret < 0) 9286708bb27SAndy Grover pr_err("Error writing ALUA metadata file: %s\n", path); 9290e9b10a9SAl Viro fput(file); 930f730f915SGera Kazakov return (ret < 0) ? -EIO : 0; 931c66ac9dbSNicholas Bellinger } 932c66ac9dbSNicholas Bellinger 933c66ac9dbSNicholas Bellinger /* 934c66ac9dbSNicholas Bellinger * Called with tg_pt_gp->tg_pt_gp_md_mutex held 935c66ac9dbSNicholas Bellinger */ 936c66ac9dbSNicholas Bellinger static int core_alua_update_tpg_primary_metadata( 9379c6e164cSHannes Reinecke struct t10_alua_tg_pt_gp *tg_pt_gp) 938c66ac9dbSNicholas Bellinger { 9391e0b9403SHannes Reinecke unsigned char *md_buf; 9400fd97ccfSChristoph Hellwig struct t10_wwn *wwn = &tg_pt_gp->tg_pt_gp_dev->t10_wwn; 941c66ac9dbSNicholas Bellinger char path[ALUA_METADATA_PATH_LEN]; 9421e0b9403SHannes Reinecke int len, rc; 9431e0b9403SHannes Reinecke 9441e0b9403SHannes Reinecke md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL); 9451e0b9403SHannes Reinecke if (!md_buf) { 9461e0b9403SHannes Reinecke pr_err("Unable to allocate buf for ALUA metadata\n"); 9471e0b9403SHannes Reinecke return -ENOMEM; 9481e0b9403SHannes Reinecke } 949c66ac9dbSNicholas Bellinger 950c66ac9dbSNicholas Bellinger memset(path, 0, ALUA_METADATA_PATH_LEN); 951c66ac9dbSNicholas Bellinger 9521e0b9403SHannes Reinecke len = snprintf(md_buf, ALUA_MD_BUF_LEN, 953c66ac9dbSNicholas Bellinger "tg_pt_gp_id=%hu\n" 954c66ac9dbSNicholas Bellinger "alua_access_state=0x%02x\n" 955c66ac9dbSNicholas Bellinger "alua_access_status=0x%02x\n", 9569c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_id, 9579c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_pending_state, 958c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_status); 959c66ac9dbSNicholas Bellinger 960c66ac9dbSNicholas Bellinger snprintf(path, ALUA_METADATA_PATH_LEN, 961c66ac9dbSNicholas Bellinger "/var/target/alua/tpgs_%s/%s", &wwn->unit_serial[0], 962c66ac9dbSNicholas Bellinger config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item)); 963c66ac9dbSNicholas Bellinger 9641e0b9403SHannes Reinecke rc = core_alua_write_tpg_metadata(path, md_buf, len); 9651e0b9403SHannes Reinecke kfree(md_buf); 9661e0b9403SHannes Reinecke return rc; 967c66ac9dbSNicholas Bellinger } 968c66ac9dbSNicholas Bellinger 9699c6e164cSHannes Reinecke static void core_alua_do_transition_tg_pt_work(struct work_struct *work) 970c66ac9dbSNicholas Bellinger { 9719c6e164cSHannes Reinecke struct t10_alua_tg_pt_gp *tg_pt_gp = container_of(work, 9729c6e164cSHannes Reinecke struct t10_alua_tg_pt_gp, tg_pt_gp_transition_work.work); 9739c6e164cSHannes Reinecke struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; 974c66ac9dbSNicholas Bellinger struct se_dev_entry *se_deve; 975c66ac9dbSNicholas Bellinger struct se_lun_acl *lacl; 976c66ac9dbSNicholas Bellinger struct se_port *port; 977c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *mem; 9789c6e164cSHannes Reinecke bool explicit = (tg_pt_gp->tg_pt_gp_alua_access_status == 9799c6e164cSHannes Reinecke ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG); 980c66ac9dbSNicholas Bellinger 981c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 982c66ac9dbSNicholas Bellinger list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list, 983c66ac9dbSNicholas Bellinger tg_pt_gp_mem_list) { 984c66ac9dbSNicholas Bellinger port = mem->tg_pt; 985c66ac9dbSNicholas Bellinger /* 986c66ac9dbSNicholas Bellinger * After an implicit target port asymmetric access state 987c66ac9dbSNicholas Bellinger * change, a device server shall establish a unit attention 988c66ac9dbSNicholas Bellinger * condition for the initiator port associated with every I_T 989c66ac9dbSNicholas Bellinger * nexus with the additional sense code set to ASYMMETRIC 990f1ae05d5SHannes Reinecke * ACCESS STATE CHANGED. 991c66ac9dbSNicholas Bellinger * 992c66ac9dbSNicholas Bellinger * After an explicit target port asymmetric access state 993c66ac9dbSNicholas Bellinger * change, a device server shall establish a unit attention 994c66ac9dbSNicholas Bellinger * condition with the additional sense code set to ASYMMETRIC 995c66ac9dbSNicholas Bellinger * ACCESS STATE CHANGED for the initiator port associated with 996c66ac9dbSNicholas Bellinger * every I_T nexus other than the I_T nexus on which the SET 997c66ac9dbSNicholas Bellinger * TARGET PORT GROUPS command 998c66ac9dbSNicholas Bellinger */ 999c66ac9dbSNicholas Bellinger atomic_inc(&mem->tg_pt_gp_mem_ref_cnt); 1000c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 1001c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1002c66ac9dbSNicholas Bellinger 1003c66ac9dbSNicholas Bellinger spin_lock_bh(&port->sep_alua_lock); 1004c66ac9dbSNicholas Bellinger list_for_each_entry(se_deve, &port->sep_alua_list, 1005c66ac9dbSNicholas Bellinger alua_port_list) { 1006c66ac9dbSNicholas Bellinger lacl = se_deve->se_lun_acl; 1007c66ac9dbSNicholas Bellinger /* 1008c66ac9dbSNicholas Bellinger * se_deve->se_lun_acl pointer may be NULL for a 1009125d0119SHannes Reinecke * entry created without explicit Node+MappedLUN ACLs 1010c66ac9dbSNicholas Bellinger */ 10116708bb27SAndy Grover if (!lacl) 1012c66ac9dbSNicholas Bellinger continue; 1013c66ac9dbSNicholas Bellinger 10149c6e164cSHannes Reinecke if ((tg_pt_gp->tg_pt_gp_alua_access_status == 10159c6e164cSHannes Reinecke ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) && 10169c6e164cSHannes Reinecke (tg_pt_gp->tg_pt_gp_alua_nacl != NULL) && 10179c6e164cSHannes Reinecke (tg_pt_gp->tg_pt_gp_alua_nacl == lacl->se_lun_nacl) && 10189c6e164cSHannes Reinecke (tg_pt_gp->tg_pt_gp_alua_port != NULL) && 10199c6e164cSHannes Reinecke (tg_pt_gp->tg_pt_gp_alua_port == port)) 1020c66ac9dbSNicholas Bellinger continue; 1021c66ac9dbSNicholas Bellinger 1022c66ac9dbSNicholas Bellinger core_scsi3_ua_allocate(lacl->se_lun_nacl, 1023c66ac9dbSNicholas Bellinger se_deve->mapped_lun, 0x2A, 1024c66ac9dbSNicholas Bellinger ASCQ_2AH_ASYMMETRIC_ACCESS_STATE_CHANGED); 1025c66ac9dbSNicholas Bellinger } 1026c66ac9dbSNicholas Bellinger spin_unlock_bh(&port->sep_alua_lock); 1027c66ac9dbSNicholas Bellinger 1028c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1029c66ac9dbSNicholas Bellinger atomic_dec(&mem->tg_pt_gp_mem_ref_cnt); 1030c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 1031c66ac9dbSNicholas Bellinger } 1032c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1033c66ac9dbSNicholas Bellinger /* 1034c66ac9dbSNicholas Bellinger * Update the ALUA metadata buf that has been allocated in 1035c66ac9dbSNicholas Bellinger * core_alua_do_port_transition(), this metadata will be written 1036c66ac9dbSNicholas Bellinger * to struct file. 1037c66ac9dbSNicholas Bellinger * 1038c66ac9dbSNicholas Bellinger * Note that there is the case where we do not want to update the 1039c66ac9dbSNicholas Bellinger * metadata when the saved metadata is being parsed in userspace 1040c66ac9dbSNicholas Bellinger * when setting the existing port access state and access status. 1041c66ac9dbSNicholas Bellinger * 1042c66ac9dbSNicholas Bellinger * Also note that the failure to write out the ALUA metadata to 1043c66ac9dbSNicholas Bellinger * struct file does NOT affect the actual ALUA transition. 1044c66ac9dbSNicholas Bellinger */ 1045c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_write_metadata) { 1046c66ac9dbSNicholas Bellinger mutex_lock(&tg_pt_gp->tg_pt_gp_md_mutex); 10479c6e164cSHannes Reinecke core_alua_update_tpg_primary_metadata(tg_pt_gp); 1048c66ac9dbSNicholas Bellinger mutex_unlock(&tg_pt_gp->tg_pt_gp_md_mutex); 1049c66ac9dbSNicholas Bellinger } 1050c66ac9dbSNicholas Bellinger /* 1051c66ac9dbSNicholas Bellinger * Set the current primary ALUA access state to the requested new state 1052c66ac9dbSNicholas Bellinger */ 1053dfbce75aSHannes Reinecke atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, 1054dfbce75aSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_pending_state); 1055c66ac9dbSNicholas Bellinger 10566708bb27SAndy Grover pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu" 1057125d0119SHannes Reinecke " from primary access state %s to %s\n", (explicit) ? "explicit" : 1058125d0119SHannes Reinecke "implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), 1059dfbce75aSHannes Reinecke tg_pt_gp->tg_pt_gp_id, 1060dfbce75aSHannes Reinecke core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_previous_state), 1061dfbce75aSHannes Reinecke core_alua_dump_state(tg_pt_gp->tg_pt_gp_alua_pending_state)); 10629c6e164cSHannes Reinecke spin_lock(&dev->t10_alua.tg_pt_gps_lock); 10639c6e164cSHannes Reinecke atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 10649c6e164cSHannes Reinecke smp_mb__after_atomic_dec(); 10659c6e164cSHannes Reinecke spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 10669c6e164cSHannes Reinecke 10679c6e164cSHannes Reinecke if (tg_pt_gp->tg_pt_gp_transition_complete) 10689c6e164cSHannes Reinecke complete(tg_pt_gp->tg_pt_gp_transition_complete); 10699c6e164cSHannes Reinecke } 10709c6e164cSHannes Reinecke 10719c6e164cSHannes Reinecke static int core_alua_do_transition_tg_pt( 10729c6e164cSHannes Reinecke struct t10_alua_tg_pt_gp *tg_pt_gp, 10739c6e164cSHannes Reinecke int new_state, 10749c6e164cSHannes Reinecke int explicit) 10759c6e164cSHannes Reinecke { 10769c6e164cSHannes Reinecke struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; 10779c6e164cSHannes Reinecke DECLARE_COMPLETION_ONSTACK(wait); 10789c6e164cSHannes Reinecke 10799c6e164cSHannes Reinecke /* Nothing to be done here */ 10809c6e164cSHannes Reinecke if (atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) == new_state) 10819c6e164cSHannes Reinecke return 0; 10829c6e164cSHannes Reinecke 10839c6e164cSHannes Reinecke if (new_state == ALUA_ACCESS_STATE_TRANSITION) 10849c6e164cSHannes Reinecke return -EAGAIN; 10859c6e164cSHannes Reinecke 10869c6e164cSHannes Reinecke /* 10879c6e164cSHannes Reinecke * Flush any pending transitions 10889c6e164cSHannes Reinecke */ 10899c6e164cSHannes Reinecke if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs && 10909c6e164cSHannes Reinecke atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state) == 10919c6e164cSHannes Reinecke ALUA_ACCESS_STATE_TRANSITION) { 10929c6e164cSHannes Reinecke /* Just in case */ 10939c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_pending_state = new_state; 10949c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_transition_complete = &wait; 10959c6e164cSHannes Reinecke flush_delayed_work(&tg_pt_gp->tg_pt_gp_transition_work); 10969c6e164cSHannes Reinecke wait_for_completion(&wait); 10979c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_transition_complete = NULL; 10989c6e164cSHannes Reinecke return 0; 10999c6e164cSHannes Reinecke } 11009c6e164cSHannes Reinecke 11019c6e164cSHannes Reinecke /* 11029c6e164cSHannes Reinecke * Save the old primary ALUA access state, and set the current state 11039c6e164cSHannes Reinecke * to ALUA_ACCESS_STATE_TRANSITION. 11049c6e164cSHannes Reinecke */ 11059c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_previous_state = 11069c6e164cSHannes Reinecke atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); 11079c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_pending_state = new_state; 11089c6e164cSHannes Reinecke 11099c6e164cSHannes Reinecke atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, 11109c6e164cSHannes Reinecke ALUA_ACCESS_STATE_TRANSITION); 11119c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_access_status = (explicit) ? 11129c6e164cSHannes Reinecke ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : 11139c6e164cSHannes Reinecke ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; 11149c6e164cSHannes Reinecke 11159c6e164cSHannes Reinecke /* 11169c6e164cSHannes Reinecke * Check for the optional ALUA primary state transition delay 11179c6e164cSHannes Reinecke */ 11189c6e164cSHannes Reinecke if (tg_pt_gp->tg_pt_gp_trans_delay_msecs != 0) 11199c6e164cSHannes Reinecke msleep_interruptible(tg_pt_gp->tg_pt_gp_trans_delay_msecs); 11209c6e164cSHannes Reinecke 11219c6e164cSHannes Reinecke /* 11229c6e164cSHannes Reinecke * Take a reference for workqueue item 11239c6e164cSHannes Reinecke */ 11249c6e164cSHannes Reinecke spin_lock(&dev->t10_alua.tg_pt_gps_lock); 11259c6e164cSHannes Reinecke atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 11269c6e164cSHannes Reinecke smp_mb__after_atomic_inc(); 11279c6e164cSHannes Reinecke spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 11289c6e164cSHannes Reinecke 11299c6e164cSHannes Reinecke if (!explicit && tg_pt_gp->tg_pt_gp_implicit_trans_secs) { 11309c6e164cSHannes Reinecke unsigned long transition_tmo; 11319c6e164cSHannes Reinecke 11329c6e164cSHannes Reinecke transition_tmo = tg_pt_gp->tg_pt_gp_implicit_trans_secs * HZ; 11339c6e164cSHannes Reinecke queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq, 11349c6e164cSHannes Reinecke &tg_pt_gp->tg_pt_gp_transition_work, 11359c6e164cSHannes Reinecke transition_tmo); 11369c6e164cSHannes Reinecke } else { 11379c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_transition_complete = &wait; 11389c6e164cSHannes Reinecke queue_delayed_work(tg_pt_gp->tg_pt_gp_dev->tmr_wq, 11399c6e164cSHannes Reinecke &tg_pt_gp->tg_pt_gp_transition_work, 0); 11409c6e164cSHannes Reinecke wait_for_completion(&wait); 11419c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_transition_complete = NULL; 11429c6e164cSHannes Reinecke } 1143c66ac9dbSNicholas Bellinger 1144c66ac9dbSNicholas Bellinger return 0; 1145c66ac9dbSNicholas Bellinger } 1146c66ac9dbSNicholas Bellinger 1147c66ac9dbSNicholas Bellinger int core_alua_do_port_transition( 1148c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *l_tg_pt_gp, 1149c66ac9dbSNicholas Bellinger struct se_device *l_dev, 1150c66ac9dbSNicholas Bellinger struct se_port *l_port, 1151c66ac9dbSNicholas Bellinger struct se_node_acl *l_nacl, 1152c66ac9dbSNicholas Bellinger int new_state, 1153125d0119SHannes Reinecke int explicit) 1154c66ac9dbSNicholas Bellinger { 1155c66ac9dbSNicholas Bellinger struct se_device *dev; 1156c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1157c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, *local_lu_gp_mem; 1158c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 11599c6e164cSHannes Reinecke int primary, valid_states, rc = 0; 1160c66ac9dbSNicholas Bellinger 1161bb91c1a0SHannes Reinecke valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states; 1162bb91c1a0SHannes Reinecke if (core_alua_check_transition(new_state, valid_states, &primary) != 0) 1163c66ac9dbSNicholas Bellinger return -EINVAL; 1164c66ac9dbSNicholas Bellinger 1165c66ac9dbSNicholas Bellinger local_lu_gp_mem = l_dev->dev_alua_lu_gp_mem; 1166c66ac9dbSNicholas Bellinger spin_lock(&local_lu_gp_mem->lu_gp_mem_lock); 1167c66ac9dbSNicholas Bellinger lu_gp = local_lu_gp_mem->lu_gp; 1168c66ac9dbSNicholas Bellinger atomic_inc(&lu_gp->lu_gp_ref_cnt); 1169c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 1170c66ac9dbSNicholas Bellinger spin_unlock(&local_lu_gp_mem->lu_gp_mem_lock); 1171c66ac9dbSNicholas Bellinger /* 1172c66ac9dbSNicholas Bellinger * For storage objects that are members of the 'default_lu_gp', 1173c66ac9dbSNicholas Bellinger * we only do transition on the passed *l_tp_pt_gp, and not 1174c66ac9dbSNicholas Bellinger * on all of the matching target port groups IDs in default_lu_gp. 1175c66ac9dbSNicholas Bellinger */ 11766708bb27SAndy Grover if (!lu_gp->lu_gp_id) { 1177c66ac9dbSNicholas Bellinger /* 1178c66ac9dbSNicholas Bellinger * core_alua_do_transition_tg_pt() will always return 1179c66ac9dbSNicholas Bellinger * success. 1180c66ac9dbSNicholas Bellinger */ 11819c6e164cSHannes Reinecke l_tg_pt_gp->tg_pt_gp_alua_port = l_port; 11829c6e164cSHannes Reinecke l_tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl; 11839c6e164cSHannes Reinecke rc = core_alua_do_transition_tg_pt(l_tg_pt_gp, 11841e0b9403SHannes Reinecke new_state, explicit); 1185c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp->lu_gp_ref_cnt); 1186c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 11879c6e164cSHannes Reinecke return rc; 1188c66ac9dbSNicholas Bellinger } 1189c66ac9dbSNicholas Bellinger /* 1190c66ac9dbSNicholas Bellinger * For all other LU groups aside from 'default_lu_gp', walk all of 1191c66ac9dbSNicholas Bellinger * the associated storage objects looking for a matching target port 1192c66ac9dbSNicholas Bellinger * group ID from the local target port group. 1193c66ac9dbSNicholas Bellinger */ 1194c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1195c66ac9dbSNicholas Bellinger list_for_each_entry(lu_gp_mem, &lu_gp->lu_gp_mem_list, 1196c66ac9dbSNicholas Bellinger lu_gp_mem_list) { 1197c66ac9dbSNicholas Bellinger 1198c66ac9dbSNicholas Bellinger dev = lu_gp_mem->lu_gp_mem_dev; 1199c66ac9dbSNicholas Bellinger atomic_inc(&lu_gp_mem->lu_gp_mem_ref_cnt); 1200c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 1201c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1202c66ac9dbSNicholas Bellinger 12030fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1204c66ac9dbSNicholas Bellinger list_for_each_entry(tg_pt_gp, 12050fd97ccfSChristoph Hellwig &dev->t10_alua.tg_pt_gps_list, 1206c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 1207c66ac9dbSNicholas Bellinger 12086708bb27SAndy Grover if (!tg_pt_gp->tg_pt_gp_valid_id) 1209c66ac9dbSNicholas Bellinger continue; 1210c66ac9dbSNicholas Bellinger /* 1211c66ac9dbSNicholas Bellinger * If the target behavior port asymmetric access state 1212f1ae05d5SHannes Reinecke * is changed for any target port group accessible via 1213c66ac9dbSNicholas Bellinger * a logical unit within a LU group, the target port 1214c66ac9dbSNicholas Bellinger * behavior group asymmetric access states for the same 1215c66ac9dbSNicholas Bellinger * target port group accessible via other logical units 1216c66ac9dbSNicholas Bellinger * in that LU group will also change. 1217c66ac9dbSNicholas Bellinger */ 1218c66ac9dbSNicholas Bellinger if (l_tg_pt_gp->tg_pt_gp_id != tg_pt_gp->tg_pt_gp_id) 1219c66ac9dbSNicholas Bellinger continue; 1220c66ac9dbSNicholas Bellinger 1221c66ac9dbSNicholas Bellinger if (l_tg_pt_gp == tg_pt_gp) { 12229c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_port = l_port; 12239c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl; 1224c66ac9dbSNicholas Bellinger } else { 12259c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_port = NULL; 12269c6e164cSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_nacl = NULL; 1227c66ac9dbSNicholas Bellinger } 1228c66ac9dbSNicholas Bellinger atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 1229c66ac9dbSNicholas Bellinger smp_mb__after_atomic_inc(); 12300fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1231c66ac9dbSNicholas Bellinger /* 1232c66ac9dbSNicholas Bellinger * core_alua_do_transition_tg_pt() will always return 1233c66ac9dbSNicholas Bellinger * success. 1234c66ac9dbSNicholas Bellinger */ 12359c6e164cSHannes Reinecke rc = core_alua_do_transition_tg_pt(tg_pt_gp, 12369c6e164cSHannes Reinecke new_state, explicit); 1237c66ac9dbSNicholas Bellinger 12380fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1239c66ac9dbSNicholas Bellinger atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 1240c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 12419c6e164cSHannes Reinecke if (rc) 12429c6e164cSHannes Reinecke break; 1243c66ac9dbSNicholas Bellinger } 12440fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1245c66ac9dbSNicholas Bellinger 1246c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1247c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp_mem->lu_gp_mem_ref_cnt); 1248c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 1249c66ac9dbSNicholas Bellinger } 1250c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1251c66ac9dbSNicholas Bellinger 12529c6e164cSHannes Reinecke if (!rc) { 12536708bb27SAndy Grover pr_debug("Successfully processed LU Group: %s all ALUA TG PT" 1254c66ac9dbSNicholas Bellinger " Group IDs: %hu %s transition to primary state: %s\n", 1255c66ac9dbSNicholas Bellinger config_item_name(&lu_gp->lu_gp_group.cg_item), 12569c6e164cSHannes Reinecke l_tg_pt_gp->tg_pt_gp_id, 12579c6e164cSHannes Reinecke (explicit) ? "explicit" : "implicit", 1258c66ac9dbSNicholas Bellinger core_alua_dump_state(new_state)); 12599c6e164cSHannes Reinecke } 1260c66ac9dbSNicholas Bellinger 1261c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp->lu_gp_ref_cnt); 1262c66ac9dbSNicholas Bellinger smp_mb__after_atomic_dec(); 12639c6e164cSHannes Reinecke return rc; 1264c66ac9dbSNicholas Bellinger } 1265c66ac9dbSNicholas Bellinger 1266c66ac9dbSNicholas Bellinger /* 1267c66ac9dbSNicholas Bellinger * Called with tg_pt_gp_mem->sep_tg_pt_md_mutex held 1268c66ac9dbSNicholas Bellinger */ 1269c66ac9dbSNicholas Bellinger static int core_alua_update_tpg_secondary_metadata( 1270c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 12711e0b9403SHannes Reinecke struct se_port *port) 1272c66ac9dbSNicholas Bellinger { 12731e0b9403SHannes Reinecke unsigned char *md_buf; 1274c66ac9dbSNicholas Bellinger struct se_portal_group *se_tpg = port->sep_tpg; 1275c66ac9dbSNicholas Bellinger char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN]; 12761e0b9403SHannes Reinecke int len, rc; 12771e0b9403SHannes Reinecke 12781e0b9403SHannes Reinecke md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL); 12791e0b9403SHannes Reinecke if (!md_buf) { 12801e0b9403SHannes Reinecke pr_err("Unable to allocate buf for ALUA metadata\n"); 12811e0b9403SHannes Reinecke return -ENOMEM; 12821e0b9403SHannes Reinecke } 1283c66ac9dbSNicholas Bellinger 1284c66ac9dbSNicholas Bellinger memset(path, 0, ALUA_METADATA_PATH_LEN); 1285c66ac9dbSNicholas Bellinger memset(wwn, 0, ALUA_SECONDARY_METADATA_WWN_LEN); 1286c66ac9dbSNicholas Bellinger 1287c66ac9dbSNicholas Bellinger len = snprintf(wwn, ALUA_SECONDARY_METADATA_WWN_LEN, "%s", 1288e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg)); 1289c66ac9dbSNicholas Bellinger 1290e3d6f909SAndy Grover if (se_tpg->se_tpg_tfo->tpg_get_tag != NULL) 1291c66ac9dbSNicholas Bellinger snprintf(wwn+len, ALUA_SECONDARY_METADATA_WWN_LEN-len, "+%hu", 1292e3d6f909SAndy Grover se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); 1293c66ac9dbSNicholas Bellinger 12941e0b9403SHannes Reinecke len = snprintf(md_buf, ALUA_MD_BUF_LEN, "alua_tg_pt_offline=%d\n" 1295c66ac9dbSNicholas Bellinger "alua_tg_pt_status=0x%02x\n", 1296c66ac9dbSNicholas Bellinger atomic_read(&port->sep_tg_pt_secondary_offline), 1297c66ac9dbSNicholas Bellinger port->sep_tg_pt_secondary_stat); 1298c66ac9dbSNicholas Bellinger 1299c66ac9dbSNicholas Bellinger snprintf(path, ALUA_METADATA_PATH_LEN, "/var/target/alua/%s/%s/lun_%u", 1300e3d6f909SAndy Grover se_tpg->se_tpg_tfo->get_fabric_name(), wwn, 1301c66ac9dbSNicholas Bellinger port->sep_lun->unpacked_lun); 1302c66ac9dbSNicholas Bellinger 13031e0b9403SHannes Reinecke rc = core_alua_write_tpg_metadata(path, md_buf, len); 13041e0b9403SHannes Reinecke kfree(md_buf); 13051e0b9403SHannes Reinecke 13061e0b9403SHannes Reinecke return rc; 1307c66ac9dbSNicholas Bellinger } 1308c66ac9dbSNicholas Bellinger 1309c66ac9dbSNicholas Bellinger static int core_alua_set_tg_pt_secondary_state( 1310c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 1311c66ac9dbSNicholas Bellinger struct se_port *port, 1312125d0119SHannes Reinecke int explicit, 1313c66ac9dbSNicholas Bellinger int offline) 1314c66ac9dbSNicholas Bellinger { 1315c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1316c66ac9dbSNicholas Bellinger int trans_delay_msecs; 1317c66ac9dbSNicholas Bellinger 1318c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1319c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 13206708bb27SAndy Grover if (!tg_pt_gp) { 1321c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 13226708bb27SAndy Grover pr_err("Unable to complete secondary state" 1323c66ac9dbSNicholas Bellinger " transition\n"); 1324e3d6f909SAndy Grover return -EINVAL; 1325c66ac9dbSNicholas Bellinger } 1326c66ac9dbSNicholas Bellinger trans_delay_msecs = tg_pt_gp->tg_pt_gp_trans_delay_msecs; 1327c66ac9dbSNicholas Bellinger /* 1328c66ac9dbSNicholas Bellinger * Set the secondary ALUA target port access state to OFFLINE 1329c66ac9dbSNicholas Bellinger * or release the previously secondary state for struct se_port 1330c66ac9dbSNicholas Bellinger */ 1331c66ac9dbSNicholas Bellinger if (offline) 1332c66ac9dbSNicholas Bellinger atomic_set(&port->sep_tg_pt_secondary_offline, 1); 1333c66ac9dbSNicholas Bellinger else 1334c66ac9dbSNicholas Bellinger atomic_set(&port->sep_tg_pt_secondary_offline, 0); 1335c66ac9dbSNicholas Bellinger 1336125d0119SHannes Reinecke port->sep_tg_pt_secondary_stat = (explicit) ? 1337125d0119SHannes Reinecke ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : 1338125d0119SHannes Reinecke ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; 1339c66ac9dbSNicholas Bellinger 13406708bb27SAndy Grover pr_debug("Successful %s ALUA transition TG PT Group: %s ID: %hu" 1341125d0119SHannes Reinecke " to secondary access state: %s\n", (explicit) ? "explicit" : 1342125d0119SHannes Reinecke "implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), 1343c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE"); 1344c66ac9dbSNicholas Bellinger 1345c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1346c66ac9dbSNicholas Bellinger /* 1347c66ac9dbSNicholas Bellinger * Do the optional transition delay after we set the secondary 1348c66ac9dbSNicholas Bellinger * ALUA access state. 1349c66ac9dbSNicholas Bellinger */ 1350c66ac9dbSNicholas Bellinger if (trans_delay_msecs != 0) 1351c66ac9dbSNicholas Bellinger msleep_interruptible(trans_delay_msecs); 1352c66ac9dbSNicholas Bellinger /* 1353c66ac9dbSNicholas Bellinger * See if we need to update the ALUA fabric port metadata for 1354c66ac9dbSNicholas Bellinger * secondary state and status 1355c66ac9dbSNicholas Bellinger */ 1356c66ac9dbSNicholas Bellinger if (port->sep_tg_pt_secondary_write_md) { 1357c66ac9dbSNicholas Bellinger mutex_lock(&port->sep_tg_pt_md_mutex); 13581e0b9403SHannes Reinecke core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port); 1359c66ac9dbSNicholas Bellinger mutex_unlock(&port->sep_tg_pt_md_mutex); 1360c66ac9dbSNicholas Bellinger } 1361c66ac9dbSNicholas Bellinger 1362c66ac9dbSNicholas Bellinger return 0; 1363c66ac9dbSNicholas Bellinger } 1364c66ac9dbSNicholas Bellinger 1365229d4f11SHannes Reinecke struct t10_alua_lba_map * 1366229d4f11SHannes Reinecke core_alua_allocate_lba_map(struct list_head *list, 1367229d4f11SHannes Reinecke u64 first_lba, u64 last_lba) 1368229d4f11SHannes Reinecke { 1369229d4f11SHannes Reinecke struct t10_alua_lba_map *lba_map; 1370229d4f11SHannes Reinecke 1371229d4f11SHannes Reinecke lba_map = kmem_cache_zalloc(t10_alua_lba_map_cache, GFP_KERNEL); 1372229d4f11SHannes Reinecke if (!lba_map) { 1373229d4f11SHannes Reinecke pr_err("Unable to allocate struct t10_alua_lba_map\n"); 1374229d4f11SHannes Reinecke return ERR_PTR(-ENOMEM); 1375229d4f11SHannes Reinecke } 1376229d4f11SHannes Reinecke INIT_LIST_HEAD(&lba_map->lba_map_mem_list); 1377229d4f11SHannes Reinecke lba_map->lba_map_first_lba = first_lba; 1378229d4f11SHannes Reinecke lba_map->lba_map_last_lba = last_lba; 1379229d4f11SHannes Reinecke 1380229d4f11SHannes Reinecke list_add_tail(&lba_map->lba_map_list, list); 1381229d4f11SHannes Reinecke return lba_map; 1382229d4f11SHannes Reinecke } 1383229d4f11SHannes Reinecke 1384229d4f11SHannes Reinecke int 1385229d4f11SHannes Reinecke core_alua_allocate_lba_map_mem(struct t10_alua_lba_map *lba_map, 1386229d4f11SHannes Reinecke int pg_id, int state) 1387229d4f11SHannes Reinecke { 1388229d4f11SHannes Reinecke struct t10_alua_lba_map_member *lba_map_mem; 1389229d4f11SHannes Reinecke 1390229d4f11SHannes Reinecke list_for_each_entry(lba_map_mem, &lba_map->lba_map_mem_list, 1391229d4f11SHannes Reinecke lba_map_mem_list) { 1392229d4f11SHannes Reinecke if (lba_map_mem->lba_map_mem_alua_pg_id == pg_id) { 1393229d4f11SHannes Reinecke pr_err("Duplicate pg_id %d in lba_map\n", pg_id); 1394229d4f11SHannes Reinecke return -EINVAL; 1395229d4f11SHannes Reinecke } 1396229d4f11SHannes Reinecke } 1397229d4f11SHannes Reinecke 1398229d4f11SHannes Reinecke lba_map_mem = kmem_cache_zalloc(t10_alua_lba_map_mem_cache, GFP_KERNEL); 1399229d4f11SHannes Reinecke if (!lba_map_mem) { 1400229d4f11SHannes Reinecke pr_err("Unable to allocate struct t10_alua_lba_map_mem\n"); 1401229d4f11SHannes Reinecke return -ENOMEM; 1402229d4f11SHannes Reinecke } 1403229d4f11SHannes Reinecke lba_map_mem->lba_map_mem_alua_state = state; 1404229d4f11SHannes Reinecke lba_map_mem->lba_map_mem_alua_pg_id = pg_id; 1405229d4f11SHannes Reinecke 1406229d4f11SHannes Reinecke list_add_tail(&lba_map_mem->lba_map_mem_list, 1407229d4f11SHannes Reinecke &lba_map->lba_map_mem_list); 1408229d4f11SHannes Reinecke return 0; 1409229d4f11SHannes Reinecke } 1410229d4f11SHannes Reinecke 1411229d4f11SHannes Reinecke void 1412229d4f11SHannes Reinecke core_alua_free_lba_map(struct list_head *lba_list) 1413229d4f11SHannes Reinecke { 1414229d4f11SHannes Reinecke struct t10_alua_lba_map *lba_map, *lba_map_tmp; 1415229d4f11SHannes Reinecke struct t10_alua_lba_map_member *lba_map_mem, *lba_map_mem_tmp; 1416229d4f11SHannes Reinecke 1417229d4f11SHannes Reinecke list_for_each_entry_safe(lba_map, lba_map_tmp, lba_list, 1418229d4f11SHannes Reinecke lba_map_list) { 1419229d4f11SHannes Reinecke list_for_each_entry_safe(lba_map_mem, lba_map_mem_tmp, 1420229d4f11SHannes Reinecke &lba_map->lba_map_mem_list, 1421229d4f11SHannes Reinecke lba_map_mem_list) { 1422229d4f11SHannes Reinecke list_del(&lba_map_mem->lba_map_mem_list); 1423229d4f11SHannes Reinecke kmem_cache_free(t10_alua_lba_map_mem_cache, 1424229d4f11SHannes Reinecke lba_map_mem); 1425229d4f11SHannes Reinecke } 1426229d4f11SHannes Reinecke list_del(&lba_map->lba_map_list); 1427229d4f11SHannes Reinecke kmem_cache_free(t10_alua_lba_map_cache, lba_map); 1428229d4f11SHannes Reinecke } 1429229d4f11SHannes Reinecke } 1430229d4f11SHannes Reinecke 1431229d4f11SHannes Reinecke void 1432229d4f11SHannes Reinecke core_alua_set_lba_map(struct se_device *dev, struct list_head *lba_map_list, 1433229d4f11SHannes Reinecke int segment_size, int segment_mult) 1434229d4f11SHannes Reinecke { 1435229d4f11SHannes Reinecke struct list_head old_lba_map_list; 1436229d4f11SHannes Reinecke struct t10_alua_tg_pt_gp *tg_pt_gp; 1437229d4f11SHannes Reinecke int activate = 0, supported; 1438229d4f11SHannes Reinecke 1439229d4f11SHannes Reinecke INIT_LIST_HEAD(&old_lba_map_list); 1440229d4f11SHannes Reinecke spin_lock(&dev->t10_alua.lba_map_lock); 1441229d4f11SHannes Reinecke dev->t10_alua.lba_map_segment_size = segment_size; 1442229d4f11SHannes Reinecke dev->t10_alua.lba_map_segment_multiplier = segment_mult; 1443229d4f11SHannes Reinecke list_splice_init(&dev->t10_alua.lba_map_list, &old_lba_map_list); 1444229d4f11SHannes Reinecke if (lba_map_list) { 1445229d4f11SHannes Reinecke list_splice_init(lba_map_list, &dev->t10_alua.lba_map_list); 1446229d4f11SHannes Reinecke activate = 1; 1447229d4f11SHannes Reinecke } 1448229d4f11SHannes Reinecke spin_unlock(&dev->t10_alua.lba_map_lock); 1449229d4f11SHannes Reinecke spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1450229d4f11SHannes Reinecke list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, 1451229d4f11SHannes Reinecke tg_pt_gp_list) { 1452229d4f11SHannes Reinecke 1453229d4f11SHannes Reinecke if (!tg_pt_gp->tg_pt_gp_valid_id) 1454229d4f11SHannes Reinecke continue; 1455229d4f11SHannes Reinecke supported = tg_pt_gp->tg_pt_gp_alua_supported_states; 1456229d4f11SHannes Reinecke if (activate) 1457229d4f11SHannes Reinecke supported |= ALUA_LBD_SUP; 1458229d4f11SHannes Reinecke else 1459229d4f11SHannes Reinecke supported &= ~ALUA_LBD_SUP; 1460229d4f11SHannes Reinecke tg_pt_gp->tg_pt_gp_alua_supported_states = supported; 1461229d4f11SHannes Reinecke } 1462229d4f11SHannes Reinecke spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1463229d4f11SHannes Reinecke core_alua_free_lba_map(&old_lba_map_list); 1464229d4f11SHannes Reinecke } 1465229d4f11SHannes Reinecke 1466c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp * 1467c66ac9dbSNicholas Bellinger core_alua_allocate_lu_gp(const char *name, int def_group) 1468c66ac9dbSNicholas Bellinger { 1469c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1470c66ac9dbSNicholas Bellinger 1471c66ac9dbSNicholas Bellinger lu_gp = kmem_cache_zalloc(t10_alua_lu_gp_cache, GFP_KERNEL); 14726708bb27SAndy Grover if (!lu_gp) { 14736708bb27SAndy Grover pr_err("Unable to allocate struct t10_alua_lu_gp\n"); 14746eab04a8SJustin P. Mattock return ERR_PTR(-ENOMEM); 1475c66ac9dbSNicholas Bellinger } 1476e3d6f909SAndy Grover INIT_LIST_HEAD(&lu_gp->lu_gp_node); 1477c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lu_gp->lu_gp_mem_list); 1478c66ac9dbSNicholas Bellinger spin_lock_init(&lu_gp->lu_gp_lock); 1479c66ac9dbSNicholas Bellinger atomic_set(&lu_gp->lu_gp_ref_cnt, 0); 1480c66ac9dbSNicholas Bellinger 1481c66ac9dbSNicholas Bellinger if (def_group) { 1482e3d6f909SAndy Grover lu_gp->lu_gp_id = alua_lu_gps_counter++; 1483c66ac9dbSNicholas Bellinger lu_gp->lu_gp_valid_id = 1; 1484e3d6f909SAndy Grover alua_lu_gps_count++; 1485c66ac9dbSNicholas Bellinger } 1486c66ac9dbSNicholas Bellinger 1487c66ac9dbSNicholas Bellinger return lu_gp; 1488c66ac9dbSNicholas Bellinger } 1489c66ac9dbSNicholas Bellinger 1490c66ac9dbSNicholas Bellinger int core_alua_set_lu_gp_id(struct t10_alua_lu_gp *lu_gp, u16 lu_gp_id) 1491c66ac9dbSNicholas Bellinger { 1492c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp_tmp; 1493c66ac9dbSNicholas Bellinger u16 lu_gp_id_tmp; 1494c66ac9dbSNicholas Bellinger /* 1495c66ac9dbSNicholas Bellinger * The lu_gp->lu_gp_id may only be set once.. 1496c66ac9dbSNicholas Bellinger */ 1497c66ac9dbSNicholas Bellinger if (lu_gp->lu_gp_valid_id) { 14986708bb27SAndy Grover pr_warn("ALUA LU Group already has a valid ID," 1499c66ac9dbSNicholas Bellinger " ignoring request\n"); 1500e3d6f909SAndy Grover return -EINVAL; 1501c66ac9dbSNicholas Bellinger } 1502c66ac9dbSNicholas Bellinger 1503e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1504e3d6f909SAndy Grover if (alua_lu_gps_count == 0x0000ffff) { 15056708bb27SAndy Grover pr_err("Maximum ALUA alua_lu_gps_count:" 1506c66ac9dbSNicholas Bellinger " 0x0000ffff reached\n"); 1507e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1508c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_lu_gp_cache, lu_gp); 1509e3d6f909SAndy Grover return -ENOSPC; 1510c66ac9dbSNicholas Bellinger } 1511c66ac9dbSNicholas Bellinger again: 1512c66ac9dbSNicholas Bellinger lu_gp_id_tmp = (lu_gp_id != 0) ? lu_gp_id : 1513e3d6f909SAndy Grover alua_lu_gps_counter++; 1514c66ac9dbSNicholas Bellinger 1515e3d6f909SAndy Grover list_for_each_entry(lu_gp_tmp, &lu_gps_list, lu_gp_node) { 1516c66ac9dbSNicholas Bellinger if (lu_gp_tmp->lu_gp_id == lu_gp_id_tmp) { 15176708bb27SAndy Grover if (!lu_gp_id) 1518c66ac9dbSNicholas Bellinger goto again; 1519c66ac9dbSNicholas Bellinger 15206708bb27SAndy Grover pr_warn("ALUA Logical Unit Group ID: %hu" 1521c66ac9dbSNicholas Bellinger " already exists, ignoring request\n", 1522c66ac9dbSNicholas Bellinger lu_gp_id); 1523e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1524e3d6f909SAndy Grover return -EINVAL; 1525c66ac9dbSNicholas Bellinger } 1526c66ac9dbSNicholas Bellinger } 1527c66ac9dbSNicholas Bellinger 1528c66ac9dbSNicholas Bellinger lu_gp->lu_gp_id = lu_gp_id_tmp; 1529c66ac9dbSNicholas Bellinger lu_gp->lu_gp_valid_id = 1; 1530e3d6f909SAndy Grover list_add_tail(&lu_gp->lu_gp_node, &lu_gps_list); 1531e3d6f909SAndy Grover alua_lu_gps_count++; 1532e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1533c66ac9dbSNicholas Bellinger 1534c66ac9dbSNicholas Bellinger return 0; 1535c66ac9dbSNicholas Bellinger } 1536c66ac9dbSNicholas Bellinger 1537c66ac9dbSNicholas Bellinger static struct t10_alua_lu_gp_member * 1538c66ac9dbSNicholas Bellinger core_alua_allocate_lu_gp_mem(struct se_device *dev) 1539c66ac9dbSNicholas Bellinger { 1540c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 1541c66ac9dbSNicholas Bellinger 1542c66ac9dbSNicholas Bellinger lu_gp_mem = kmem_cache_zalloc(t10_alua_lu_gp_mem_cache, GFP_KERNEL); 15436708bb27SAndy Grover if (!lu_gp_mem) { 15446708bb27SAndy Grover pr_err("Unable to allocate struct t10_alua_lu_gp_member\n"); 1545c66ac9dbSNicholas Bellinger return ERR_PTR(-ENOMEM); 1546c66ac9dbSNicholas Bellinger } 1547c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&lu_gp_mem->lu_gp_mem_list); 1548c66ac9dbSNicholas Bellinger spin_lock_init(&lu_gp_mem->lu_gp_mem_lock); 1549c66ac9dbSNicholas Bellinger atomic_set(&lu_gp_mem->lu_gp_mem_ref_cnt, 0); 1550c66ac9dbSNicholas Bellinger 1551c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_mem_dev = dev; 1552c66ac9dbSNicholas Bellinger dev->dev_alua_lu_gp_mem = lu_gp_mem; 1553c66ac9dbSNicholas Bellinger 1554c66ac9dbSNicholas Bellinger return lu_gp_mem; 1555c66ac9dbSNicholas Bellinger } 1556c66ac9dbSNicholas Bellinger 1557c66ac9dbSNicholas Bellinger void core_alua_free_lu_gp(struct t10_alua_lu_gp *lu_gp) 1558c66ac9dbSNicholas Bellinger { 1559c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, *lu_gp_mem_tmp; 1560c66ac9dbSNicholas Bellinger /* 1561c66ac9dbSNicholas Bellinger * Once we have reached this point, config_item_put() has 1562c66ac9dbSNicholas Bellinger * already been called from target_core_alua_drop_lu_gp(). 1563c66ac9dbSNicholas Bellinger * 1564c66ac9dbSNicholas Bellinger * Here, we remove the *lu_gp from the global list so that 1565c66ac9dbSNicholas Bellinger * no associations can be made while we are releasing 1566c66ac9dbSNicholas Bellinger * struct t10_alua_lu_gp. 1567c66ac9dbSNicholas Bellinger */ 1568e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1569e3d6f909SAndy Grover list_del(&lu_gp->lu_gp_node); 1570e3d6f909SAndy Grover alua_lu_gps_count--; 1571e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1572c66ac9dbSNicholas Bellinger /* 1573c66ac9dbSNicholas Bellinger * Allow struct t10_alua_lu_gp * referenced by core_alua_get_lu_gp_by_name() 1574c66ac9dbSNicholas Bellinger * in target_core_configfs.c:target_core_store_alua_lu_gp() to be 1575c66ac9dbSNicholas Bellinger * released with core_alua_put_lu_gp_from_name() 1576c66ac9dbSNicholas Bellinger */ 1577c66ac9dbSNicholas Bellinger while (atomic_read(&lu_gp->lu_gp_ref_cnt)) 1578c66ac9dbSNicholas Bellinger cpu_relax(); 1579c66ac9dbSNicholas Bellinger /* 1580c66ac9dbSNicholas Bellinger * Release reference to struct t10_alua_lu_gp * from all associated 1581c66ac9dbSNicholas Bellinger * struct se_device. 1582c66ac9dbSNicholas Bellinger */ 1583c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1584c66ac9dbSNicholas Bellinger list_for_each_entry_safe(lu_gp_mem, lu_gp_mem_tmp, 1585c66ac9dbSNicholas Bellinger &lu_gp->lu_gp_mem_list, lu_gp_mem_list) { 1586c66ac9dbSNicholas Bellinger if (lu_gp_mem->lu_gp_assoc) { 1587c66ac9dbSNicholas Bellinger list_del(&lu_gp_mem->lu_gp_mem_list); 1588c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members--; 1589c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 0; 1590c66ac9dbSNicholas Bellinger } 1591c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1592c66ac9dbSNicholas Bellinger /* 1593c66ac9dbSNicholas Bellinger * 159425985edcSLucas De Marchi * lu_gp_mem is associated with a single 1595c66ac9dbSNicholas Bellinger * struct se_device->dev_alua_lu_gp_mem, and is released when 1596c66ac9dbSNicholas Bellinger * struct se_device is released via core_alua_free_lu_gp_mem(). 1597c66ac9dbSNicholas Bellinger * 1598c66ac9dbSNicholas Bellinger * If the passed lu_gp does NOT match the default_lu_gp, assume 1599f1ae05d5SHannes Reinecke * we want to re-associate a given lu_gp_mem with default_lu_gp. 1600c66ac9dbSNicholas Bellinger */ 1601c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 1602e3d6f909SAndy Grover if (lu_gp != default_lu_gp) 1603c66ac9dbSNicholas Bellinger __core_alua_attach_lu_gp_mem(lu_gp_mem, 1604e3d6f909SAndy Grover default_lu_gp); 1605c66ac9dbSNicholas Bellinger else 1606c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = NULL; 1607c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 1608c66ac9dbSNicholas Bellinger 1609c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1610c66ac9dbSNicholas Bellinger } 1611c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1612c66ac9dbSNicholas Bellinger 1613c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_lu_gp_cache, lu_gp); 1614c66ac9dbSNicholas Bellinger } 1615c66ac9dbSNicholas Bellinger 1616c66ac9dbSNicholas Bellinger void core_alua_free_lu_gp_mem(struct se_device *dev) 1617c66ac9dbSNicholas Bellinger { 1618c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1619c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 1620c66ac9dbSNicholas Bellinger 1621c66ac9dbSNicholas Bellinger lu_gp_mem = dev->dev_alua_lu_gp_mem; 16226708bb27SAndy Grover if (!lu_gp_mem) 1623c66ac9dbSNicholas Bellinger return; 1624c66ac9dbSNicholas Bellinger 1625c66ac9dbSNicholas Bellinger while (atomic_read(&lu_gp_mem->lu_gp_mem_ref_cnt)) 1626c66ac9dbSNicholas Bellinger cpu_relax(); 1627c66ac9dbSNicholas Bellinger 1628c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 1629c66ac9dbSNicholas Bellinger lu_gp = lu_gp_mem->lu_gp; 16306708bb27SAndy Grover if (lu_gp) { 1631c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1632c66ac9dbSNicholas Bellinger if (lu_gp_mem->lu_gp_assoc) { 1633c66ac9dbSNicholas Bellinger list_del(&lu_gp_mem->lu_gp_mem_list); 1634c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members--; 1635c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 0; 1636c66ac9dbSNicholas Bellinger } 1637c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1638c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = NULL; 1639c66ac9dbSNicholas Bellinger } 1640c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 1641c66ac9dbSNicholas Bellinger 1642c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_lu_gp_mem_cache, lu_gp_mem); 1643c66ac9dbSNicholas Bellinger } 1644c66ac9dbSNicholas Bellinger 1645c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *core_alua_get_lu_gp_by_name(const char *name) 1646c66ac9dbSNicholas Bellinger { 1647c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp; 1648c66ac9dbSNicholas Bellinger struct config_item *ci; 1649c66ac9dbSNicholas Bellinger 1650e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1651e3d6f909SAndy Grover list_for_each_entry(lu_gp, &lu_gps_list, lu_gp_node) { 16526708bb27SAndy Grover if (!lu_gp->lu_gp_valid_id) 1653c66ac9dbSNicholas Bellinger continue; 1654c66ac9dbSNicholas Bellinger ci = &lu_gp->lu_gp_group.cg_item; 16556708bb27SAndy Grover if (!strcmp(config_item_name(ci), name)) { 1656c66ac9dbSNicholas Bellinger atomic_inc(&lu_gp->lu_gp_ref_cnt); 1657e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1658c66ac9dbSNicholas Bellinger return lu_gp; 1659c66ac9dbSNicholas Bellinger } 1660c66ac9dbSNicholas Bellinger } 1661e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1662c66ac9dbSNicholas Bellinger 1663c66ac9dbSNicholas Bellinger return NULL; 1664c66ac9dbSNicholas Bellinger } 1665c66ac9dbSNicholas Bellinger 1666c66ac9dbSNicholas Bellinger void core_alua_put_lu_gp_from_name(struct t10_alua_lu_gp *lu_gp) 1667c66ac9dbSNicholas Bellinger { 1668e3d6f909SAndy Grover spin_lock(&lu_gps_lock); 1669c66ac9dbSNicholas Bellinger atomic_dec(&lu_gp->lu_gp_ref_cnt); 1670e3d6f909SAndy Grover spin_unlock(&lu_gps_lock); 1671c66ac9dbSNicholas Bellinger } 1672c66ac9dbSNicholas Bellinger 1673c66ac9dbSNicholas Bellinger /* 1674c66ac9dbSNicholas Bellinger * Called with struct t10_alua_lu_gp_member->lu_gp_mem_lock 1675c66ac9dbSNicholas Bellinger */ 1676c66ac9dbSNicholas Bellinger void __core_alua_attach_lu_gp_mem( 1677c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, 1678c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp) 1679c66ac9dbSNicholas Bellinger { 1680c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1681c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = lu_gp; 1682c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 1; 1683c66ac9dbSNicholas Bellinger list_add_tail(&lu_gp_mem->lu_gp_mem_list, &lu_gp->lu_gp_mem_list); 1684c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members++; 1685c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1686c66ac9dbSNicholas Bellinger } 1687c66ac9dbSNicholas Bellinger 1688c66ac9dbSNicholas Bellinger /* 1689c66ac9dbSNicholas Bellinger * Called with struct t10_alua_lu_gp_member->lu_gp_mem_lock 1690c66ac9dbSNicholas Bellinger */ 1691c66ac9dbSNicholas Bellinger void __core_alua_drop_lu_gp_mem( 1692c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem, 1693c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp *lu_gp) 1694c66ac9dbSNicholas Bellinger { 1695c66ac9dbSNicholas Bellinger spin_lock(&lu_gp->lu_gp_lock); 1696c66ac9dbSNicholas Bellinger list_del(&lu_gp_mem->lu_gp_mem_list); 1697c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp = NULL; 1698c66ac9dbSNicholas Bellinger lu_gp_mem->lu_gp_assoc = 0; 1699c66ac9dbSNicholas Bellinger lu_gp->lu_gp_members--; 1700c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp->lu_gp_lock); 1701c66ac9dbSNicholas Bellinger } 1702c66ac9dbSNicholas Bellinger 17030fd97ccfSChristoph Hellwig struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev, 17040fd97ccfSChristoph Hellwig const char *name, int def_group) 1705c66ac9dbSNicholas Bellinger { 1706c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1707c66ac9dbSNicholas Bellinger 1708c66ac9dbSNicholas Bellinger tg_pt_gp = kmem_cache_zalloc(t10_alua_tg_pt_gp_cache, GFP_KERNEL); 17096708bb27SAndy Grover if (!tg_pt_gp) { 17106708bb27SAndy Grover pr_err("Unable to allocate struct t10_alua_tg_pt_gp\n"); 1711c66ac9dbSNicholas Bellinger return NULL; 1712c66ac9dbSNicholas Bellinger } 1713c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_list); 1714c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_mem_list); 1715c66ac9dbSNicholas Bellinger mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); 1716c66ac9dbSNicholas Bellinger spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); 1717c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); 17189c6e164cSHannes Reinecke INIT_DELAYED_WORK(&tg_pt_gp->tg_pt_gp_transition_work, 17199c6e164cSHannes Reinecke core_alua_do_transition_tg_pt_work); 17200fd97ccfSChristoph Hellwig tg_pt_gp->tg_pt_gp_dev = dev; 1721c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp->tg_pt_gp_alua_access_state, 172273f3bf51SHannes Reinecke ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED); 1723c66ac9dbSNicholas Bellinger /* 1724125d0119SHannes Reinecke * Enable both explicit and implicit ALUA support by default 1725c66ac9dbSNicholas Bellinger */ 1726c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = 1727125d0119SHannes Reinecke TPGS_EXPLICIT_ALUA | TPGS_IMPLICIT_ALUA; 1728c66ac9dbSNicholas Bellinger /* 1729c66ac9dbSNicholas Bellinger * Set the default Active/NonOptimized Delay in milliseconds 1730c66ac9dbSNicholas Bellinger */ 1731c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS; 1732c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS; 1733125d0119SHannes Reinecke tg_pt_gp->tg_pt_gp_implicit_trans_secs = ALUA_DEFAULT_IMPLICIT_TRANS_SECS; 1734c66ac9dbSNicholas Bellinger 1735c0dc941eSHannes Reinecke /* 1736c0dc941eSHannes Reinecke * Enable all supported states 1737c0dc941eSHannes Reinecke */ 1738c0dc941eSHannes Reinecke tg_pt_gp->tg_pt_gp_alua_supported_states = 1739c0dc941eSHannes Reinecke ALUA_T_SUP | ALUA_O_SUP | 1740c0dc941eSHannes Reinecke ALUA_U_SUP | ALUA_S_SUP | ALUA_AN_SUP | ALUA_AO_SUP; 1741c0dc941eSHannes Reinecke 1742c66ac9dbSNicholas Bellinger if (def_group) { 17430fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1744c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id = 17450fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_counter++; 1746c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_valid_id = 1; 17470fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_count++; 1748c66ac9dbSNicholas Bellinger list_add_tail(&tg_pt_gp->tg_pt_gp_list, 17490fd97ccfSChristoph Hellwig &dev->t10_alua.tg_pt_gps_list); 17500fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1751c66ac9dbSNicholas Bellinger } 1752c66ac9dbSNicholas Bellinger 1753c66ac9dbSNicholas Bellinger return tg_pt_gp; 1754c66ac9dbSNicholas Bellinger } 1755c66ac9dbSNicholas Bellinger 1756c66ac9dbSNicholas Bellinger int core_alua_set_tg_pt_gp_id( 1757c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 1758c66ac9dbSNicholas Bellinger u16 tg_pt_gp_id) 1759c66ac9dbSNicholas Bellinger { 17600fd97ccfSChristoph Hellwig struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; 1761c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp_tmp; 1762c66ac9dbSNicholas Bellinger u16 tg_pt_gp_id_tmp; 17630fd97ccfSChristoph Hellwig 1764c66ac9dbSNicholas Bellinger /* 1765c66ac9dbSNicholas Bellinger * The tg_pt_gp->tg_pt_gp_id may only be set once.. 1766c66ac9dbSNicholas Bellinger */ 1767c66ac9dbSNicholas Bellinger if (tg_pt_gp->tg_pt_gp_valid_id) { 17686708bb27SAndy Grover pr_warn("ALUA TG PT Group already has a valid ID," 1769c66ac9dbSNicholas Bellinger " ignoring request\n"); 1770e3d6f909SAndy Grover return -EINVAL; 1771c66ac9dbSNicholas Bellinger } 1772c66ac9dbSNicholas Bellinger 17730fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 17740fd97ccfSChristoph Hellwig if (dev->t10_alua.alua_tg_pt_gps_count == 0x0000ffff) { 17756708bb27SAndy Grover pr_err("Maximum ALUA alua_tg_pt_gps_count:" 1776c66ac9dbSNicholas Bellinger " 0x0000ffff reached\n"); 17770fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1778c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); 1779e3d6f909SAndy Grover return -ENOSPC; 1780c66ac9dbSNicholas Bellinger } 1781c66ac9dbSNicholas Bellinger again: 1782c66ac9dbSNicholas Bellinger tg_pt_gp_id_tmp = (tg_pt_gp_id != 0) ? tg_pt_gp_id : 17830fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_counter++; 1784c66ac9dbSNicholas Bellinger 17850fd97ccfSChristoph Hellwig list_for_each_entry(tg_pt_gp_tmp, &dev->t10_alua.tg_pt_gps_list, 1786c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 1787c66ac9dbSNicholas Bellinger if (tg_pt_gp_tmp->tg_pt_gp_id == tg_pt_gp_id_tmp) { 17886708bb27SAndy Grover if (!tg_pt_gp_id) 1789c66ac9dbSNicholas Bellinger goto again; 1790c66ac9dbSNicholas Bellinger 17916708bb27SAndy Grover pr_err("ALUA Target Port Group ID: %hu already" 1792c66ac9dbSNicholas Bellinger " exists, ignoring request\n", tg_pt_gp_id); 17930fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1794e3d6f909SAndy Grover return -EINVAL; 1795c66ac9dbSNicholas Bellinger } 1796c66ac9dbSNicholas Bellinger } 1797c66ac9dbSNicholas Bellinger 1798c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id = tg_pt_gp_id_tmp; 1799c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_valid_id = 1; 1800c66ac9dbSNicholas Bellinger list_add_tail(&tg_pt_gp->tg_pt_gp_list, 18010fd97ccfSChristoph Hellwig &dev->t10_alua.tg_pt_gps_list); 18020fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_count++; 18030fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1804c66ac9dbSNicholas Bellinger 1805c66ac9dbSNicholas Bellinger return 0; 1806c66ac9dbSNicholas Bellinger } 1807c66ac9dbSNicholas Bellinger 1808c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( 1809c66ac9dbSNicholas Bellinger struct se_port *port) 1810c66ac9dbSNicholas Bellinger { 1811c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1812c66ac9dbSNicholas Bellinger 1813c66ac9dbSNicholas Bellinger tg_pt_gp_mem = kmem_cache_zalloc(t10_alua_tg_pt_gp_mem_cache, 1814c66ac9dbSNicholas Bellinger GFP_KERNEL); 18156708bb27SAndy Grover if (!tg_pt_gp_mem) { 18166708bb27SAndy Grover pr_err("Unable to allocate struct t10_alua_tg_pt_gp_member\n"); 1817c66ac9dbSNicholas Bellinger return ERR_PTR(-ENOMEM); 1818c66ac9dbSNicholas Bellinger } 1819c66ac9dbSNicholas Bellinger INIT_LIST_HEAD(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1820c66ac9dbSNicholas Bellinger spin_lock_init(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1821c66ac9dbSNicholas Bellinger atomic_set(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt, 0); 1822c66ac9dbSNicholas Bellinger 1823c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt = port; 1824c66ac9dbSNicholas Bellinger port->sep_alua_tg_pt_gp_mem = tg_pt_gp_mem; 1825c66ac9dbSNicholas Bellinger 1826c66ac9dbSNicholas Bellinger return tg_pt_gp_mem; 1827c66ac9dbSNicholas Bellinger } 1828c66ac9dbSNicholas Bellinger 1829c66ac9dbSNicholas Bellinger void core_alua_free_tg_pt_gp( 1830c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1831c66ac9dbSNicholas Bellinger { 18320fd97ccfSChristoph Hellwig struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; 1833c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *tg_pt_gp_mem_tmp; 18340fd97ccfSChristoph Hellwig 1835c66ac9dbSNicholas Bellinger /* 1836c66ac9dbSNicholas Bellinger * Once we have reached this point, config_item_put() has already 1837c66ac9dbSNicholas Bellinger * been called from target_core_alua_drop_tg_pt_gp(). 1838c66ac9dbSNicholas Bellinger * 1839c66ac9dbSNicholas Bellinger * Here we remove *tg_pt_gp from the global list so that 1840f1ae05d5SHannes Reinecke * no associations *OR* explicit ALUA via SET_TARGET_PORT_GROUPS 1841c66ac9dbSNicholas Bellinger * can be made while we are releasing struct t10_alua_tg_pt_gp. 1842c66ac9dbSNicholas Bellinger */ 18430fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1844c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp->tg_pt_gp_list); 18450fd97ccfSChristoph Hellwig dev->t10_alua.alua_tg_pt_gps_counter--; 18460fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 18470fd97ccfSChristoph Hellwig 18489c6e164cSHannes Reinecke flush_delayed_work(&tg_pt_gp->tg_pt_gp_transition_work); 18499c6e164cSHannes Reinecke 1850c66ac9dbSNicholas Bellinger /* 1851c66ac9dbSNicholas Bellinger * Allow a struct t10_alua_tg_pt_gp_member * referenced by 1852c66ac9dbSNicholas Bellinger * core_alua_get_tg_pt_gp_by_name() in 1853c66ac9dbSNicholas Bellinger * target_core_configfs.c:target_core_store_alua_tg_pt_gp() 1854c66ac9dbSNicholas Bellinger * to be released with core_alua_put_tg_pt_gp_from_name(). 1855c66ac9dbSNicholas Bellinger */ 1856c66ac9dbSNicholas Bellinger while (atomic_read(&tg_pt_gp->tg_pt_gp_ref_cnt)) 1857c66ac9dbSNicholas Bellinger cpu_relax(); 18580fd97ccfSChristoph Hellwig 1859c66ac9dbSNicholas Bellinger /* 1860c66ac9dbSNicholas Bellinger * Release reference to struct t10_alua_tg_pt_gp from all associated 1861c66ac9dbSNicholas Bellinger * struct se_port. 1862c66ac9dbSNicholas Bellinger */ 1863c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1864c66ac9dbSNicholas Bellinger list_for_each_entry_safe(tg_pt_gp_mem, tg_pt_gp_mem_tmp, 1865c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_mem_list, tg_pt_gp_mem_list) { 1866c66ac9dbSNicholas Bellinger if (tg_pt_gp_mem->tg_pt_gp_assoc) { 1867c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1868c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members--; 1869c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 0; 1870c66ac9dbSNicholas Bellinger } 1871c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1872c66ac9dbSNicholas Bellinger /* 187325985edcSLucas De Marchi * tg_pt_gp_mem is associated with a single 1874c66ac9dbSNicholas Bellinger * se_port->sep_alua_tg_pt_gp_mem, and is released via 1875c66ac9dbSNicholas Bellinger * core_alua_free_tg_pt_gp_mem(). 1876c66ac9dbSNicholas Bellinger * 1877c66ac9dbSNicholas Bellinger * If the passed tg_pt_gp does NOT match the default_tg_pt_gp, 1878f1ae05d5SHannes Reinecke * assume we want to re-associate a given tg_pt_gp_mem with 1879c66ac9dbSNicholas Bellinger * default_tg_pt_gp. 1880c66ac9dbSNicholas Bellinger */ 1881c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 18820fd97ccfSChristoph Hellwig if (tg_pt_gp != dev->t10_alua.default_tg_pt_gp) { 1883c66ac9dbSNicholas Bellinger __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, 18840fd97ccfSChristoph Hellwig dev->t10_alua.default_tg_pt_gp); 1885c66ac9dbSNicholas Bellinger } else 1886c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = NULL; 1887c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1888c66ac9dbSNicholas Bellinger 1889c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1890c66ac9dbSNicholas Bellinger } 1891c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1892c66ac9dbSNicholas Bellinger 1893c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); 1894c66ac9dbSNicholas Bellinger } 1895c66ac9dbSNicholas Bellinger 1896c66ac9dbSNicholas Bellinger void core_alua_free_tg_pt_gp_mem(struct se_port *port) 1897c66ac9dbSNicholas Bellinger { 1898c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1899c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1900c66ac9dbSNicholas Bellinger 1901c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 19026708bb27SAndy Grover if (!tg_pt_gp_mem) 1903c66ac9dbSNicholas Bellinger return; 1904c66ac9dbSNicholas Bellinger 1905c66ac9dbSNicholas Bellinger while (atomic_read(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt)) 1906c66ac9dbSNicholas Bellinger cpu_relax(); 1907c66ac9dbSNicholas Bellinger 1908c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1909c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 19106708bb27SAndy Grover if (tg_pt_gp) { 1911c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1912c66ac9dbSNicholas Bellinger if (tg_pt_gp_mem->tg_pt_gp_assoc) { 1913c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1914c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members--; 1915c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 0; 1916c66ac9dbSNicholas Bellinger } 1917c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1918c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = NULL; 1919c66ac9dbSNicholas Bellinger } 1920c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 1921c66ac9dbSNicholas Bellinger 1922c66ac9dbSNicholas Bellinger kmem_cache_free(t10_alua_tg_pt_gp_mem_cache, tg_pt_gp_mem); 1923c66ac9dbSNicholas Bellinger } 1924c66ac9dbSNicholas Bellinger 1925c66ac9dbSNicholas Bellinger static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( 19260fd97ccfSChristoph Hellwig struct se_device *dev, const char *name) 1927c66ac9dbSNicholas Bellinger { 1928c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1929c66ac9dbSNicholas Bellinger struct config_item *ci; 1930c66ac9dbSNicholas Bellinger 19310fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 19320fd97ccfSChristoph Hellwig list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, 1933c66ac9dbSNicholas Bellinger tg_pt_gp_list) { 19346708bb27SAndy Grover if (!tg_pt_gp->tg_pt_gp_valid_id) 1935c66ac9dbSNicholas Bellinger continue; 1936c66ac9dbSNicholas Bellinger ci = &tg_pt_gp->tg_pt_gp_group.cg_item; 19376708bb27SAndy Grover if (!strcmp(config_item_name(ci), name)) { 1938c66ac9dbSNicholas Bellinger atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt); 19390fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1940c66ac9dbSNicholas Bellinger return tg_pt_gp; 1941c66ac9dbSNicholas Bellinger } 1942c66ac9dbSNicholas Bellinger } 19430fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1944c66ac9dbSNicholas Bellinger 1945c66ac9dbSNicholas Bellinger return NULL; 1946c66ac9dbSNicholas Bellinger } 1947c66ac9dbSNicholas Bellinger 1948c66ac9dbSNicholas Bellinger static void core_alua_put_tg_pt_gp_from_name( 1949c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1950c66ac9dbSNicholas Bellinger { 19510fd97ccfSChristoph Hellwig struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; 1952c66ac9dbSNicholas Bellinger 19530fd97ccfSChristoph Hellwig spin_lock(&dev->t10_alua.tg_pt_gps_lock); 1954c66ac9dbSNicholas Bellinger atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt); 19550fd97ccfSChristoph Hellwig spin_unlock(&dev->t10_alua.tg_pt_gps_lock); 1956c66ac9dbSNicholas Bellinger } 1957c66ac9dbSNicholas Bellinger 1958c66ac9dbSNicholas Bellinger /* 1959c66ac9dbSNicholas Bellinger * Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held 1960c66ac9dbSNicholas Bellinger */ 1961c66ac9dbSNicholas Bellinger void __core_alua_attach_tg_pt_gp_mem( 1962c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 1963c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1964c66ac9dbSNicholas Bellinger { 1965c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1966c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = tg_pt_gp; 1967c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 1; 1968c66ac9dbSNicholas Bellinger list_add_tail(&tg_pt_gp_mem->tg_pt_gp_mem_list, 1969c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_mem_list); 1970c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members++; 1971c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1972c66ac9dbSNicholas Bellinger } 1973c66ac9dbSNicholas Bellinger 1974c66ac9dbSNicholas Bellinger /* 1975c66ac9dbSNicholas Bellinger * Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held 1976c66ac9dbSNicholas Bellinger */ 1977c66ac9dbSNicholas Bellinger static void __core_alua_drop_tg_pt_gp_mem( 1978c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, 1979c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp) 1980c66ac9dbSNicholas Bellinger { 1981c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp->tg_pt_gp_lock); 1982c66ac9dbSNicholas Bellinger list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); 1983c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp = NULL; 1984c66ac9dbSNicholas Bellinger tg_pt_gp_mem->tg_pt_gp_assoc = 0; 1985c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_members--; 1986c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp->tg_pt_gp_lock); 1987c66ac9dbSNicholas Bellinger } 1988c66ac9dbSNicholas Bellinger 1989c66ac9dbSNicholas Bellinger ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page) 1990c66ac9dbSNicholas Bellinger { 1991c66ac9dbSNicholas Bellinger struct config_item *tg_pt_ci; 1992c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp; 1993c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 1994c66ac9dbSNicholas Bellinger ssize_t len = 0; 1995c66ac9dbSNicholas Bellinger 1996c66ac9dbSNicholas Bellinger tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 19976708bb27SAndy Grover if (!tg_pt_gp_mem) 1998c66ac9dbSNicholas Bellinger return len; 1999c66ac9dbSNicholas Bellinger 2000c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 2001c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 20026708bb27SAndy Grover if (tg_pt_gp) { 2003c66ac9dbSNicholas Bellinger tg_pt_ci = &tg_pt_gp->tg_pt_gp_group.cg_item; 2004c66ac9dbSNicholas Bellinger len += sprintf(page, "TG Port Alias: %s\nTG Port Group ID:" 2005c66ac9dbSNicholas Bellinger " %hu\nTG Port Primary Access State: %s\nTG Port " 2006c66ac9dbSNicholas Bellinger "Primary Access Status: %s\nTG Port Secondary Access" 2007c66ac9dbSNicholas Bellinger " State: %s\nTG Port Secondary Access Status: %s\n", 2008c66ac9dbSNicholas Bellinger config_item_name(tg_pt_ci), tg_pt_gp->tg_pt_gp_id, 2009c66ac9dbSNicholas Bellinger core_alua_dump_state(atomic_read( 2010c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_alua_access_state)), 2011c66ac9dbSNicholas Bellinger core_alua_dump_status( 2012c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_status), 2013c66ac9dbSNicholas Bellinger (atomic_read(&port->sep_tg_pt_secondary_offline)) ? 2014c66ac9dbSNicholas Bellinger "Offline" : "None", 2015c66ac9dbSNicholas Bellinger core_alua_dump_status(port->sep_tg_pt_secondary_stat)); 2016c66ac9dbSNicholas Bellinger } 2017c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 2018c66ac9dbSNicholas Bellinger 2019c66ac9dbSNicholas Bellinger return len; 2020c66ac9dbSNicholas Bellinger } 2021c66ac9dbSNicholas Bellinger 2022c66ac9dbSNicholas Bellinger ssize_t core_alua_store_tg_pt_gp_info( 2023c66ac9dbSNicholas Bellinger struct se_port *port, 2024c66ac9dbSNicholas Bellinger const char *page, 2025c66ac9dbSNicholas Bellinger size_t count) 2026c66ac9dbSNicholas Bellinger { 2027c66ac9dbSNicholas Bellinger struct se_portal_group *tpg; 2028c66ac9dbSNicholas Bellinger struct se_lun *lun; 20290fd97ccfSChristoph Hellwig struct se_device *dev = port->sep_lun->lun_se_dev; 2030c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL; 2031c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 2032c66ac9dbSNicholas Bellinger unsigned char buf[TG_PT_GROUP_NAME_BUF]; 2033c66ac9dbSNicholas Bellinger int move = 0; 2034c66ac9dbSNicholas Bellinger 2035c66ac9dbSNicholas Bellinger tpg = port->sep_tpg; 2036c66ac9dbSNicholas Bellinger lun = port->sep_lun; 2037c66ac9dbSNicholas Bellinger 2038c87fbd56SChristoph Hellwig tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; 2039c87fbd56SChristoph Hellwig if (!tg_pt_gp_mem) 2040c87fbd56SChristoph Hellwig return 0; 2041c66ac9dbSNicholas Bellinger 2042c66ac9dbSNicholas Bellinger if (count > TG_PT_GROUP_NAME_BUF) { 20436708bb27SAndy Grover pr_err("ALUA Target Port Group alias too large!\n"); 2044c66ac9dbSNicholas Bellinger return -EINVAL; 2045c66ac9dbSNicholas Bellinger } 2046c66ac9dbSNicholas Bellinger memset(buf, 0, TG_PT_GROUP_NAME_BUF); 2047c66ac9dbSNicholas Bellinger memcpy(buf, page, count); 2048c66ac9dbSNicholas Bellinger /* 2049c66ac9dbSNicholas Bellinger * Any ALUA target port group alias besides "NULL" means we will be 2050c66ac9dbSNicholas Bellinger * making a new group association. 2051c66ac9dbSNicholas Bellinger */ 2052c66ac9dbSNicholas Bellinger if (strcmp(strstrip(buf), "NULL")) { 2053c66ac9dbSNicholas Bellinger /* 2054c66ac9dbSNicholas Bellinger * core_alua_get_tg_pt_gp_by_name() will increment reference to 2055c66ac9dbSNicholas Bellinger * struct t10_alua_tg_pt_gp. This reference is released with 2056c66ac9dbSNicholas Bellinger * core_alua_put_tg_pt_gp_from_name() below. 2057c66ac9dbSNicholas Bellinger */ 20580fd97ccfSChristoph Hellwig tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(dev, 2059c66ac9dbSNicholas Bellinger strstrip(buf)); 20606708bb27SAndy Grover if (!tg_pt_gp_new) 2061c66ac9dbSNicholas Bellinger return -ENODEV; 2062c66ac9dbSNicholas Bellinger } 2063c66ac9dbSNicholas Bellinger 2064c66ac9dbSNicholas Bellinger spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 2065c66ac9dbSNicholas Bellinger tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; 20666708bb27SAndy Grover if (tg_pt_gp) { 2067c66ac9dbSNicholas Bellinger /* 2068c66ac9dbSNicholas Bellinger * Clearing an existing tg_pt_gp association, and replacing 2069c66ac9dbSNicholas Bellinger * with the default_tg_pt_gp. 2070c66ac9dbSNicholas Bellinger */ 20716708bb27SAndy Grover if (!tg_pt_gp_new) { 20726708bb27SAndy Grover pr_debug("Target_Core_ConfigFS: Moving" 2073c66ac9dbSNicholas Bellinger " %s/tpgt_%hu/%s from ALUA Target Port Group:" 2074c66ac9dbSNicholas Bellinger " alua/%s, ID: %hu back to" 2075c66ac9dbSNicholas Bellinger " default_tg_pt_gp\n", 2076e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_wwn(tpg), 2077e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), 2078c66ac9dbSNicholas Bellinger config_item_name(&lun->lun_group.cg_item), 2079c66ac9dbSNicholas Bellinger config_item_name( 2080c66ac9dbSNicholas Bellinger &tg_pt_gp->tg_pt_gp_group.cg_item), 2081c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_id); 2082c66ac9dbSNicholas Bellinger 2083c66ac9dbSNicholas Bellinger __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); 2084c66ac9dbSNicholas Bellinger __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, 20850fd97ccfSChristoph Hellwig dev->t10_alua.default_tg_pt_gp); 2086c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 2087c66ac9dbSNicholas Bellinger 2088c66ac9dbSNicholas Bellinger return count; 2089c66ac9dbSNicholas Bellinger } 2090c66ac9dbSNicholas Bellinger /* 2091c66ac9dbSNicholas Bellinger * Removing existing association of tg_pt_gp_mem with tg_pt_gp 2092c66ac9dbSNicholas Bellinger */ 2093c66ac9dbSNicholas Bellinger __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); 2094c66ac9dbSNicholas Bellinger move = 1; 2095c66ac9dbSNicholas Bellinger } 2096c66ac9dbSNicholas Bellinger /* 2097c66ac9dbSNicholas Bellinger * Associate tg_pt_gp_mem with tg_pt_gp_new. 2098c66ac9dbSNicholas Bellinger */ 2099c66ac9dbSNicholas Bellinger __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp_new); 2100c66ac9dbSNicholas Bellinger spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); 21016708bb27SAndy Grover pr_debug("Target_Core_ConfigFS: %s %s/tpgt_%hu/%s to ALUA" 2102c66ac9dbSNicholas Bellinger " Target Port Group: alua/%s, ID: %hu\n", (move) ? 2103e3d6f909SAndy Grover "Moving" : "Adding", tpg->se_tpg_tfo->tpg_get_wwn(tpg), 2104e3d6f909SAndy Grover tpg->se_tpg_tfo->tpg_get_tag(tpg), 2105c66ac9dbSNicholas Bellinger config_item_name(&lun->lun_group.cg_item), 2106c66ac9dbSNicholas Bellinger config_item_name(&tg_pt_gp_new->tg_pt_gp_group.cg_item), 2107c66ac9dbSNicholas Bellinger tg_pt_gp_new->tg_pt_gp_id); 2108c66ac9dbSNicholas Bellinger 2109c66ac9dbSNicholas Bellinger core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new); 2110c66ac9dbSNicholas Bellinger return count; 2111c66ac9dbSNicholas Bellinger } 2112c66ac9dbSNicholas Bellinger 2113c66ac9dbSNicholas Bellinger ssize_t core_alua_show_access_type( 2114c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2115c66ac9dbSNicholas Bellinger char *page) 2116c66ac9dbSNicholas Bellinger { 2117125d0119SHannes Reinecke if ((tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA) && 2118125d0119SHannes Reinecke (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA)) 2119125d0119SHannes Reinecke return sprintf(page, "Implicit and Explicit\n"); 2120125d0119SHannes Reinecke else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_IMPLICIT_ALUA) 2121125d0119SHannes Reinecke return sprintf(page, "Implicit\n"); 2122125d0119SHannes Reinecke else if (tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA) 2123125d0119SHannes Reinecke return sprintf(page, "Explicit\n"); 2124c66ac9dbSNicholas Bellinger else 2125c66ac9dbSNicholas Bellinger return sprintf(page, "None\n"); 2126c66ac9dbSNicholas Bellinger } 2127c66ac9dbSNicholas Bellinger 2128c66ac9dbSNicholas Bellinger ssize_t core_alua_store_access_type( 2129c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2130c66ac9dbSNicholas Bellinger const char *page, 2131c66ac9dbSNicholas Bellinger size_t count) 2132c66ac9dbSNicholas Bellinger { 2133c66ac9dbSNicholas Bellinger unsigned long tmp; 2134c66ac9dbSNicholas Bellinger int ret; 2135c66ac9dbSNicholas Bellinger 213657103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 2137c66ac9dbSNicholas Bellinger if (ret < 0) { 21386708bb27SAndy Grover pr_err("Unable to extract alua_access_type\n"); 213957103d7fSJingoo Han return ret; 2140c66ac9dbSNicholas Bellinger } 2141c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1) && (tmp != 2) && (tmp != 3)) { 21426708bb27SAndy Grover pr_err("Illegal value for alua_access_type:" 2143c66ac9dbSNicholas Bellinger " %lu\n", tmp); 2144c66ac9dbSNicholas Bellinger return -EINVAL; 2145c66ac9dbSNicholas Bellinger } 2146c66ac9dbSNicholas Bellinger if (tmp == 3) 2147c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = 2148125d0119SHannes Reinecke TPGS_IMPLICIT_ALUA | TPGS_EXPLICIT_ALUA; 2149c66ac9dbSNicholas Bellinger else if (tmp == 2) 2150125d0119SHannes Reinecke tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_EXPLICIT_ALUA; 2151c66ac9dbSNicholas Bellinger else if (tmp == 1) 2152125d0119SHannes Reinecke tg_pt_gp->tg_pt_gp_alua_access_type = TPGS_IMPLICIT_ALUA; 2153c66ac9dbSNicholas Bellinger else 2154c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_alua_access_type = 0; 2155c66ac9dbSNicholas Bellinger 2156c66ac9dbSNicholas Bellinger return count; 2157c66ac9dbSNicholas Bellinger } 2158c66ac9dbSNicholas Bellinger 2159c66ac9dbSNicholas Bellinger ssize_t core_alua_show_nonop_delay_msecs( 2160c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2161c66ac9dbSNicholas Bellinger char *page) 2162c66ac9dbSNicholas Bellinger { 2163c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_nonop_delay_msecs); 2164c66ac9dbSNicholas Bellinger } 2165c66ac9dbSNicholas Bellinger 2166c66ac9dbSNicholas Bellinger ssize_t core_alua_store_nonop_delay_msecs( 2167c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2168c66ac9dbSNicholas Bellinger const char *page, 2169c66ac9dbSNicholas Bellinger size_t count) 2170c66ac9dbSNicholas Bellinger { 2171c66ac9dbSNicholas Bellinger unsigned long tmp; 2172c66ac9dbSNicholas Bellinger int ret; 2173c66ac9dbSNicholas Bellinger 217457103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 2175c66ac9dbSNicholas Bellinger if (ret < 0) { 21766708bb27SAndy Grover pr_err("Unable to extract nonop_delay_msecs\n"); 217757103d7fSJingoo Han return ret; 2178c66ac9dbSNicholas Bellinger } 2179c66ac9dbSNicholas Bellinger if (tmp > ALUA_MAX_NONOP_DELAY_MSECS) { 21806708bb27SAndy Grover pr_err("Passed nonop_delay_msecs: %lu, exceeds" 2181c66ac9dbSNicholas Bellinger " ALUA_MAX_NONOP_DELAY_MSECS: %d\n", tmp, 2182c66ac9dbSNicholas Bellinger ALUA_MAX_NONOP_DELAY_MSECS); 2183c66ac9dbSNicholas Bellinger return -EINVAL; 2184c66ac9dbSNicholas Bellinger } 2185c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_nonop_delay_msecs = (int)tmp; 2186c66ac9dbSNicholas Bellinger 2187c66ac9dbSNicholas Bellinger return count; 2188c66ac9dbSNicholas Bellinger } 2189c66ac9dbSNicholas Bellinger 2190c66ac9dbSNicholas Bellinger ssize_t core_alua_show_trans_delay_msecs( 2191c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2192c66ac9dbSNicholas Bellinger char *page) 2193c66ac9dbSNicholas Bellinger { 2194c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_trans_delay_msecs); 2195c66ac9dbSNicholas Bellinger } 2196c66ac9dbSNicholas Bellinger 2197c66ac9dbSNicholas Bellinger ssize_t core_alua_store_trans_delay_msecs( 2198c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2199c66ac9dbSNicholas Bellinger const char *page, 2200c66ac9dbSNicholas Bellinger size_t count) 2201c66ac9dbSNicholas Bellinger { 2202c66ac9dbSNicholas Bellinger unsigned long tmp; 2203c66ac9dbSNicholas Bellinger int ret; 2204c66ac9dbSNicholas Bellinger 220557103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 2206c66ac9dbSNicholas Bellinger if (ret < 0) { 22076708bb27SAndy Grover pr_err("Unable to extract trans_delay_msecs\n"); 220857103d7fSJingoo Han return ret; 2209c66ac9dbSNicholas Bellinger } 2210c66ac9dbSNicholas Bellinger if (tmp > ALUA_MAX_TRANS_DELAY_MSECS) { 22116708bb27SAndy Grover pr_err("Passed trans_delay_msecs: %lu, exceeds" 2212c66ac9dbSNicholas Bellinger " ALUA_MAX_TRANS_DELAY_MSECS: %d\n", tmp, 2213c66ac9dbSNicholas Bellinger ALUA_MAX_TRANS_DELAY_MSECS); 2214c66ac9dbSNicholas Bellinger return -EINVAL; 2215c66ac9dbSNicholas Bellinger } 2216c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_trans_delay_msecs = (int)tmp; 2217c66ac9dbSNicholas Bellinger 2218c66ac9dbSNicholas Bellinger return count; 2219c66ac9dbSNicholas Bellinger } 2220c66ac9dbSNicholas Bellinger 2221125d0119SHannes Reinecke ssize_t core_alua_show_implicit_trans_secs( 22225b9a4d72SNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 22235b9a4d72SNicholas Bellinger char *page) 22245b9a4d72SNicholas Bellinger { 2225125d0119SHannes Reinecke return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implicit_trans_secs); 22265b9a4d72SNicholas Bellinger } 22275b9a4d72SNicholas Bellinger 2228125d0119SHannes Reinecke ssize_t core_alua_store_implicit_trans_secs( 22295b9a4d72SNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 22305b9a4d72SNicholas Bellinger const char *page, 22315b9a4d72SNicholas Bellinger size_t count) 22325b9a4d72SNicholas Bellinger { 22335b9a4d72SNicholas Bellinger unsigned long tmp; 22345b9a4d72SNicholas Bellinger int ret; 22355b9a4d72SNicholas Bellinger 223657103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 22375b9a4d72SNicholas Bellinger if (ret < 0) { 2238125d0119SHannes Reinecke pr_err("Unable to extract implicit_trans_secs\n"); 223957103d7fSJingoo Han return ret; 22405b9a4d72SNicholas Bellinger } 2241125d0119SHannes Reinecke if (tmp > ALUA_MAX_IMPLICIT_TRANS_SECS) { 2242125d0119SHannes Reinecke pr_err("Passed implicit_trans_secs: %lu, exceeds" 2243125d0119SHannes Reinecke " ALUA_MAX_IMPLICIT_TRANS_SECS: %d\n", tmp, 2244125d0119SHannes Reinecke ALUA_MAX_IMPLICIT_TRANS_SECS); 22455b9a4d72SNicholas Bellinger return -EINVAL; 22465b9a4d72SNicholas Bellinger } 2247125d0119SHannes Reinecke tg_pt_gp->tg_pt_gp_implicit_trans_secs = (int)tmp; 22485b9a4d72SNicholas Bellinger 22495b9a4d72SNicholas Bellinger return count; 22505b9a4d72SNicholas Bellinger } 22515b9a4d72SNicholas Bellinger 2252c66ac9dbSNicholas Bellinger ssize_t core_alua_show_preferred_bit( 2253c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2254c66ac9dbSNicholas Bellinger char *page) 2255c66ac9dbSNicholas Bellinger { 2256c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_pref); 2257c66ac9dbSNicholas Bellinger } 2258c66ac9dbSNicholas Bellinger 2259c66ac9dbSNicholas Bellinger ssize_t core_alua_store_preferred_bit( 2260c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp *tg_pt_gp, 2261c66ac9dbSNicholas Bellinger const char *page, 2262c66ac9dbSNicholas Bellinger size_t count) 2263c66ac9dbSNicholas Bellinger { 2264c66ac9dbSNicholas Bellinger unsigned long tmp; 2265c66ac9dbSNicholas Bellinger int ret; 2266c66ac9dbSNicholas Bellinger 226757103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 2268c66ac9dbSNicholas Bellinger if (ret < 0) { 22696708bb27SAndy Grover pr_err("Unable to extract preferred ALUA value\n"); 227057103d7fSJingoo Han return ret; 2271c66ac9dbSNicholas Bellinger } 2272c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 22736708bb27SAndy Grover pr_err("Illegal value for preferred ALUA: %lu\n", tmp); 2274c66ac9dbSNicholas Bellinger return -EINVAL; 2275c66ac9dbSNicholas Bellinger } 2276c66ac9dbSNicholas Bellinger tg_pt_gp->tg_pt_gp_pref = (int)tmp; 2277c66ac9dbSNicholas Bellinger 2278c66ac9dbSNicholas Bellinger return count; 2279c66ac9dbSNicholas Bellinger } 2280c66ac9dbSNicholas Bellinger 2281c66ac9dbSNicholas Bellinger ssize_t core_alua_show_offline_bit(struct se_lun *lun, char *page) 2282c66ac9dbSNicholas Bellinger { 22836708bb27SAndy Grover if (!lun->lun_sep) 2284c66ac9dbSNicholas Bellinger return -ENODEV; 2285c66ac9dbSNicholas Bellinger 2286c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", 2287c66ac9dbSNicholas Bellinger atomic_read(&lun->lun_sep->sep_tg_pt_secondary_offline)); 2288c66ac9dbSNicholas Bellinger } 2289c66ac9dbSNicholas Bellinger 2290c66ac9dbSNicholas Bellinger ssize_t core_alua_store_offline_bit( 2291c66ac9dbSNicholas Bellinger struct se_lun *lun, 2292c66ac9dbSNicholas Bellinger const char *page, 2293c66ac9dbSNicholas Bellinger size_t count) 2294c66ac9dbSNicholas Bellinger { 2295c66ac9dbSNicholas Bellinger struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; 2296c66ac9dbSNicholas Bellinger unsigned long tmp; 2297c66ac9dbSNicholas Bellinger int ret; 2298c66ac9dbSNicholas Bellinger 22996708bb27SAndy Grover if (!lun->lun_sep) 2300c66ac9dbSNicholas Bellinger return -ENODEV; 2301c66ac9dbSNicholas Bellinger 230257103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 2303c66ac9dbSNicholas Bellinger if (ret < 0) { 23046708bb27SAndy Grover pr_err("Unable to extract alua_tg_pt_offline value\n"); 230557103d7fSJingoo Han return ret; 2306c66ac9dbSNicholas Bellinger } 2307c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 23086708bb27SAndy Grover pr_err("Illegal value for alua_tg_pt_offline: %lu\n", 2309c66ac9dbSNicholas Bellinger tmp); 2310c66ac9dbSNicholas Bellinger return -EINVAL; 2311c66ac9dbSNicholas Bellinger } 2312c66ac9dbSNicholas Bellinger tg_pt_gp_mem = lun->lun_sep->sep_alua_tg_pt_gp_mem; 23136708bb27SAndy Grover if (!tg_pt_gp_mem) { 23146708bb27SAndy Grover pr_err("Unable to locate *tg_pt_gp_mem\n"); 2315c66ac9dbSNicholas Bellinger return -EINVAL; 2316c66ac9dbSNicholas Bellinger } 2317c66ac9dbSNicholas Bellinger 2318c66ac9dbSNicholas Bellinger ret = core_alua_set_tg_pt_secondary_state(tg_pt_gp_mem, 2319c66ac9dbSNicholas Bellinger lun->lun_sep, 0, (int)tmp); 2320c66ac9dbSNicholas Bellinger if (ret < 0) 2321c66ac9dbSNicholas Bellinger return -EINVAL; 2322c66ac9dbSNicholas Bellinger 2323c66ac9dbSNicholas Bellinger return count; 2324c66ac9dbSNicholas Bellinger } 2325c66ac9dbSNicholas Bellinger 2326c66ac9dbSNicholas Bellinger ssize_t core_alua_show_secondary_status( 2327c66ac9dbSNicholas Bellinger struct se_lun *lun, 2328c66ac9dbSNicholas Bellinger char *page) 2329c66ac9dbSNicholas Bellinger { 2330c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", lun->lun_sep->sep_tg_pt_secondary_stat); 2331c66ac9dbSNicholas Bellinger } 2332c66ac9dbSNicholas Bellinger 2333c66ac9dbSNicholas Bellinger ssize_t core_alua_store_secondary_status( 2334c66ac9dbSNicholas Bellinger struct se_lun *lun, 2335c66ac9dbSNicholas Bellinger const char *page, 2336c66ac9dbSNicholas Bellinger size_t count) 2337c66ac9dbSNicholas Bellinger { 2338c66ac9dbSNicholas Bellinger unsigned long tmp; 2339c66ac9dbSNicholas Bellinger int ret; 2340c66ac9dbSNicholas Bellinger 234157103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 2342c66ac9dbSNicholas Bellinger if (ret < 0) { 23436708bb27SAndy Grover pr_err("Unable to extract alua_tg_pt_status\n"); 234457103d7fSJingoo Han return ret; 2345c66ac9dbSNicholas Bellinger } 2346c66ac9dbSNicholas Bellinger if ((tmp != ALUA_STATUS_NONE) && 2347125d0119SHannes Reinecke (tmp != ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) && 2348125d0119SHannes Reinecke (tmp != ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA)) { 23496708bb27SAndy Grover pr_err("Illegal value for alua_tg_pt_status: %lu\n", 2350c66ac9dbSNicholas Bellinger tmp); 2351c66ac9dbSNicholas Bellinger return -EINVAL; 2352c66ac9dbSNicholas Bellinger } 2353c66ac9dbSNicholas Bellinger lun->lun_sep->sep_tg_pt_secondary_stat = (int)tmp; 2354c66ac9dbSNicholas Bellinger 2355c66ac9dbSNicholas Bellinger return count; 2356c66ac9dbSNicholas Bellinger } 2357c66ac9dbSNicholas Bellinger 2358c66ac9dbSNicholas Bellinger ssize_t core_alua_show_secondary_write_metadata( 2359c66ac9dbSNicholas Bellinger struct se_lun *lun, 2360c66ac9dbSNicholas Bellinger char *page) 2361c66ac9dbSNicholas Bellinger { 2362c66ac9dbSNicholas Bellinger return sprintf(page, "%d\n", 2363c66ac9dbSNicholas Bellinger lun->lun_sep->sep_tg_pt_secondary_write_md); 2364c66ac9dbSNicholas Bellinger } 2365c66ac9dbSNicholas Bellinger 2366c66ac9dbSNicholas Bellinger ssize_t core_alua_store_secondary_write_metadata( 2367c66ac9dbSNicholas Bellinger struct se_lun *lun, 2368c66ac9dbSNicholas Bellinger const char *page, 2369c66ac9dbSNicholas Bellinger size_t count) 2370c66ac9dbSNicholas Bellinger { 2371c66ac9dbSNicholas Bellinger unsigned long tmp; 2372c66ac9dbSNicholas Bellinger int ret; 2373c66ac9dbSNicholas Bellinger 237457103d7fSJingoo Han ret = kstrtoul(page, 0, &tmp); 2375c66ac9dbSNicholas Bellinger if (ret < 0) { 23766708bb27SAndy Grover pr_err("Unable to extract alua_tg_pt_write_md\n"); 237757103d7fSJingoo Han return ret; 2378c66ac9dbSNicholas Bellinger } 2379c66ac9dbSNicholas Bellinger if ((tmp != 0) && (tmp != 1)) { 23806708bb27SAndy Grover pr_err("Illegal value for alua_tg_pt_write_md:" 2381c66ac9dbSNicholas Bellinger " %lu\n", tmp); 2382c66ac9dbSNicholas Bellinger return -EINVAL; 2383c66ac9dbSNicholas Bellinger } 2384c66ac9dbSNicholas Bellinger lun->lun_sep->sep_tg_pt_secondary_write_md = (int)tmp; 2385c66ac9dbSNicholas Bellinger 2386c66ac9dbSNicholas Bellinger return count; 2387c66ac9dbSNicholas Bellinger } 2388c66ac9dbSNicholas Bellinger 23890fd97ccfSChristoph Hellwig int core_setup_alua(struct se_device *dev) 2390c66ac9dbSNicholas Bellinger { 2391c87fbd56SChristoph Hellwig if (dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV && 2392c87fbd56SChristoph Hellwig !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) { 2393c66ac9dbSNicholas Bellinger struct t10_alua_lu_gp_member *lu_gp_mem; 23940fd97ccfSChristoph Hellwig 2395c66ac9dbSNicholas Bellinger /* 239625985edcSLucas De Marchi * Associate this struct se_device with the default ALUA 2397c66ac9dbSNicholas Bellinger * LUN Group. 2398c66ac9dbSNicholas Bellinger */ 2399c66ac9dbSNicholas Bellinger lu_gp_mem = core_alua_allocate_lu_gp_mem(dev); 2400e3d6f909SAndy Grover if (IS_ERR(lu_gp_mem)) 2401e3d6f909SAndy Grover return PTR_ERR(lu_gp_mem); 2402c66ac9dbSNicholas Bellinger 2403c66ac9dbSNicholas Bellinger spin_lock(&lu_gp_mem->lu_gp_mem_lock); 2404c66ac9dbSNicholas Bellinger __core_alua_attach_lu_gp_mem(lu_gp_mem, 2405e3d6f909SAndy Grover default_lu_gp); 2406c66ac9dbSNicholas Bellinger spin_unlock(&lu_gp_mem->lu_gp_mem_lock); 2407c66ac9dbSNicholas Bellinger 24086708bb27SAndy Grover pr_debug("%s: Adding to default ALUA LU Group:" 2409c66ac9dbSNicholas Bellinger " core/alua/lu_gps/default_lu_gp\n", 2410e3d6f909SAndy Grover dev->transport->name); 2411c66ac9dbSNicholas Bellinger } 2412c66ac9dbSNicholas Bellinger 2413c66ac9dbSNicholas Bellinger return 0; 2414c66ac9dbSNicholas Bellinger } 2415