[PATCH 1/6] [Target_Core_Mod/ALUA]: Add support for SPC-3 TargetPort and Logical Unit Groups

From: Nicholas A. Bellinger
Date: Fri Feb 06 2009 - 02:58:20 EST


>From d796aa7f4d5474ced5c97557fb52fcc326dab31e Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
Date: Thu, 5 Feb 2009 23:03:20 -0800
Subject: [PATCH 1/6] [Target_Core_Mod/ALUA]: Add support for SPC-3 Target Port and Logical Unit Groups

This patch adds the necessary infrastructure for ALUA defined Target Port Group
and Logical Unit Group abstractions with Target_Core_Mod. It adds the following
data structures:

*) t10_alua_tg_pt_gp_t (References se_port_t)
*) t10_alua_lu_gp_t (References se_device_t)

it also places these lists in se_global_t.

Also, patch also updates REPORT_TARGET_PORT_GROUP CDB emulation to scan
through the t10_alua_tg_pt_gp_t list.

Finally, this patch adds new functions core_alua_show_tg_pt_gp_info() and
core_alua_store_tg_pt_gp_info() as EXPORT_SYMBOL(). These wrapper functions
are used by ConfigFS aware $FABRIC_MOD (like LIO-Target v3.0) to modify
Target Port Group assocation for a given Target_Core_Mod/ConfigFS symlinked
SCSI Target Port.

Here is what it looks like with sg_rtpg with DEFAULT Target Port Group "
core/alua/tg_pt_gps/default_tg_pt_gp:

initiator# sg_rtpg -v /dev/sde
report target port groups cdb: a3 0a 00 00 00 00 00 00 04 00 00 00
Report list length = 20
Report target port groups:
target port group id : 0x0 , Pref=0
target port group asymmetric access state : 0x00
T_SUP : 0, O_SUP : 0, U_SUP : 0, S_SUP : 0, AN_SUP : 1, AO_SUP : 1
status code : 0x02
vendor unique status : 0x00
target port count : 02
Relative target port ids:
0x01
0x02

with the same Target_Core_Mod/IBLOCK storage object exported on
two different Relative target port ids.

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
---
drivers/lio-core/target_core_alua.c | 496 ++++++++++++++++++++++++++++++-----
drivers/lio-core/target_core_alua.h | 14 +
drivers/lio-core/target_core_base.h | 42 +++
3 files changed, 490 insertions(+), 62 deletions(-)

diff --git a/drivers/lio-core/target_core_alua.c b/drivers/lio-core/target_core_alua.c
index b43356e..b5f5d66 100644
--- a/drivers/lio-core/target_core_alua.c
+++ b/drivers/lio-core/target_core_alua.c
@@ -43,74 +43,81 @@

#undef TARGET_CORE_ALUA_C

+extern se_global_t *se_global;
+
+extern struct kmem_cache *t10_alua_lu_gp_cache;
+extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
+
+/*
+ * REPORT_TARGET_PORT_GROUPS
+ *
+ * See spc4r17 6.2.7
+ */
extern int core_scsi3_emulate_report_target_port_groups (se_cmd_t *cmd)
{
- se_lun_t *lun = SE_LUN(cmd);
se_port_t *port;
+ t10_alua_tg_pt_gp_t *tg_pt_gp;
unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
u32 rd_len = 0, off = 4;
- u16 tg_pg = 0;
- u8 tg_pg_count = 1; // Assume 1 for now

- if (!(lun)) {
- printk(KERN_ERR "SPC-3 ALUA se_lun_t is NULL!\n");
- return(PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_FAILURE);
- }
- if (!(port = lun->lun_sep)) {
- printk(KERN_ERR "SPC-3 ALUA se_port_t is NULL\n");
- return(PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_FAILURE);
- }
- /*
- * PREF: Preferred target port bit
- */
-// buf[off] = 0x80;
- /*
- * Set the ASYMMETRIC ACCESS State
- */
- buf[off++] |= ALUA_ACCESS_STATE_ACTIVE_OPTMIZED;
- /*
- * Set supported ASYMMETRIC ACCESS State bits
- */
-// buf[off] = 0x80; // T_SUP
-// buf[off] |= 0x40; // O_SUP
-// buf[off] |= 0x8; // U_SUP
-// buf[off] |= 0x4; // S_SUP
-// buf[off] |= 0x2; // AN_SUP
- buf[off++] |= 0x1; // AO_SUP
- /*
- * TARGET PORT GROUP
- */
- buf[off++] = ((tg_pg >> 8) & 0xff);
- buf[off++] = (tg_pg & 0xff);
+ spin_lock(&se_global->tg_pt_gps_lock);
+ list_for_each_entry(tg_pt_gp, &se_global->g_tg_pt_gps_list, tg_pt_gp_list) {
+ /*
+ * PREF: Preferred target port bit
+ */
+// buf[off] = 0x80;
+ /*
+ * Set the ASYMMETRIC ACCESS State
+ */
+ buf[off++] |= (tg_pt_gp->tg_pt_gp_alua_access_state & 0xff);
+ /*
+ * Set supported ASYMMETRIC ACCESS State bits
+ */
+// buf[off] = 0x80; // T_SUP
+// buf[off] |= 0x40; // O_SUP
+// buf[off] |= 0x8; // U_SUP
+// buf[off] |= 0x4; // S_SUP
+ buf[off] |= 0x2; // AN_SUP
+ buf[off++] |= 0x1; // AO_SUP
+ /*
+ * TARGET PORT GROUP
+ */
+ buf[off++] = ((tg_pt_gp->tg_pt_gp_id >> 8) & 0xff);
+ buf[off++] = (tg_pt_gp->tg_pt_gp_id & 0xff);

- off++; // Skip over Reserved
- /*
- * STATUS CODE
- */
- buf[off++] = ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA;
- /*
- * Vendor Specific field
- */
- buf[off++] = 0x00;
- /*
- * TARGET PORT COUNT
- */
- buf[off++] = tg_pg_count;
-
- rd_len += 8;
- /*
- * Start Target Port descriptor format
- *
- * See spc4r17 section 6.2.7 Table 247
- */
- off += 2; // Skip over Obsolete
- /*
- * Set RELATIVE TARGET PORT IDENTIFIER
- */
- buf[off++] = ((port->sep_rtpi >> 8) & 0xff);
- buf[off++] = (port->sep_rtpi & 0xff);
-
- rd_len += 4;
+ off++; // Skip over Reserved
+ /*
+ * STATUS CODE
+ */
+ buf[off++] = ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA;
+ /*
+ * Vendor Specific field
+ */
+ buf[off++] = 0x00;
+ /*
+ * TARGET PORT COUNT
+ */
+ buf[off++] = (tg_pt_gp->tg_pt_gp_members & 0xff);
+ rd_len += 8;
+
+ spin_lock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ list_for_each_entry(port, &tg_pt_gp->tg_pt_gp_ref_list, sep_tg_pt_gp_list) {
+ /*
+ * Start Target Port descriptor format
+ *
+ * See spc4r17 section 6.2.7 Table 247
+ */
+ off += 2; // Skip over Obsolete
+ /*
+ * Set RELATIVE TARGET PORT IDENTIFIER
+ */
+ buf[off++] = ((port->sep_rtpi >> 8) & 0xff);
+ buf[off++] = (port->sep_rtpi & 0xff);
+ rd_len += 4;
+ }
+ spin_unlock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ }
+ spin_unlock(&se_global->tg_pt_gps_lock);
/*
* Set the RETURN DATA LENGTH set in the header of the DataIN Payload
*/
@@ -122,6 +129,364 @@ extern int core_scsi3_emulate_report_target_port_groups (se_cmd_t *cmd)
return(0);
}

+extern t10_alua_lu_gp_t *core_alua_allocate_lu_gp (const char *name)
+{
+ t10_alua_lu_gp_t *lu_gp, *lu_gp_tmp;
+
+ if (!(lu_gp = kmem_cache_zalloc(t10_alua_lu_gp_cache, GFP_KERNEL))) {
+ printk("Unable to allocate t10_alua_lu_gp_t\n");
+ return(NULL);
+ }
+ INIT_LIST_HEAD(&lu_gp->lu_gp_list);
+ INIT_LIST_HEAD(&lu_gp->lu_gp_ref_list);
+ spin_lock_init(&lu_gp->lu_gp_ref_lock);
+ lu_gp->lu_gp_alua_access_state = ALUA_ACCESS_STATE_ACTIVE_OPTMIZED;
+
+ spin_lock(&se_global->lu_gps_lock);
+ if (se_global->alua_lu_gps_count == 0x0000ffff) {
+ spin_unlock(&se_global->lu_gps_lock);
+ kmem_cache_free(t10_alua_lu_gp_cache, lu_gp);
+ return(NULL);
+ }
+again:
+ lu_gp->lu_gp_id = se_global->alua_lu_gps_counter++;
+
+ list_for_each_entry(lu_gp_tmp, &se_global->g_lu_gps_list, lu_gp_list) {
+ if (lu_gp_tmp->lu_gp_id == lu_gp->lu_gp_id)
+ goto again;
+ }
+
+ list_add_tail(&lu_gp->lu_gp_list, &se_global->g_lu_gps_list);
+ se_global->alua_lu_gps_count++;
+ spin_unlock(&se_global->lu_gps_lock);
+
+ return(lu_gp);
+}
+
+extern void core_alua_free_lu_gp (t10_alua_lu_gp_t *lu_gp)
+{
+ se_device_t *dev, *dev_tmp;
+
+ spin_lock(&lu_gp->lu_gp_ref_lock);
+ list_for_each_entry_safe(dev, dev_tmp, &lu_gp->lu_gp_ref_list, dev_lu_gp_list) {
+ list_del(&dev->dev_lu_gp_list);
+ spin_lock(&dev->dev_alua_lock);
+ dev->dev_alua_lu_gp = NULL;
+ spin_unlock(&dev->dev_alua_lock);
+ }
+ spin_unlock(&lu_gp->lu_gp_ref_lock);
+
+ spin_lock(&se_global->lu_gps_lock);
+ list_del(&lu_gp->lu_gp_list);
+ se_global->alua_lu_gps_count--;
+ spin_unlock(&se_global->lu_gps_lock);
+
+ kmem_cache_free(t10_alua_lu_gp_cache, lu_gp);
+ return;
+}
+
+extern t10_alua_lu_gp_t *core_alua_get_lu_gp_by_name (se_device_t *dev, const char *name)
+{
+ t10_alua_lu_gp_t *lu_gp;
+ struct config_item *ci;
+
+ spin_lock(&se_global->lu_gps_lock);
+ list_for_each_entry(lu_gp, &se_global->g_lu_gps_list, lu_gp_list) {
+ ci = &lu_gp->lu_gp_group.cg_item;
+ if (!(strcmp(config_item_name(ci), name))) {
+ atomic_inc(&lu_gp->lu_gp_ref_cnt);
+ spin_unlock(&se_global->lu_gps_lock);
+ return(lu_gp);
+ }
+ }
+ spin_unlock(&se_global->lu_gps_lock);
+
+ return(NULL);
+}
+
+extern void core_alua_attach_lu_gp (se_device_t *dev, t10_alua_lu_gp_t *lu_gp)
+{
+ spin_lock(&lu_gp->lu_gp_ref_lock);
+ list_add_tail(&dev->dev_lu_gp_list, &lu_gp->lu_gp_ref_list);
+ lu_gp->lu_gp_members++;
+ spin_lock(&dev->dev_alua_lock);
+ dev->dev_alua_lu_gp = lu_gp;
+ spin_unlock(&dev->dev_alua_lock);
+ spin_unlock(&lu_gp->lu_gp_ref_lock);
+
+ return;
+}
+
+/*
+ * Called with se_device_t->dev_alua_lock held.
+ */
+extern void __core_alua_put_lu_gp (se_device_t *dev, int clear)
+{
+ t10_alua_lu_gp_t *lu_gp;
+
+ if (!(lu_gp = dev->dev_alua_lu_gp))
+ return;
+
+ spin_lock(&lu_gp->lu_gp_ref_lock);
+ list_del(&dev->dev_lu_gp_list);
+ atomic_dec(&lu_gp->lu_gp_ref_cnt);
+ lu_gp->lu_gp_members--;
+
+ if (!(clear)) {
+ spin_unlock(&lu_gp->lu_gp_ref_lock);
+ return;
+ }
+ dev->dev_alua_lu_gp = NULL;
+ spin_unlock(&lu_gp->lu_gp_ref_lock);
+
+ return;
+}
+
+extern void core_alua_put_lu_gp (se_device_t *dev, int clear)
+{
+ t10_alua_lu_gp_t *lu_gp;
+
+ spin_lock(&dev->dev_alua_lock);
+ if (!(lu_gp = dev->dev_alua_lu_gp)) {
+ spin_unlock(&dev->dev_alua_lock);
+ return;
+ }
+ spin_lock(&lu_gp->lu_gp_ref_lock);
+ list_del(&dev->dev_lu_gp_list);
+ atomic_dec(&lu_gp->lu_gp_ref_cnt);
+ lu_gp->lu_gp_members--;
+
+ if (!(clear)) {
+ spin_unlock(&lu_gp->lu_gp_ref_lock);
+ spin_unlock(&dev->dev_alua_lock);
+ return;
+ }
+ dev->dev_alua_lu_gp = NULL;
+ spin_unlock(&lu_gp->lu_gp_ref_lock);
+ spin_unlock(&dev->dev_alua_lock);
+
+ return;
+}
+
+extern t10_alua_tg_pt_gp_t *core_alua_allocate_tg_pt_gp (const char *name)
+{
+ t10_alua_tg_pt_gp_t *tg_pt_gp, *tg_pt_gp_tmp;
+
+ if (!(tg_pt_gp = kmem_cache_zalloc(t10_alua_tg_pt_gp_cache, GFP_KERNEL))) {
+ printk("Unable to allocate t10_alua_tg_pt_gp_t\n");
+ return(NULL);
+ }
+ INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_list);
+ INIT_LIST_HEAD(&tg_pt_gp->tg_pt_gp_ref_list);
+ spin_lock_init(&tg_pt_gp->tg_pt_gp_ref_lock);
+ tg_pt_gp->tg_pt_gp_alua_access_state = ALUA_ACCESS_STATE_ACTIVE_OPTMIZED;
+
+ spin_lock(&se_global->tg_pt_gps_lock);
+ if (se_global->alua_tg_pt_gps_count == 0x0000ffff) {
+ spin_unlock(&se_global->tg_pt_gps_lock);
+ kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp);
+ return(NULL);
+ }
+again:
+ tg_pt_gp->tg_pt_gp_id = se_global->alua_tg_pt_gps_counter++;
+
+ list_for_each_entry(tg_pt_gp_tmp, &se_global->g_tg_pt_gps_list, tg_pt_gp_list) {
+ if (tg_pt_gp_tmp->tg_pt_gp_id == tg_pt_gp->tg_pt_gp_id)
+ goto again;
+ }
+
+ list_add_tail(&tg_pt_gp->tg_pt_gp_list, &se_global->g_tg_pt_gps_list);
+ se_global->alua_tg_pt_gps_count++;
+ spin_unlock(&se_global->tg_pt_gps_lock);
+
+ return(tg_pt_gp);
+}
+
+extern void core_alua_free_tg_pt_gp (t10_alua_tg_pt_gp_t *tg_pt_gp)
+{
+ se_port_t *port, *port_tmp;
+
+ spin_lock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ list_for_each_entry_safe(port, port_tmp, &tg_pt_gp->tg_pt_gp_ref_list,
+ sep_tg_pt_gp_list) {
+ list_del(&port->sep_tg_pt_gp_list);
+ spin_lock(&port->sep_alua_lock);
+ port->sep_alua_tg_pt_gp = NULL;
+ spin_unlock(&port->sep_alua_lock);
+ }
+ spin_unlock(&tg_pt_gp->tg_pt_gp_ref_lock);
+
+ spin_lock(&se_global->tg_pt_gps_lock);
+ list_del(&tg_pt_gp->tg_pt_gp_list);
+ se_global->alua_tg_pt_gps_counter--;
+ spin_unlock(&se_global->tg_pt_gps_lock);
+
+ kmem_cache_free(t10_alua_tg_pt_gp_cache, tg_pt_gp);
+ return;
+}
+
+extern t10_alua_tg_pt_gp_t *core_alua_get_tg_pt_gp_by_name (se_port_t *port, const char *name)
+{
+ t10_alua_tg_pt_gp_t *tg_pt_gp;
+ struct config_item *ci;
+
+ spin_lock(&se_global->tg_pt_gps_lock);
+ list_for_each_entry(tg_pt_gp, &se_global->g_tg_pt_gps_list, tg_pt_gp_list) {
+ ci = &tg_pt_gp->tg_pt_gp_group.cg_item;
+ if (!(strcmp(config_item_name(ci), name))) {
+ atomic_inc(&tg_pt_gp->tg_pt_gp_ref_cnt);
+ spin_unlock(&se_global->tg_pt_gps_lock);
+ return(tg_pt_gp);
+ }
+ }
+ spin_unlock(&se_global->tg_pt_gps_lock);
+
+ return(NULL);
+}
+
+extern void core_alua_attach_tg_pt_gp (se_port_t *port, t10_alua_tg_pt_gp_t *tg_pt_gp)
+{
+ spin_lock(&port->sep_alua_lock);
+ spin_lock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ list_add_tail(&port->sep_tg_pt_gp_list, &tg_pt_gp->tg_pt_gp_ref_list);
+ tg_pt_gp->tg_pt_gp_members++;
+ spin_unlock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ port->sep_alua_tg_pt_gp = tg_pt_gp;
+ spin_unlock(&port->sep_alua_lock);
+
+ return;
+}
+
+/*
+ * Called with se_port_t->sep_alua_lock held.
+ */
+extern void __core_alua_put_tg_pt_gp (se_port_t *port, int clear)
+{
+ t10_alua_tg_pt_gp_t *tg_pt_gp;
+
+ if (!(tg_pt_gp = port->sep_alua_tg_pt_gp))
+ return;
+
+ spin_lock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ list_del(&port->sep_tg_pt_gp_list);
+ atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
+ tg_pt_gp->tg_pt_gp_members--;
+
+ if (!(clear)) {
+ spin_unlock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ return;
+ }
+ port->sep_alua_tg_pt_gp = NULL;
+ spin_unlock(&tg_pt_gp->tg_pt_gp_ref_lock);
+
+ return;
+}
+
+extern void core_alua_put_tg_pt_gp (se_port_t *port, int clear)
+{
+ t10_alua_tg_pt_gp_t *tg_pt_gp;
+
+ spin_lock(&port->sep_alua_lock);
+ if (!(tg_pt_gp = port->sep_alua_tg_pt_gp)) {
+ spin_unlock(&port->sep_alua_lock);
+ return;
+ }
+ spin_lock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ list_del(&port->sep_tg_pt_gp_list);
+ atomic_dec(&tg_pt_gp->tg_pt_gp_ref_cnt);
+ tg_pt_gp->tg_pt_gp_members--;
+
+ if (!(clear)) {
+ spin_unlock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ spin_unlock(&port->sep_alua_lock);
+ return;
+ }
+ port->sep_alua_tg_pt_gp = NULL;
+ spin_unlock(&tg_pt_gp->tg_pt_gp_ref_lock);
+ spin_unlock(&port->sep_alua_lock);
+
+ return;
+}
+
+extern ssize_t core_alua_show_tg_pt_gp_info (se_port_t *port, char *page)
+{
+ struct config_item *tg_pt_ci;
+ t10_alua_tg_pt_gp_t *tg_pt_gp;
+ ssize_t len = 0;
+
+ spin_lock(&port->sep_alua_lock);
+ if ((tg_pt_gp = port->sep_alua_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: %hu\n",
+ config_item_name(tg_pt_ci), tg_pt_gp->tg_pt_gp_id);
+ }
+ spin_unlock(&port->sep_alua_lock);
+
+ return(len);
+}
+
+EXPORT_SYMBOL(core_alua_show_tg_pt_gp_info);
+
+extern ssize_t core_alua_store_tg_pt_gp_info (se_port_t *port, const char *page, size_t count)
+{
+ se_portal_group_t *tpg;
+ se_lun_t *lun;
+ t10_alua_tg_pt_gp_t *tg_pt_gp = NULL, *tg_pt_gp_new;
+ unsigned char buf[256];
+ int move = 0;
+
+ if (count > 256) {
+ printk(KERN_ERR "ALUA Target Port Group alias too large!\n");
+ return(-EINVAL);
+ }
+ memset(buf, 0, 256);
+ memcpy(buf, page, count);
+
+ tpg = port->sep_tpg;
+ lun = port->sep_lun;
+
+ spin_lock(&port->sep_alua_lock);
+ if ((tg_pt_gp = port->sep_alua_tg_pt_gp)) {
+ if (!(strcmp(strstrip(buf), "NULL"))) {
+ printk("Target_Core_ConfigFS: Releasing %s/tpgt_%hu/%s"
+ " from ALUA Target Port Group: core/alua/tg_pt"
+ "_gps/%s, ID: %hu\n",
+ TPG_TFO(tpg)->tpg_get_wwn(tpg),
+ TPG_TFO(tpg)->tpg_get_tag(tpg),
+ config_item_name(&lun->lun_group.cg_item),
+ config_item_name(&tg_pt_gp->tg_pt_gp_group.cg_item),
+ tg_pt_gp->tg_pt_gp_id);
+
+ __core_alua_put_tg_pt_gp(port, 1);
+ spin_unlock(&port->sep_alua_lock);
+
+ return(count);
+ }
+ }
+ spin_unlock(&port->sep_alua_lock);
+
+ if (!(tg_pt_gp_new = core_alua_get_tg_pt_gp_by_name(port, strstrip(buf))))
+ return(-ENODEV);
+
+ if (tg_pt_gp) {
+ core_alua_put_tg_pt_gp(port, 0);
+ move = 1;
+ }
+ core_alua_attach_tg_pt_gp(port, tg_pt_gp_new);
+
+ printk("Target_Core_ConfigFS: %s %s/tpgt_%hu/%s to ALUA Target Port"
+ " Group: core/alua/tg_pt_gps/%s, ID: %hu\n", (move) ?
+ "Moving" : "Adding", TPG_TFO(tpg)->tpg_get_wwn(tpg),
+ TPG_TFO(tpg)->tpg_get_tag(tpg),
+ config_item_name(&lun->lun_group.cg_item),
+ config_item_name(&tg_pt_gp_new->tg_pt_gp_group.cg_item),
+ tg_pt_gp_new->tg_pt_gp_id);
+
+ return(count);
+}
+
+EXPORT_SYMBOL(core_alua_store_tg_pt_gp_info);
+
extern int core_setup_alua (se_device_t *dev)
{
se_subsystem_dev_t *su_dev = dev->se_sub_dev;
@@ -147,9 +512,16 @@ extern int core_setup_alua (se_device_t *dev)
alua->alua_type = SPC3_ALUA_EMULATED;
printk("%s: Enabling ALUA Emulation for SPC-3 device\n",
TRANSPORT(dev)->name);
+ /*
+ * Assoicate this se_device_t with the default ALUA
+ * LUN Group.
+ */
+ core_alua_attach_lu_gp(dev, se_global->default_lu_gp);
+ printk("%s: Adding to default ALUA LU Group: core/alua"
+ "/lu_gps/default_lu_gp\n", TRANSPORT(dev)->name);
} else {
alua->alua_type = SPC2_ALUA_DISABLED;
- printk("%s: Disabling ALUA for SPC-2 device\n",
+ printk("%s: Disabling ALUA Emulation for SPC-2 device\n",
TRANSPORT(dev)->name);
}

diff --git a/drivers/lio-core/target_core_alua.h b/drivers/lio-core/target_core_alua.h
index e08cbf4..335847a 100644
--- a/drivers/lio-core/target_core_alua.h
+++ b/drivers/lio-core/target_core_alua.h
@@ -33,6 +33,20 @@
#define ALUA_STATUS_ALTERED_BY_IMPLICT_ALUA 0x02

extern int core_scsi3_emulate_report_target_port_groups (struct se_cmd_s *);
+extern struct t10_alua_lu_gp_s *core_alua_allocate_lu_gp (const char *);
+extern void core_alua_free_lu_gp (struct t10_alua_lu_gp_s *);
+extern struct t10_alua_lu_gp_s *core_alua_get_lu_gp_by_name (struct se_device_s *, const char *);
+extern void core_alua_attach_lu_gp (struct se_device_s *, struct t10_alua_lu_gp_s *);
+extern void __core_alua_put_lu_gp (struct se_device_s *, int);
+extern void core_alua_put_lu_gp (struct se_device_s *, int);
+extern struct t10_alua_tg_pt_gp_s *core_alua_allocate_tg_pt_gp (const char *);
+extern void core_alua_free_tg_pt_gp (struct t10_alua_tg_pt_gp_s *);
+extern struct t10_alua_tg_pt_gp_s *core_alua_get_tg_pt_gp_by_name (struct se_port_s *, const char *);
+extern void core_alua_attach_tg_pt_gp (struct se_port_s *, struct t10_alua_tg_pt_gp_s *);
+extern void __core_alua_put_tg_pt_gp (struct se_port_s *, int);
+extern void core_alua_put_tg_pt_gp (struct se_port_s *, int);
+extern ssize_t core_alua_show_tg_pt_gp_info (struct se_port_s *, char *);
+extern ssize_t core_alua_store_tg_pt_gp_info (struct se_port_s *, const char *, size_t);
extern int core_setup_alua (struct se_device_s *);

#endif // TARGET_CORE_ALUA_H
diff --git a/drivers/lio-core/target_core_base.h b/drivers/lio-core/target_core_base.h
index a5208e8..08859a3 100644
--- a/drivers/lio-core/target_core_base.h
+++ b/drivers/lio-core/target_core_base.h
@@ -189,6 +189,28 @@ typedef struct t10_alua_s {
t10_alua_index_t alua_type;
} ____cacheline_aligned t10_alua_t;

+typedef struct t10_alua_lu_gp_s {
+ u16 lu_gp_id;
+ int lu_gp_alua_access_state;
+ u32 lu_gp_members;
+ atomic_t lu_gp_ref_cnt;
+ spinlock_t lu_gp_ref_lock;
+ struct config_group lu_gp_group;
+ struct list_head lu_gp_list;
+ struct list_head lu_gp_ref_list;
+} ____cacheline_aligned t10_alua_lu_gp_t;
+
+typedef struct t10_alua_tg_pt_gp_s {
+ u16 tg_pt_gp_id;
+ int tg_pt_gp_alua_access_state;
+ u32 tg_pt_gp_members;
+ atomic_t tg_pt_gp_ref_cnt;
+ spinlock_t tg_pt_gp_ref_lock;
+ struct config_group tg_pt_gp_group;
+ struct list_head tg_pt_gp_list;
+ struct list_head tg_pt_gp_ref_list;
+} ____cacheline_aligned t10_alua_tg_pt_gp_t;
+
typedef struct t10_evpd_s {
unsigned char device_identifier[INQUIRY_EVPD_DEVICE_IDENTIFIER_LEN];
int protocol_identifier_set;
@@ -580,12 +602,15 @@ typedef struct se_device_s {
spinlock_t execute_task_lock;
spinlock_t state_task_lock;
spinlock_t dev_reservation_lock;
+ spinlock_t dev_alua_lock;
spinlock_t dev_state_lock;
spinlock_t dev_status_lock;
spinlock_t dev_status_thr_lock;
spinlock_t se_port_lock;
struct se_node_acl_s *dev_reserved_node_acl; /* Used for legacy SPC-2 reservationsa */
+ struct t10_alua_lu_gp_s *dev_alua_lu_gp; /* Used for ALUA Logical Unit Groups */
struct t10_pr_registration_s *dev_pr_res_holder; /* Used for SPC-3 Persistent Reservations */
+ struct list_head dev_lu_gp_list;
struct list_head dev_sep_list;
struct timer_list dev_status_timer;
struct task_struct *process_thread; /* Pointer to descriptor for processing thread */
@@ -672,9 +697,12 @@ typedef struct se_port_s {
u32 sep_index;
scsi_port_stats_t sep_stats;
#endif
+ spinlock_t sep_alua_lock;
+ struct t10_alua_tg_pt_gp_s *sep_alua_tg_pt_gp; /* Used for ALUA Target Port Groups */
struct se_lun_s *sep_lun;
struct se_portal_group_s *sep_tpg;
struct list_head sep_list;
+ struct list_head sep_tg_pt_gp_list;
} ____cacheline_aligned se_port_t;

typedef struct se_portal_group_s {
@@ -695,11 +723,25 @@ typedef struct se_portal_group_s {
#define TPG_TFO(se_tpg) ((struct target_core_fabric_ops *)(se_tpg)->se_tpg_tfo)

typedef struct se_global_s {
+ u16 alua_lu_gps_counter;
+ u16 alua_tg_pt_gps_counter;
u32 in_shutdown;
+ u32 alua_lu_gps_count;
+ u32 alua_tg_pt_gps_count;
+ struct config_group target_core_hbagroup;
+ struct config_group alua_group;
+ struct config_group alua_lu_gps_group;
+ struct config_group alua_tg_pt_gps_group;
+ struct list_head g_lu_gps_list;
+ struct list_head g_tg_pt_gps_list;
struct list_head g_se_tpg_list;
struct se_plugin_class_s *plugin_class_list;
se_hba_t *hba_list;
+ t10_alua_lu_gp_t *default_lu_gp;
+ t10_alua_tg_pt_gp_t *default_tg_pt_gp;
spinlock_t hba_lock;
+ spinlock_t lu_gps_lock;
+ spinlock_t tg_pt_gps_lock;
spinlock_t plugin_class_lock;
#ifdef DEBUG_DEV
spinlock_t debug_dev_lock;
--
1.5.4.1



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/