diff options
Diffstat (limited to 'drivers/target/target_core_alua.c')
| -rw-r--r-- | drivers/target/target_core_alua.c | 236 |
1 files changed, 106 insertions, 130 deletions
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 6b0d9beacf90..10250aca5a81 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /******************************************************************************* * Filename: target_core_alua.c * @@ -7,20 +8,6 @@ * * Nicholas A. Bellinger <nab@kernel.org> * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * ******************************************************************************/ #include <linux/slab.h> @@ -32,7 +19,7 @@ #include <linux/file.h> #include <linux/fs.h> #include <scsi/scsi_proto.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <target/target_core_base.h> #include <target/target_core_backend.h> @@ -136,7 +123,7 @@ target_emulate_report_referrals(struct se_cmd *cmd) transport_kunmap_data_sg(cmd); - target_complete_cmd(cmd, GOOD); + target_complete_cmd(cmd, SAM_STAT_GOOD); return 0; } @@ -177,6 +164,9 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd) spin_lock(&dev->t10_alua.tg_pt_gps_lock); list_for_each_entry(tg_pt_gp, &dev->t10_alua.tg_pt_gps_list, tg_pt_gp_list) { + /* Skip empty port groups */ + if (!tg_pt_gp->tg_pt_gp_members) + continue; /* * Check if the Target port group and Target port descriptor list * based on tg_pt_gp_members count will fit into the response payload. @@ -235,7 +225,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd) /* * Set RELATIVE TARGET PORT IDENTIFIER */ - put_unaligned_be16(lun->lun_rtpi, &buf[off]); + put_unaligned_be16(lun->lun_tpg->tpg_rtpi, &buf[off]); off += 2; rd_len += 4; } @@ -260,15 +250,15 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd) * this CDB was received upon to determine this value individually * for ALUA target port group. */ - spin_lock(&cmd->se_lun->lun_tg_pt_gp_lock); - tg_pt_gp = cmd->se_lun->lun_tg_pt_gp; + rcu_read_lock(); + tg_pt_gp = rcu_dereference(cmd->se_lun->lun_tg_pt_gp); if (tg_pt_gp) buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs; - spin_unlock(&cmd->se_lun->lun_tg_pt_gp_lock); + rcu_read_unlock(); } transport_kunmap_data_sg(cmd); - target_complete_cmd_with_length(cmd, GOOD, rd_len + 4); + target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, rd_len + 4); return 0; } @@ -305,24 +295,24 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) * Determine if explicit ALUA via SET_TARGET_PORT_GROUPS is allowed * for the local tg_pt_gp. */ - spin_lock(&l_lun->lun_tg_pt_gp_lock); - l_tg_pt_gp = l_lun->lun_tg_pt_gp; + rcu_read_lock(); + l_tg_pt_gp = rcu_dereference(l_lun->lun_tg_pt_gp); if (!l_tg_pt_gp) { - spin_unlock(&l_lun->lun_tg_pt_gp_lock); + rcu_read_unlock(); pr_err("Unable to access l_lun->tg_pt_gp\n"); rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) { - spin_unlock(&l_lun->lun_tg_pt_gp_lock); + rcu_read_unlock(); pr_debug("Unable to process SET_TARGET_PORT_GROUPS" " while TPGS_EXPLICIT_ALUA is disabled\n"); rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states; - spin_unlock(&l_lun->lun_tg_pt_gp_lock); + rcu_read_unlock(); ptr = &buf[4]; /* Skip over RESERVED area in header */ @@ -398,7 +388,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) /* * Extract the RELATIVE TARGET PORT IDENTIFIER to identify - * the Target Port in question for the the incoming + * the Target Port in question for the incoming * SET_TARGET_PORT_GROUPS op. */ rtpi = get_unaligned_be16(ptr + 2); @@ -409,7 +399,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) spin_lock(&dev->se_port_lock); list_for_each_entry(lun, &dev->dev_sep_list, lun_dev_link) { - if (lun->lun_rtpi != rtpi) + if (lun->lun_tpg->tpg_rtpi != rtpi) continue; // XXX: racy unlock @@ -437,26 +427,10 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) out: transport_kunmap_data_sg(cmd); if (!rc) - target_complete_cmd(cmd, GOOD); + target_complete_cmd(cmd, SAM_STAT_GOOD); return rc; } -static inline void set_ascq(struct se_cmd *cmd, u8 alua_ascq) -{ - /* - * Set SCSI additional sense code (ASC) to 'LUN Not Accessible'; - * The ALUA additional sense code qualifier (ASCQ) is determined - * by the ALUA primary or secondary access state.. - */ - pr_debug("[%s]: ALUA TG Port not available, " - "SenseKey: NOT_READY, ASC/ASCQ: " - "0x04/0x%02x\n", - cmd->se_tfo->fabric_name, alua_ascq); - - cmd->scsi_asc = 0x04; - cmd->scsi_ascq = alua_ascq; -} - static inline void core_alua_state_nonoptimized( struct se_cmd *cmd, unsigned char *cdb, @@ -471,9 +445,9 @@ static inline void core_alua_state_nonoptimized( cmd->alua_nonop_delay = nonop_delay_msecs; } -static inline int core_alua_state_lba_dependent( +static inline sense_reason_t core_alua_state_lba_dependent( struct se_cmd *cmd, - struct t10_alua_tg_pt_gp *tg_pt_gp) + u16 tg_pt_gp_id) { struct se_device *dev = cmd->se_dev; u64 segment_size, segment_mult, sectors, lba; @@ -519,23 +493,19 @@ static inline int core_alua_state_lba_dependent( } if (!cur_map) { spin_unlock(&dev->t10_alua.lba_map_lock); - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE); - return 1; + return TCM_ALUA_TG_PT_UNAVAILABLE; } list_for_each_entry(map_mem, &cur_map->lba_map_mem_list, lba_map_mem_list) { - if (map_mem->lba_map_mem_alua_pg_id != - tg_pt_gp->tg_pt_gp_id) + if (map_mem->lba_map_mem_alua_pg_id != tg_pt_gp_id) continue; switch(map_mem->lba_map_mem_alua_state) { case ALUA_ACCESS_STATE_STANDBY: spin_unlock(&dev->t10_alua.lba_map_lock); - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY); - return 1; + return TCM_ALUA_TG_PT_STANDBY; case ALUA_ACCESS_STATE_UNAVAILABLE: spin_unlock(&dev->t10_alua.lba_map_lock); - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE); - return 1; + return TCM_ALUA_TG_PT_UNAVAILABLE; default: break; } @@ -545,7 +515,7 @@ static inline int core_alua_state_lba_dependent( return 0; } -static inline int core_alua_state_standby( +static inline sense_reason_t core_alua_state_standby( struct se_cmd *cmd, unsigned char *cdb) { @@ -569,24 +539,21 @@ static inline int core_alua_state_standby( case SAI_READ_CAPACITY_16: return 0; default: - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY); - return 1; + return TCM_ALUA_TG_PT_STANDBY; } case MAINTENANCE_IN: switch (cdb[1] & 0x1f) { case MI_REPORT_TARGET_PGS: return 0; default: - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY); - return 1; + return TCM_ALUA_TG_PT_STANDBY; } case MAINTENANCE_OUT: switch (cdb[1]) { case MO_SET_TARGET_PGS: return 0; default: - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY); - return 1; + return TCM_ALUA_TG_PT_STANDBY; } case REQUEST_SENSE: case PERSISTENT_RESERVE_IN: @@ -595,14 +562,13 @@ static inline int core_alua_state_standby( case WRITE_BUFFER: return 0; default: - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_STANDBY); - return 1; + return TCM_ALUA_TG_PT_STANDBY; } return 0; } -static inline int core_alua_state_unavailable( +static inline sense_reason_t core_alua_state_unavailable( struct se_cmd *cmd, unsigned char *cdb) { @@ -619,30 +585,27 @@ static inline int core_alua_state_unavailable( case MI_REPORT_TARGET_PGS: return 0; default: - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE); - return 1; + return TCM_ALUA_TG_PT_UNAVAILABLE; } case MAINTENANCE_OUT: switch (cdb[1]) { case MO_SET_TARGET_PGS: return 0; default: - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE); - return 1; + return TCM_ALUA_TG_PT_UNAVAILABLE; } case REQUEST_SENSE: case READ_BUFFER: case WRITE_BUFFER: return 0; default: - set_ascq(cmd, ASCQ_04H_ALUA_TG_PT_UNAVAILABLE); - return 1; + return TCM_ALUA_TG_PT_UNAVAILABLE; } return 0; } -static inline int core_alua_state_transition( +static inline sense_reason_t core_alua_state_transition( struct se_cmd *cmd, unsigned char *cdb) { @@ -659,16 +622,14 @@ static inline int core_alua_state_transition( case MI_REPORT_TARGET_PGS: return 0; default: - set_ascq(cmd, ASCQ_04H_ALUA_STATE_TRANSITION); - return 1; + return TCM_ALUA_STATE_TRANSITION; } case REQUEST_SENSE: case READ_BUFFER: case WRITE_BUFFER: return 0; default: - set_ascq(cmd, ASCQ_04H_ALUA_STATE_TRANSITION); - return 1; + return TCM_ALUA_STATE_TRANSITION; } return 0; @@ -687,10 +648,12 @@ target_alua_state_check(struct se_cmd *cmd) struct se_lun *lun = cmd->se_lun; struct t10_alua_tg_pt_gp *tg_pt_gp; int out_alua_state, nonop_delay_msecs; + u16 tg_pt_gp_id; + sense_reason_t rc = TCM_NO_SENSE; if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) return 0; - if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA) + if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA) return 0; /* @@ -700,20 +663,19 @@ target_alua_state_check(struct se_cmd *cmd) if (atomic_read(&lun->lun_tg_pt_secondary_offline)) { pr_debug("ALUA: Got secondary offline status for local" " target port\n"); - set_ascq(cmd, ASCQ_04H_ALUA_OFFLINE); - return TCM_CHECK_CONDITION_NOT_READY; + return TCM_ALUA_OFFLINE; } - - if (!lun->lun_tg_pt_gp) + rcu_read_lock(); + tg_pt_gp = rcu_dereference(lun->lun_tg_pt_gp); + if (!tg_pt_gp) { + rcu_read_unlock(); return 0; + } - spin_lock(&lun->lun_tg_pt_gp_lock); - tg_pt_gp = lun->lun_tg_pt_gp; out_alua_state = tg_pt_gp->tg_pt_gp_alua_access_state; nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs; - - // XXX: keeps using tg_pt_gp witout reference after unlock - spin_unlock(&lun->lun_tg_pt_gp_lock); + tg_pt_gp_id = tg_pt_gp->tg_pt_gp_id; + rcu_read_unlock(); /* * Process ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED in a separate conditional * statement so the compiler knows explicitly to check this case first. @@ -728,20 +690,16 @@ target_alua_state_check(struct se_cmd *cmd) core_alua_state_nonoptimized(cmd, cdb, nonop_delay_msecs); break; case ALUA_ACCESS_STATE_STANDBY: - if (core_alua_state_standby(cmd, cdb)) - return TCM_CHECK_CONDITION_NOT_READY; + rc = core_alua_state_standby(cmd, cdb); break; case ALUA_ACCESS_STATE_UNAVAILABLE: - if (core_alua_state_unavailable(cmd, cdb)) - return TCM_CHECK_CONDITION_NOT_READY; + rc = core_alua_state_unavailable(cmd, cdb); break; case ALUA_ACCESS_STATE_TRANSITION: - if (core_alua_state_transition(cmd, cdb)) - return TCM_CHECK_CONDITION_NOT_READY; + rc = core_alua_state_transition(cmd, cdb); break; case ALUA_ACCESS_STATE_LBA_DEPENDENT: - if (core_alua_state_lba_dependent(cmd, tg_pt_gp)) - return TCM_CHECK_CONDITION_NOT_READY; + rc = core_alua_state_lba_dependent(cmd, tg_pt_gp_id); break; /* * OFFLINE is a secondary ALUA target port group access state, that is @@ -751,10 +709,16 @@ target_alua_state_check(struct se_cmd *cmd) default: pr_err("Unknown ALUA access state: 0x%02x\n", out_alua_state); - return TCM_INVALID_CDB_FIELD; + rc = TCM_INVALID_CDB_FIELD; } - return 0; + if (rc && rc != TCM_INVALID_CDB_FIELD) { + pr_debug("[%s]: ALUA TG Port not available, " + "SenseKey: NOT_READY, ASC/rc: 0x04/%d\n", + cmd->se_tfo->fabric_name, rc); + } + + return rc; } /* @@ -873,8 +837,6 @@ int core_alua_check_nonop_delay( { if (!(cmd->se_cmd_flags & SCF_ALUA_NON_OPTIMIZED)) return 0; - if (in_interrupt()) - return 0; /* * The ALUA Active/NonOptimized access state delay can be disabled * in via configfs with a value of zero @@ -888,7 +850,6 @@ int core_alua_check_nonop_delay( msleep_interruptible(cmd->alua_nonop_delay); return 0; } -EXPORT_SYMBOL(core_alua_check_nonop_delay); static int core_alua_write_tpg_metadata( const char *path, @@ -910,9 +871,6 @@ static int core_alua_write_tpg_metadata( return (ret < 0) ? -EIO : 0; } -/* - * Called with tg_pt_gp->tg_pt_gp_transition_mutex held - */ static int core_alua_update_tpg_primary_metadata( struct t10_alua_tg_pt_gp *tg_pt_gp) { @@ -921,6 +879,8 @@ static int core_alua_update_tpg_primary_metadata( char *path; int len, rc; + lockdep_assert_held(&tg_pt_gp->tg_pt_gp_transition_mutex); + md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL); if (!md_buf) { pr_err("Unable to allocate buf for ALUA metadata\n"); @@ -976,8 +936,7 @@ static void core_alua_queue_state_change_ua(struct t10_alua_tg_pt_gp *tg_pt_gp) spin_lock(&lun->lun_deve_lock); list_for_each_entry(se_deve, &lun->lun_deve_list, lun_link) { - lacl = rcu_dereference_check(se_deve->se_lun_acl, - lockdep_is_held(&lun->lun_deve_lock)); + lacl = se_deve->se_lun_acl; /* * spc4r37 p.242: @@ -1104,7 +1063,7 @@ int core_alua_do_port_transition( struct t10_alua_tg_pt_gp *tg_pt_gp; int primary, valid_states, rc = 0; - if (l_dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA) + if (l_dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA) return -ENODEV; valid_states = l_tg_pt_gp->tg_pt_gp_alua_supported_states; @@ -1261,10 +1220,10 @@ static int core_alua_set_tg_pt_secondary_state( struct t10_alua_tg_pt_gp *tg_pt_gp; int trans_delay_msecs; - spin_lock(&lun->lun_tg_pt_gp_lock); - tg_pt_gp = lun->lun_tg_pt_gp; + rcu_read_lock(); + tg_pt_gp = rcu_dereference(lun->lun_tg_pt_gp); if (!tg_pt_gp) { - spin_unlock(&lun->lun_tg_pt_gp_lock); + rcu_read_unlock(); pr_err("Unable to complete secondary state" " transition\n"); return -EINVAL; @@ -1288,7 +1247,7 @@ static int core_alua_set_tg_pt_secondary_state( "implicit", config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item), tg_pt_gp->tg_pt_gp_id, (offline) ? "OFFLINE" : "ONLINE"); - spin_unlock(&lun->lun_tg_pt_gp_lock); + rcu_read_unlock(); /* * Do the optional transition delay after we set the secondary * ALUA access state. @@ -1716,7 +1675,6 @@ int core_alua_set_tg_pt_gp_id( pr_err("Maximum ALUA alua_tg_pt_gps_count:" " 0x0000ffff reached\n"); spin_unlock(&dev->t10_alua.tg_pt_gps_lock); - kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); return -ENOSPC; } again: @@ -1761,8 +1719,10 @@ void core_alua_free_tg_pt_gp( * can be made while we are releasing struct t10_alua_tg_pt_gp. */ spin_lock(&dev->t10_alua.tg_pt_gps_lock); - list_del(&tg_pt_gp->tg_pt_gp_list); - dev->t10_alua.alua_tg_pt_gps_counter--; + if (tg_pt_gp->tg_pt_gp_valid_id) { + list_del(&tg_pt_gp->tg_pt_gp_list); + dev->t10_alua.alua_tg_pt_gps_count--; + } spin_unlock(&dev->t10_alua.tg_pt_gps_lock); /* @@ -1795,13 +1755,14 @@ void core_alua_free_tg_pt_gp( __target_attach_tg_pt_gp(lun, dev->t10_alua.default_tg_pt_gp); } else - lun->lun_tg_pt_gp = NULL; + rcu_assign_pointer(lun->lun_tg_pt_gp, NULL); spin_unlock(&lun->lun_tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock); } spin_unlock(&tg_pt_gp->tg_pt_gp_lock); + synchronize_rcu(); kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); } @@ -1846,7 +1807,7 @@ static void __target_attach_tg_pt_gp(struct se_lun *lun, assert_spin_locked(&lun->lun_tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock); - lun->lun_tg_pt_gp = tg_pt_gp; + rcu_assign_pointer(lun->lun_tg_pt_gp, tg_pt_gp); list_add_tail(&lun->lun_tg_pt_gp_link, &tg_pt_gp->tg_pt_gp_lun_list); tg_pt_gp->tg_pt_gp_members++; spin_lock(&lun->lun_deve_lock); @@ -1863,6 +1824,7 @@ void target_attach_tg_pt_gp(struct se_lun *lun, spin_lock(&lun->lun_tg_pt_gp_lock); __target_attach_tg_pt_gp(lun, tg_pt_gp); spin_unlock(&lun->lun_tg_pt_gp_lock); + synchronize_rcu(); } static void __target_detach_tg_pt_gp(struct se_lun *lun, @@ -1874,8 +1836,6 @@ static void __target_detach_tg_pt_gp(struct se_lun *lun, list_del_init(&lun->lun_tg_pt_gp_link); tg_pt_gp->tg_pt_gp_members--; spin_unlock(&tg_pt_gp->tg_pt_gp_lock); - - lun->lun_tg_pt_gp = NULL; } void target_detach_tg_pt_gp(struct se_lun *lun) @@ -1883,10 +1843,25 @@ void target_detach_tg_pt_gp(struct se_lun *lun) struct t10_alua_tg_pt_gp *tg_pt_gp; spin_lock(&lun->lun_tg_pt_gp_lock); - tg_pt_gp = lun->lun_tg_pt_gp; - if (tg_pt_gp) + tg_pt_gp = rcu_dereference_check(lun->lun_tg_pt_gp, + lockdep_is_held(&lun->lun_tg_pt_gp_lock)); + if (tg_pt_gp) { __target_detach_tg_pt_gp(lun, tg_pt_gp); + rcu_assign_pointer(lun->lun_tg_pt_gp, NULL); + } spin_unlock(&lun->lun_tg_pt_gp_lock); + synchronize_rcu(); +} + +static void target_swap_tg_pt_gp(struct se_lun *lun, + struct t10_alua_tg_pt_gp *old_tg_pt_gp, + struct t10_alua_tg_pt_gp *new_tg_pt_gp) +{ + assert_spin_locked(&lun->lun_tg_pt_gp_lock); + + if (old_tg_pt_gp) + __target_detach_tg_pt_gp(lun, old_tg_pt_gp); + __target_attach_tg_pt_gp(lun, new_tg_pt_gp); } ssize_t core_alua_show_tg_pt_gp_info(struct se_lun *lun, char *page) @@ -1895,8 +1870,8 @@ ssize_t core_alua_show_tg_pt_gp_info(struct se_lun *lun, char *page) struct t10_alua_tg_pt_gp *tg_pt_gp; ssize_t len = 0; - spin_lock(&lun->lun_tg_pt_gp_lock); - tg_pt_gp = lun->lun_tg_pt_gp; + rcu_read_lock(); + tg_pt_gp = rcu_dereference(lun->lun_tg_pt_gp); if (tg_pt_gp) { tg_pt_ci = &tg_pt_gp->tg_pt_gp_group.cg_item; len += sprintf(page, "TG Port Alias: %s\nTG Port Group ID:" @@ -1912,7 +1887,7 @@ ssize_t core_alua_show_tg_pt_gp_info(struct se_lun *lun, char *page) "Offline" : "None", core_alua_dump_status(lun->lun_tg_pt_secondary_stat)); } - spin_unlock(&lun->lun_tg_pt_gp_lock); + rcu_read_unlock(); return len; } @@ -1932,7 +1907,7 @@ ssize_t core_alua_store_tg_pt_gp_info( unsigned char buf[TG_PT_GROUP_NAME_BUF]; int move = 0; - if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA || + if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA || (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) return -ENODEV; @@ -1959,7 +1934,8 @@ ssize_t core_alua_store_tg_pt_gp_info( } spin_lock(&lun->lun_tg_pt_gp_lock); - tg_pt_gp = lun->lun_tg_pt_gp; + tg_pt_gp = rcu_dereference_check(lun->lun_tg_pt_gp, + lockdep_is_held(&lun->lun_tg_pt_gp_lock)); if (tg_pt_gp) { /* * Clearing an existing tg_pt_gp association, and replacing @@ -1977,18 +1953,16 @@ ssize_t core_alua_store_tg_pt_gp_info( &tg_pt_gp->tg_pt_gp_group.cg_item), tg_pt_gp->tg_pt_gp_id); - __target_detach_tg_pt_gp(lun, tg_pt_gp); - __target_attach_tg_pt_gp(lun, + target_swap_tg_pt_gp(lun, tg_pt_gp, dev->t10_alua.default_tg_pt_gp); spin_unlock(&lun->lun_tg_pt_gp_lock); - return count; + goto sync_rcu; } - __target_detach_tg_pt_gp(lun, tg_pt_gp); move = 1; } - __target_attach_tg_pt_gp(lun, tg_pt_gp_new); + target_swap_tg_pt_gp(lun, tg_pt_gp, tg_pt_gp_new); spin_unlock(&lun->lun_tg_pt_gp_lock); pr_debug("Target_Core_ConfigFS: %s %s/tpgt_%hu/%s to ALUA" " Target Port Group: alua/%s, ID: %hu\n", (move) ? @@ -1999,6 +1973,8 @@ ssize_t core_alua_store_tg_pt_gp_info( tg_pt_gp_new->tg_pt_gp_id); core_alua_put_tg_pt_gp_from_name(tg_pt_gp_new); +sync_rcu: + synchronize_rcu(); return count; } @@ -2189,7 +2165,7 @@ ssize_t core_alua_store_offline_bit( unsigned long tmp; int ret; - if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA || + if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA || (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) return -ENODEV; @@ -2275,7 +2251,7 @@ ssize_t core_alua_store_secondary_write_metadata( int core_setup_alua(struct se_device *dev) { - if (!(dev->transport->transport_flags & + if (!(dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_ALUA) && !(dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) { struct t10_alua_lu_gp_member *lu_gp_mem; |
