summaryrefslogtreecommitdiffstats
path: root/drivers/target/target_core_alua.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-05-25 21:33:08 -0700
committerNicholas Bellinger <nab@linux-iscsi.org>2015-06-01 00:26:38 -0700
commitadf653f92f38e80a78bb77e912d49bcc8055330f (patch)
tree374904527485a43dbc810905fa6f280cd1c2f5cf /drivers/target/target_core_alua.c
parentb3eeea6619a0ed4f37138661c49339b21361d397 (diff)
downloadblackbird-obmc-linux-adf653f92f38e80a78bb77e912d49bcc8055330f.tar.gz
blackbird-obmc-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.c394
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;
}
OpenPOWER on IntegriCloud