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>
u32 index;
struct ft_lport_acl *lport_acl;
struct ft_tport *tport; /* active tport or NULL */
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;
struct list_head lun_list; /* head of LUNs */
struct se_portal_group se_tpg;
struct workqueue_struct *workqueue;
struct ft_lport_acl {
u64 wwpn;
char name[FT_NAMELEN];
struct ft_lport_acl {
u64 wwpn;
char name[FT_NAMELEN];
- struct list_head tpg_list;
struct se_wwn fc_lport_wwn;
};
struct se_wwn fc_lport_wwn;
};
if (index > UINT_MAX)
return NULL;
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)
lacl = container_of(wwn, struct ft_lport_acl, fc_lport_wwn);
tpg = kzalloc(sizeof(*tpg), GFP_KERNEL);
if (!tpg)
tpg->workqueue = wq;
mutex_lock(&ft_lport_lock);
tpg->workqueue = wq;
mutex_lock(&ft_lport_lock);
- list_add_tail(&tpg->list, &lacl->tpg_list);
mutex_unlock(&ft_lport_lock);
return &tpg->se_tpg;
mutex_unlock(&ft_lport_lock);
return &tpg->se_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);
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));
pr_debug("del tpg %s\n",
config_item_name(&tpg->se_tpg.tpg_group.cg_item));
synchronize_rcu();
mutex_lock(&ft_lport_lock);
synchronize_rcu();
mutex_lock(&ft_lport_lock);
if (tpg->tport) {
tpg->tport->tpg = NULL;
tpg->tport = NULL;
if (tpg->tport) {
tpg->tport->tpg = NULL;
tpg->tport = NULL;
struct ft_tpg *ft_lport_find_tpg(struct fc_lport *lport)
{
struct ft_lport_acl *lacl;
struct ft_tpg *ft_lport_find_tpg(struct fc_lport *lport)
{
struct ft_lport_acl *lacl;
list_for_each_entry(lacl, &ft_lport_list, list) {
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;
if (!lacl)
return NULL;
lacl->wwpn = wwpn;
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) {
mutex_lock(&ft_lport_lock);
list_for_each_entry(old_lacl, &ft_lport_list, list) {