diff options
author | Christoph Hellwig <hch@lst.de> | 2015-05-25 21:33:08 -0700 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2015-06-01 00:26:38 -0700 |
commit | adf653f92f38e80a78bb77e912d49bcc8055330f (patch) | |
tree | 374904527485a43dbc810905fa6f280cd1c2f5cf /drivers/target/target_core_alua.c | |
parent | b3eeea6619a0ed4f37138661c49339b21361d397 (diff) | |
download | linux-adf653f92f38e80a78bb77e912d49bcc8055330f.tar.gz linux-adf653f92f38e80a78bb77e912d49bcc8055330f.tar.bz2 linux-adf653f92f38e80a78bb77e912d49bcc8055330f.zip |
target: Subsume se_port + t10_alua_tg_pt_gp_member into se_lun
This patch eliminates all se_port + t10_alua_tg_pt_gp_member usage,
and converts current users to direct se_lun pointer dereference.
This includes the removal of core_export_port(), core_release_port()
core_dev_export() and core_dev_unexport(). Along with conversion
of special case se_lun pointer dereference within PR ALL_TG_PT=1
and ALUA access state transition UNIT_ATTENTION handling.
Also, update core_enable_device_list_for_node() to reference the
new per se_lun->lun_deve_list when creating a new entry, or
replacing an existing one via RCU.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/target_core_alua.c')
-rw-r--r-- | drivers/target/target_core_alua.c | 394 |
1 files changed, 148 insertions, 246 deletions
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 53cdfabac861..1109c2833fe6 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -43,11 +43,13 @@ static sense_reason_t core_alua_check_transition(int state, int valid, int *primary); static int core_alua_set_tg_pt_secondary_state( - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, - struct se_port *port, int explicit, int offline); + struct se_lun *lun, int explicit, int offline); static char *core_alua_dump_state(int state); +static void __target_attach_tg_pt_gp(struct se_lun *lun, + struct t10_alua_tg_pt_gp *tg_pt_gp); + static u16 alua_lu_gps_counter; static u32 alua_lu_gps_count; @@ -145,9 +147,8 @@ sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - struct se_port *port; struct t10_alua_tg_pt_gp *tg_pt_gp; - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; + struct se_lun *lun; unsigned char *buf; u32 rd_len = 0, off; int ext_hdr = (cmd->t_task_cdb[1] & 0x20); @@ -222,9 +223,8 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd) rd_len += 8; spin_lock(&tg_pt_gp->tg_pt_gp_lock); - list_for_each_entry(tg_pt_gp_mem, &tg_pt_gp->tg_pt_gp_mem_list, - tg_pt_gp_mem_list) { - port = tg_pt_gp_mem->tg_pt; + list_for_each_entry(lun, &tg_pt_gp->tg_pt_gp_lun_list, + lun_tg_pt_gp_link) { /* * Start Target Port descriptor format * @@ -234,8 +234,8 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd) /* * Set RELATIVE TARGET PORT IDENTIFIER */ - buf[off++] = ((port->sep_rtpi >> 8) & 0xff); - buf[off++] = (port->sep_rtpi & 0xff); + buf[off++] = ((lun->lun_rtpi >> 8) & 0xff); + buf[off++] = (lun->lun_rtpi & 0xff); rd_len += 4; } spin_unlock(&tg_pt_gp->tg_pt_gp_lock); @@ -259,15 +259,11 @@ 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. */ - port = cmd->se_lun->lun_sep; - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; - if (tg_pt_gp_mem) { - spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; - if (tg_pt_gp) - buf[5] = tg_pt_gp->tg_pt_gp_implicit_trans_secs; - spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - } + spin_lock(&cmd->se_lun->lun_tg_pt_gp_lock); + tg_pt_gp = 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); } transport_kunmap_data_sg(cmd); @@ -284,10 +280,9 @@ sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *cmd) { struct se_device *dev = cmd->se_dev; - struct se_port *port, *l_port = cmd->se_lun->lun_sep; + struct se_lun *l_lun = cmd->se_lun; struct se_node_acl *nacl = cmd->se_sess->se_node_acl; struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *l_tg_pt_gp; - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; unsigned char *buf; unsigned char *ptr; sense_reason_t rc = TCM_NO_SENSE; @@ -295,9 +290,6 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) int alua_access_state, primary = 0, valid_states; u16 tg_pt_id, rtpi; - if (!l_port) - return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - if (cmd->data_length < 4) { pr_warn("SET TARGET PORT GROUPS parameter list length %u too" " small\n", cmd->data_length); @@ -312,29 +304,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. */ - l_tg_pt_gp_mem = l_port->sep_alua_tg_pt_gp_mem; - if (!l_tg_pt_gp_mem) { - pr_err("Unable to access l_port->sep_alua_tg_pt_gp_mem\n"); - rc = TCM_UNSUPPORTED_SCSI_OPCODE; - goto out; - } - spin_lock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); - l_tg_pt_gp = l_tg_pt_gp_mem->tg_pt_gp; + spin_lock(&l_lun->lun_tg_pt_gp_lock); + l_tg_pt_gp = l_lun->lun_tg_pt_gp; if (!l_tg_pt_gp) { - spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); - pr_err("Unable to access *l_tg_pt_gp_mem->tg_pt_gp\n"); + spin_unlock(&l_lun->lun_tg_pt_gp_lock); + pr_err("Unable to access l_lun->tg_pt_gp\n"); rc = TCM_UNSUPPORTED_SCSI_OPCODE; goto out; } - spin_unlock(&l_tg_pt_gp_mem->tg_pt_gp_mem_lock); if (!(l_tg_pt_gp->tg_pt_gp_alua_access_type & TPGS_EXPLICIT_ALUA)) { + spin_unlock(&l_lun->lun_tg_pt_gp_lock); 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); ptr = &buf[4]; /* Skip over RESERVED area in header */ @@ -396,7 +383,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) spin_unlock(&dev->t10_alua.tg_pt_gps_lock); if (!core_alua_do_port_transition(tg_pt_gp, - dev, l_port, nacl, + dev, l_lun, nacl, alua_access_state, 1)) found = true; @@ -406,6 +393,8 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) } spin_unlock(&dev->t10_alua.tg_pt_gps_lock); } else { + struct se_lun *lun; + /* * Extract the RELATIVE TARGET PORT IDENTIFIER to identify * the Target Port in question for the the incoming @@ -417,17 +406,16 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) * for the struct se_device storage object. */ spin_lock(&dev->se_port_lock); - list_for_each_entry(port, &dev->dev_sep_list, - sep_list) { - if (port->sep_rtpi != rtpi) + list_for_each_entry(lun, &dev->dev_sep_list, + lun_dev_link) { + if (lun->lun_rtpi != rtpi) continue; - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; - + // XXX: racy unlock spin_unlock(&dev->se_port_lock); if (!core_alua_set_tg_pt_secondary_state( - tg_pt_gp_mem, port, 1, 1)) + lun, 1, 1)) found = true; spin_lock(&dev->se_port_lock); @@ -696,9 +684,7 @@ target_alua_state_check(struct se_cmd *cmd) struct se_device *dev = cmd->se_dev; unsigned char *cdb = cmd->t_task_cdb; struct se_lun *lun = cmd->se_lun; - struct se_port *port = lun->lun_sep; struct t10_alua_tg_pt_gp *tg_pt_gp; - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; int out_alua_state, nonop_delay_msecs; if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) @@ -706,33 +692,27 @@ target_alua_state_check(struct se_cmd *cmd) if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) return 0; - if (!port) - return 0; /* * First, check for a struct se_port specific secondary ALUA target port * access state: OFFLINE */ - if (atomic_read(&port->sep_tg_pt_secondary_offline)) { + 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; } - /* - * Second, obtain the struct t10_alua_tg_pt_gp_member pointer to the - * ALUA target port group, to obtain current ALUA access state. - * Otherwise look for the underlying struct se_device association with - * a ALUA logical unit group. - */ - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; - if (!tg_pt_gp_mem) + + if (!lun->lun_tg_pt_gp) return 0; - spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; + spin_lock(&lun->lun_tg_pt_gp_lock); + tg_pt_gp = lun->lun_tg_pt_gp; out_alua_state = atomic_read(&tg_pt_gp->tg_pt_gp_alua_access_state); nonop_delay_msecs = tg_pt_gp->tg_pt_gp_nonop_delay_msecs; - spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); + + // XXX: keeps using tg_pt_gp witout reference after unlock + spin_unlock(&lun->lun_tg_pt_gp_lock); /* * Process ALUA_ACCESS_STATE_ACTIVE_OPTIMIZED in a separate conditional * statement so the compiler knows explicitly to check this case first. @@ -764,7 +744,7 @@ target_alua_state_check(struct se_cmd *cmd) break; /* * OFFLINE is a secondary ALUA target port group access state, that is - * handled above with struct se_port->sep_tg_pt_secondary_offline=1 + * handled above with struct se_lun->lun_tg_pt_secondary_offline=1 */ case ALUA_ACCESS_STATE_OFFLINE: default: @@ -906,10 +886,6 @@ int core_alua_check_nonop_delay( } EXPORT_SYMBOL(core_alua_check_nonop_delay); -/* - * Called with tg_pt_gp->tg_pt_gp_md_mutex or tg_pt_gp_mem->sep_tg_pt_md_mutex - * - */ static int core_alua_write_tpg_metadata( const char *path, unsigned char *md_buf, @@ -971,16 +947,14 @@ static void core_alua_do_transition_tg_pt_work(struct work_struct *work) struct t10_alua_tg_pt_gp, tg_pt_gp_transition_work.work); struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; struct se_dev_entry *se_deve; + struct se_lun *lun; struct se_lun_acl *lacl; - struct se_port *port; - struct t10_alua_tg_pt_gp_member *mem; bool explicit = (tg_pt_gp->tg_pt_gp_alua_access_status == ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG); spin_lock(&tg_pt_gp->tg_pt_gp_lock); - list_for_each_entry(mem, &tg_pt_gp->tg_pt_gp_mem_list, - tg_pt_gp_mem_list) { - port = mem->tg_pt; + list_for_each_entry(lun, &tg_pt_gp->tg_pt_gp_lun_list, + lun_tg_pt_gp_link) { /* * After an implicit target port asymmetric access state * change, a device server shall establish a unit attention @@ -995,14 +969,13 @@ static void core_alua_do_transition_tg_pt_work(struct work_struct *work) * every I_T nexus other than the I_T nexus on which the SET * TARGET PORT GROUPS command */ - atomic_inc_mb(&mem->tg_pt_gp_mem_ref_cnt); + atomic_inc_mb(&lun->lun_active); spin_unlock(&tg_pt_gp->tg_pt_gp_lock); - spin_lock_bh(&port->sep_alua_lock); - list_for_each_entry(se_deve, &port->sep_alua_list, - alua_port_list) { + spin_lock_bh(&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(&port->sep_alua_lock)); + lockdep_is_held(&lun->lun_deve_lock)); /* * se_deve->se_lun_acl pointer may be NULL for a * entry created without explicit Node+MappedLUN ACLs @@ -1014,18 +987,18 @@ static void core_alua_do_transition_tg_pt_work(struct work_struct *work) ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG) && (tg_pt_gp->tg_pt_gp_alua_nacl != NULL) && (tg_pt_gp->tg_pt_gp_alua_nacl == lacl->se_lun_nacl) && - (tg_pt_gp->tg_pt_gp_alua_port != NULL) && - (tg_pt_gp->tg_pt_gp_alua_port == port)) + (tg_pt_gp->tg_pt_gp_alua_lun != NULL) && + (tg_pt_gp->tg_pt_gp_alua_lun == lun)) continue; core_scsi3_ua_allocate(lacl->se_lun_nacl, se_deve->mapped_lun, 0x2A, ASCQ_2AH_ASYMMETRIC_ACCESS_STATE_CHANGED); } - spin_unlock_bh(&port->sep_alua_lock); + spin_unlock_bh(&lun->lun_deve_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock); - atomic_dec_mb(&mem->tg_pt_gp_mem_ref_cnt); + atomic_dec_mb(&lun->lun_active); } spin_unlock(&tg_pt_gp->tg_pt_gp_lock); /* @@ -1143,7 +1116,7 @@ static int core_alua_do_transition_tg_pt( int core_alua_do_port_transition( struct t10_alua_tg_pt_gp *l_tg_pt_gp, struct se_device *l_dev, - struct se_port *l_port, + struct se_lun *l_lun, struct se_node_acl *l_nacl, int new_state, int explicit) @@ -1173,7 +1146,7 @@ int core_alua_do_port_transition( * core_alua_do_transition_tg_pt() will always return * success. */ - l_tg_pt_gp->tg_pt_gp_alua_port = l_port; + l_tg_pt_gp->tg_pt_gp_alua_lun = l_lun; l_tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl; rc = core_alua_do_transition_tg_pt(l_tg_pt_gp, new_state, explicit); @@ -1212,10 +1185,10 @@ int core_alua_do_port_transition( continue; if (l_tg_pt_gp == tg_pt_gp) { - tg_pt_gp->tg_pt_gp_alua_port = l_port; + tg_pt_gp->tg_pt_gp_alua_lun = l_lun; tg_pt_gp->tg_pt_gp_alua_nacl = l_nacl; } else { - tg_pt_gp->tg_pt_gp_alua_port = NULL; + tg_pt_gp->tg_pt_gp_alua_lun = NULL; tg_pt_gp->tg_pt_gp_alua_nacl = NULL; } atomic_inc_mb(&tg_pt_gp->tg_pt_gp_ref_cnt); @@ -1252,22 +1225,20 @@ int core_alua_do_port_transition( return rc; } -/* - * Called with tg_pt_gp_mem->sep_tg_pt_md_mutex held - */ -static int core_alua_update_tpg_secondary_metadata( - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, - struct se_port *port) +static int core_alua_update_tpg_secondary_metadata(struct se_lun *lun) { + struct se_portal_group *se_tpg = lun->lun_tpg; unsigned char *md_buf; - struct se_portal_group *se_tpg = port->sep_tpg; char path[ALUA_METADATA_PATH_LEN], wwn[ALUA_SECONDARY_METADATA_WWN_LEN]; int len, rc; + mutex_lock(&lun->lun_tg_pt_md_mutex); + md_buf = kzalloc(ALUA_MD_BUF_LEN, GFP_KERNEL); if (!md_buf) { pr_err("Unable to allocate buf for ALUA metadata\n"); - return -ENOMEM; + rc = -ENOMEM; + goto out_unlock; } memset(path, 0, ALUA_METADATA_PATH_LEN); @@ -1282,32 +1253,33 @@ static int core_alua_update_tpg_secondary_metadata( len = snprintf(md_buf, ALUA_MD_BUF_LEN, "alua_tg_pt_offline=%d\n" "alua_tg_pt_status=0x%02x\n", - atomic_read(&port->sep_tg_pt_secondary_offline), - port->sep_tg_pt_secondary_stat); + atomic_read(&lun->lun_tg_pt_secondary_offline), + lun->lun_tg_pt_secondary_stat); snprintf(path, ALUA_METADATA_PATH_LEN, "/var/target/alua/%s/%s/lun_%u", se_tpg->se_tpg_tfo->get_fabric_name(), wwn, - port->sep_lun->unpacked_lun); + lun->unpacked_lun); rc = core_alua_write_tpg_metadata(path, md_buf, len); kfree(md_buf); +out_unlock: + mutex_unlock(&lun->lun_tg_pt_md_mutex); return rc; } static int core_alua_set_tg_pt_secondary_state( - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, - struct se_port *port, + struct se_lun *lun, int explicit, int offline) { struct t10_alua_tg_pt_gp *tg_pt_gp; int trans_delay_msecs; - spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; + spin_lock(&lun->lun_tg_pt_gp_lock); + tg_pt_gp = lun->lun_tg_pt_gp; if (!tg_pt_gp) { - spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); + spin_unlock(&lun->lun_tg_pt_gp_lock); pr_err("Unable to complete secondary state" " transition\n"); return -EINVAL; @@ -1315,14 +1287,14 @@ static int core_alua_set_tg_pt_secondary_state( trans_delay_msecs = tg_pt_gp->tg_pt_gp_trans_delay_msecs; /* * Set the secondary ALUA target port access state to OFFLINE - * or release the previously secondary state for struct se_port + * or release the previously secondary state for struct se_lun */ if (offline) - atomic_set(&port->sep_tg_pt_secondary_offline, 1); + atomic_set(&lun->lun_tg_pt_secondary_offline, 1); else - atomic_set(&port->sep_tg_pt_secondary_offline, 0); + atomic_set(&lun->lun_tg_pt_secondary_offline, 0); - port->sep_tg_pt_secondary_stat = (explicit) ? + lun->lun_tg_pt_secondary_stat = (explicit) ? ALUA_STATUS_ALTERED_BY_EXPLICIT_STPG : ALUA_STATUS_ALTERED_BY_IMPLICIT_ALUA; @@ -1331,7 +1303,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(&tg_pt_gp_mem->tg_pt_gp_mem_lock); + spin_unlock(&lun->lun_tg_pt_gp_lock); /* * Do the optional transition delay after we set the secondary * ALUA access state. @@ -1342,11 +1314,8 @@ static int core_alua_set_tg_pt_secondary_state( * See if we need to update the ALUA fabric port metadata for * secondary state and status */ - if (port->sep_tg_pt_secondary_write_md) { - mutex_lock(&port->sep_tg_pt_md_mutex); - core_alua_update_tpg_secondary_metadata(tg_pt_gp_mem, port); - mutex_unlock(&port->sep_tg_pt_md_mutex); - } + if (lun->lun_tg_pt_secondary_write_md) + core_alua_update_tpg_secondary_metadata(lun); return 0; } @@ -1700,7 +1669,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(struct se_device *dev, return NULL; } INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_list); - INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_mem_list); + INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_lun_list); mutex_init(&tg_pt_gp->tg_pt_gp_md_mutex); spin_lock_init(&tg_pt_gp->tg_pt_gp_lock); atomic_set(&tg_pt_gp->tg_pt_gp_ref_cnt, 0); @@ -1794,32 +1763,11 @@ again: return 0; } -struct t10_alua_tg_pt_gp_member *core_alua_allocate_tg_pt_gp_mem( - struct se_port *port) -{ - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; - - tg_pt_gp_mem = kmem_cache_zalloc(t10_alua_tg_pt_gp_mem_cache, - GFP_KERNEL); - if (!tg_pt_gp_mem) { - pr_err("Unable to allocate struct t10_alua_tg_pt_gp_member\n"); - return ERR_PTR(-ENOMEM); - } - INIT_LIST_HEAD(&tg_pt_gp_mem->tg_pt_gp_mem_list); - spin_lock_init(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - atomic_set(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt, 0); - - tg_pt_gp_mem->tg_pt = port; - port->sep_alua_tg_pt_gp_mem = tg_pt_gp_mem; - - return tg_pt_gp_mem; -} - void core_alua_free_tg_pt_gp( struct t10_alua_tg_pt_gp *tg_pt_gp) { struct se_device *dev = tg_pt_gp->tg_pt_gp_dev; - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *tg_pt_gp_mem_tmp; + struct se_lun *lun, *next; /* * Once we have reached this point, config_item_put() has already @@ -1850,30 +1798,24 @@ void core_alua_free_tg_pt_gp( * struct se_port. */ spin_lock(&tg_pt_gp->tg_pt_gp_lock); - list_for_each_entry_safe(tg_pt_gp_mem, tg_pt_gp_mem_tmp, - &tg_pt_gp->tg_pt_gp_mem_list, tg_pt_gp_mem_list) { - if (tg_pt_gp_mem->tg_pt_gp_assoc) { - list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); - tg_pt_gp->tg_pt_gp_members--; - tg_pt_gp_mem->tg_pt_gp_assoc = 0; - } + list_for_each_entry_safe(lun, next, + &tg_pt_gp->tg_pt_gp_lun_list, lun_tg_pt_gp_link) { + 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); /* - * tg_pt_gp_mem is associated with a single - * se_port->sep_alua_tg_pt_gp_mem, and is released via - * core_alua_free_tg_pt_gp_mem(). - * * If the passed tg_pt_gp does NOT match the default_tg_pt_gp, * assume we want to re-associate a given tg_pt_gp_mem with * default_tg_pt_gp. */ - spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); + spin_lock(&lun->lun_tg_pt_gp_lock); if (tg_pt_gp != dev->t10_alua.default_tg_pt_gp) { - __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, + __target_attach_tg_pt_gp(lun, dev->t10_alua.default_tg_pt_gp); } else - tg_pt_gp_mem->tg_pt_gp = NULL; - spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); + lun->lun_tg_pt_gp = NULL; + spin_unlock(&lun->lun_tg_pt_gp_lock); spin_lock(&tg_pt_gp->tg_pt_gp_lock); } @@ -1882,35 +1824,6 @@ void core_alua_free_tg_pt_gp( kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp); } -void core_alua_free_tg_pt_gp_mem(struct se_port *port) -{ - struct t10_alua_tg_pt_gp *tg_pt_gp; - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; - - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; - if (!tg_pt_gp_mem) - return; - - while (atomic_read(&tg_pt_gp_mem->tg_pt_gp_mem_ref_cnt)) - cpu_relax(); - - spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; - if (tg_pt_gp) { - spin_lock(&tg_pt_gp->tg_pt_gp_lock); - if (tg_pt_gp_mem->tg_pt_gp_assoc) { - list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); - tg_pt_gp->tg_pt_gp_members--; - tg_pt_gp_mem->tg_pt_gp_assoc = 0; - } - spin_unlock(&tg_pt_gp->tg_pt_gp_lock); - tg_pt_gp_mem->tg_pt_gp = NULL; - } - spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - - kmem_cache_free(t10_alua_tg_pt_gp_mem_cache, tg_pt_gp_mem); -} - static struct t10_alua_tg_pt_gp *core_alua_get_tg_pt_gp_by_name( struct se_device *dev, const char *name) { @@ -1944,50 +1857,58 @@ static void core_alua_put_tg_pt_gp_from_name( spin_unlock(&dev->t10_alua.tg_pt_gps_lock); } -/* - * Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held - */ -void __core_alua_attach_tg_pt_gp_mem( - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, - struct t10_alua_tg_pt_gp *tg_pt_gp) +static void __target_attach_tg_pt_gp(struct se_lun *lun, + struct t10_alua_tg_pt_gp *tg_pt_gp) { + assert_spin_locked(&lun->lun_tg_pt_gp_lock); + spin_lock(&tg_pt_gp->tg_pt_gp_lock); - tg_pt_gp_mem->tg_pt_gp = tg_pt_gp; - tg_pt_gp_mem->tg_pt_gp_assoc = 1; - list_add_tail(&tg_pt_gp_mem->tg_pt_gp_mem_list, - &tg_pt_gp->tg_pt_gp_mem_list); + 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_unlock(&tg_pt_gp->tg_pt_gp_lock); } -/* - * Called with struct t10_alua_tg_pt_gp_member->tg_pt_gp_mem_lock held - */ -static void __core_alua_drop_tg_pt_gp_mem( - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, - struct t10_alua_tg_pt_gp *tg_pt_gp) +void target_attach_tg_pt_gp(struct se_lun *lun, + struct t10_alua_tg_pt_gp *tg_pt_gp) +{ + 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); +} + +static void __target_detach_tg_pt_gp(struct se_lun *lun, + struct t10_alua_tg_pt_gp *tg_pt_gp) { + assert_spin_locked(&lun->lun_tg_pt_gp_lock); + spin_lock(&tg_pt_gp->tg_pt_gp_lock); - list_del(&tg_pt_gp_mem->tg_pt_gp_mem_list); - tg_pt_gp_mem->tg_pt_gp = NULL; - tg_pt_gp_mem->tg_pt_gp_assoc = 0; + 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; } -ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page) +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) + __target_detach_tg_pt_gp(lun, tg_pt_gp); + spin_unlock(&lun->lun_tg_pt_gp_lock); +} + +ssize_t core_alua_show_tg_pt_gp_info(struct se_lun *lun, char *page) { struct config_item *tg_pt_ci; struct t10_alua_tg_pt_gp *tg_pt_gp; - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; ssize_t len = 0; - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; - if (!tg_pt_gp_mem) - return len; - - spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - tg_pt_gp = tg_pt_gp_mem->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_ci = &tg_pt_gp->tg_pt_gp_group.cg_item; len += sprintf(page, "TG Port Alias: %s\nTG Port Group ID:" @@ -1999,34 +1920,29 @@ ssize_t core_alua_show_tg_pt_gp_info(struct se_port *port, char *page) &tg_pt_gp->tg_pt_gp_alua_access_state)), core_alua_dump_status( tg_pt_gp->tg_pt_gp_alua_access_status), - (atomic_read(&port->sep_tg_pt_secondary_offline)) ? + atomic_read(&lun->lun_tg_pt_secondary_offline) ? "Offline" : "None", - core_alua_dump_status(port->sep_tg_pt_secondary_stat)); + core_alua_dump_status(lun->lun_tg_pt_secondary_stat)); } - spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); + spin_unlock(&lun->lun_tg_pt_gp_lock); return len; } ssize_t core_alua_store_tg_pt_gp_info( - struct se_port *port, + struct se_lun *lun, const char *page, size_t count) { - struct se_portal_group *tpg; - struct se_lun *lun; - struct se_device *dev = port->sep_lun->lun_se_dev; + struct se_portal_group *tpg = lun->lun_tpg; + struct se_device *dev = lun->lun_se_dev; struct t10_alua_tg_pt_gp *tg_pt_gp = NULL, *tg_pt_gp_new = NULL; - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; unsigned char buf[TG_PT_GROUP_NAME_BUF]; int move = 0; - tpg = port->sep_tpg; - lun = port->sep_lun; - - tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; - if (!tg_pt_gp_mem) - return 0; + if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH || + (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) + return -ENODEV; if (count > TG_PT_GROUP_NAME_BUF) { pr_err("ALUA Target Port Group alias too large!\n"); @@ -2050,8 +1966,8 @@ ssize_t core_alua_store_tg_pt_gp_info( return -ENODEV; } - spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); - tg_pt_gp = tg_pt_gp_mem->tg_pt_gp; + spin_lock(&lun->lun_tg_pt_gp_lock); + tg_pt_gp = lun->lun_tg_pt_gp; if (tg_pt_gp) { /* * Clearing an existing tg_pt_gp association, and replacing @@ -2069,24 +1985,19 @@ 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); - __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); - __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, + __target_detach_tg_pt_gp(lun, tg_pt_gp); + __target_attach_tg_pt_gp(lun, dev->t10_alua.default_tg_pt_gp); - spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); + spin_unlock(&lun->lun_tg_pt_gp_lock); return count; } - /* - * Removing existing association of tg_pt_gp_mem with tg_pt_gp - */ - __core_alua_drop_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp); + __target_detach_tg_pt_gp(lun, tg_pt_gp); move = 1; } - /* - * Associate tg_pt_gp_mem with tg_pt_gp_new. - */ - __core_alua_attach_tg_pt_gp_mem(tg_pt_gp_mem, tg_pt_gp_new); - spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock); + + __target_attach_tg_pt_gp(lun, 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) ? "Moving" : "Adding", tpg->se_tpg_tfo->tpg_get_wwn(tpg), @@ -2269,11 +2180,8 @@ ssize_t core_alua_store_preferred_bit( ssize_t core_alua_show_offline_bit(struct se_lun *lun, char *page) { - if (!lun->lun_sep) - return -ENODEV; - return sprintf(page, "%d\n", - atomic_read(&lun->lun_sep->sep_tg_pt_secondary_offline)); + atomic_read(&lun->lun_tg_pt_secondary_offline)); } ssize_t core_alua_store_offline_bit( @@ -2281,11 +2189,12 @@ ssize_t core_alua_store_offline_bit( const char *page, size_t count) { - struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem; + struct se_device *dev = lun->lun_se_dev; unsigned long tmp; int ret; - if (!lun->lun_sep) + if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH || + (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)) return -ENODEV; ret = kstrtoul(page, 0, &tmp); @@ -2298,14 +2207,8 @@ ssize_t core_alua_store_offline_bit( tmp); return -EINVAL; } - tg_pt_gp_mem = lun->lun_sep->sep_alua_tg_pt_gp_mem; - if (!tg_pt_gp_mem) { - pr_err("Unable to locate *tg_pt_gp_mem\n"); - return -EINVAL; - } - ret = core_alua_set_tg_pt_secondary_state(tg_pt_gp_mem, - lun->lun_sep, 0, (int)tmp); + ret = core_alua_set_tg_pt_secondary_state(lun, 0, (int)tmp); if (ret < 0) return -EINVAL; @@ -2316,7 +2219,7 @@ ssize_t core_alua_show_secondary_status( struct se_lun *lun, char *page) { - return sprintf(page, "%d\n", lun->lun_sep->sep_tg_pt_secondary_stat); + return sprintf(page, "%d\n", lun->lun_tg_pt_secondary_stat); } ssize_t core_alua_store_secondary_status( @@ -2339,7 +2242,7 @@ ssize_t core_alua_store_secondary_status( tmp); return -EINVAL; } - lun->lun_sep->sep_tg_pt_secondary_stat = (int)tmp; + lun->lun_tg_pt_secondary_stat = (int)tmp; return count; } @@ -2348,8 +2251,7 @@ ssize_t core_alua_show_secondary_write_metadata( struct se_lun *lun, char *page) { - return sprintf(page, "%d\n", - lun->lun_sep->sep_tg_pt_secondary_write_md); + return sprintf(page, "%d\n", lun->lun_tg_pt_secondary_write_md); } ssize_t core_alua_store_secondary_write_metadata( @@ -2370,7 +2272,7 @@ ssize_t core_alua_store_secondary_write_metadata( " %lu\n", tmp); return -EINVAL; } - lun->lun_sep->sep_tg_pt_secondary_write_md = (int)tmp; + lun->lun_tg_pt_secondary_write_md = (int)tmp; return count; } |