From: Andy Grover <agrover@redhat.com>
Date: Fri, 4 Apr 2014 23:54:12 +0000 (-0700)
Subject: target/tcm_fc: Limit to 1 TPG per wwn
X-Git-Tag: v3.15-rc1~12^2~4
X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=d242c1d7d39bb50d2816a2834b84c420c3e7084e;p=users%2Fdwmw2%2Flinux.git

target/tcm_fc: Limit to 1 TPG per wwn

tcm_fc doesn't support multiple TPGs per wwn. For proof, see
ft_lport_find_tpg. Enforce this in the code.

Replace ft_lport_wwn.tpg_list with a single pointer. We can't fold ft_tpg
into ft_lport_wwn because they can have different lifetimes.

Signed-off-by: Andy Grover <agrover@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---

diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h
index aba6861c362b0..7290f8fb53f03 100644
--- a/drivers/target/tcm_fc/tcm_fc.h
+++ b/drivers/target/tcm_fc/tcm_fc.h
@@ -96,7 +96,6 @@ struct ft_tpg {
 	u32 index;
 	struct ft_lport_acl *lport_acl;
 	struct ft_tport *tport;		/* active tport or NULL */
-	struct list_head list;		/* linkage in ft_lport_acl tpg_list */
 	struct list_head lun_list;	/* head of LUNs */
 	struct se_portal_group se_tpg;
 	struct workqueue_struct *workqueue;
@@ -105,8 +104,8 @@ struct ft_tpg {
 struct ft_lport_acl {
 	u64 wwpn;
 	char name[FT_NAMELEN];
+	struct ft_tpg *tpg;
 	struct list_head list;
-	struct list_head tpg_list;
 	struct se_wwn fc_lport_wwn;
 };
 
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index 9c2da1ff886a2..ccfa328e03675 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -318,6 +318,11 @@ static struct se_portal_group *ft_add_tpg(
 	if (index > UINT_MAX)
 		return NULL;
 
+	if ((index != 1)) {
+		pr_err("Error, a single TPG=1 is used for HW port mappings\n");
+		return ERR_PTR(-ENOSYS);
+	}
+
 	lacl = container_of(wwn, struct ft_lport_acl, fc_lport_wwn);
 	tpg = kzalloc(sizeof(*tpg), GFP_KERNEL);
 	if (!tpg)
@@ -342,7 +347,7 @@ static struct se_portal_group *ft_add_tpg(
 	tpg->workqueue = wq;
 
 	mutex_lock(&ft_lport_lock);
-	list_add_tail(&tpg->list, &lacl->tpg_list);
+	lacl->tpg = tpg;
 	mutex_unlock(&ft_lport_lock);
 
 	return &tpg->se_tpg;
@@ -351,6 +356,7 @@ static struct se_portal_group *ft_add_tpg(
 static void ft_del_tpg(struct se_portal_group *se_tpg)
 {
 	struct ft_tpg *tpg = container_of(se_tpg, struct ft_tpg, se_tpg);
+	struct ft_lport_acl *lacl = tpg->lport_acl;
 
 	pr_debug("del tpg %s\n",
 		    config_item_name(&tpg->se_tpg.tpg_group.cg_item));
@@ -361,7 +367,8 @@ static void ft_del_tpg(struct se_portal_group *se_tpg)
 	synchronize_rcu();
 
 	mutex_lock(&ft_lport_lock);
-	list_del(&tpg->list);
+	lacl->tpg = NULL;
+
 	if (tpg->tport) {
 		tpg->tport->tpg = NULL;
 		tpg->tport = NULL;
@@ -381,14 +388,10 @@ static void ft_del_tpg(struct se_portal_group *se_tpg)
 struct ft_tpg *ft_lport_find_tpg(struct fc_lport *lport)
 {
 	struct ft_lport_acl *lacl;
-	struct ft_tpg *tpg;
 
 	list_for_each_entry(lacl, &ft_lport_list, list) {
-		if (lacl->wwpn == lport->wwpn) {
-			list_for_each_entry(tpg, &lacl->tpg_list, list)
-				return tpg; /* XXX for now return first entry */
-			return NULL;
-		}
+		if (lacl->wwpn == lport->wwpn)
+			return lacl->tpg;
 	}
 	return NULL;
 }
@@ -417,7 +420,6 @@ static struct se_wwn *ft_add_lport(
 	if (!lacl)
 		return NULL;
 	lacl->wwpn = wwpn;
-	INIT_LIST_HEAD(&lacl->tpg_list);
 
 	mutex_lock(&ft_lport_lock);
 	list_for_each_entry(old_lacl, &ft_lport_list, list) {