diff options
author | Andy Grover <agrover@redhat.com> | 2014-04-04 19:54:12 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-04-11 18:30:50 -0400 |
commit | d242c1d7d39bb50d2816a2834b84c420c3e7084e (patch) | |
tree | d693093cca72b2e40b6b7d7a7861e44b753804fe | |
parent | b295e76900223e4b8e350d02f7b6801fe126d8d2 (diff) |
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>
-rw-r--r-- | drivers/target/tcm_fc/tcm_fc.h | 3 | ||||
-rw-r--r-- | drivers/target/tcm_fc/tfc_conf.c | 20 |
2 files changed, 12 insertions, 11 deletions
diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index aba6861c362b..7290f8fb53f0 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h | |||
@@ -96,7 +96,6 @@ struct ft_tpg { | |||
96 | u32 index; | 96 | u32 index; |
97 | struct ft_lport_acl *lport_acl; | 97 | struct ft_lport_acl *lport_acl; |
98 | struct ft_tport *tport; /* active tport or NULL */ | 98 | struct ft_tport *tport; /* active tport or NULL */ |
99 | struct list_head list; /* linkage in ft_lport_acl tpg_list */ | ||
100 | struct list_head lun_list; /* head of LUNs */ | 99 | struct list_head lun_list; /* head of LUNs */ |
101 | struct se_portal_group se_tpg; | 100 | struct se_portal_group se_tpg; |
102 | struct workqueue_struct *workqueue; | 101 | struct workqueue_struct *workqueue; |
@@ -105,8 +104,8 @@ struct ft_tpg { | |||
105 | struct ft_lport_acl { | 104 | struct ft_lport_acl { |
106 | u64 wwpn; | 105 | u64 wwpn; |
107 | char name[FT_NAMELEN]; | 106 | char name[FT_NAMELEN]; |
107 | struct ft_tpg *tpg; | ||
108 | struct list_head list; | 108 | struct list_head list; |
109 | struct list_head tpg_list; | ||
110 | struct se_wwn fc_lport_wwn; | 109 | struct se_wwn fc_lport_wwn; |
111 | }; | 110 | }; |
112 | 111 | ||
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c index 9c2da1ff886a..ccfa328e0367 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( | |||
318 | if (index > UINT_MAX) | 318 | if (index > UINT_MAX) |
319 | return NULL; | 319 | return NULL; |
320 | 320 | ||
321 | if ((index != 1)) { | ||
322 | pr_err("Error, a single TPG=1 is used for HW port mappings\n"); | ||
323 | return ERR_PTR(-ENOSYS); | ||
324 | } | ||
325 | |||
321 | lacl = container_of(wwn, struct ft_lport_acl, fc_lport_wwn); | 326 | lacl = container_of(wwn, struct ft_lport_acl, fc_lport_wwn); |
322 | tpg = kzalloc(sizeof(*tpg), GFP_KERNEL); | 327 | tpg = kzalloc(sizeof(*tpg), GFP_KERNEL); |
323 | if (!tpg) | 328 | if (!tpg) |
@@ -342,7 +347,7 @@ static struct se_portal_group *ft_add_tpg( | |||
342 | tpg->workqueue = wq; | 347 | tpg->workqueue = wq; |
343 | 348 | ||
344 | mutex_lock(&ft_lport_lock); | 349 | mutex_lock(&ft_lport_lock); |
345 | list_add_tail(&tpg->list, &lacl->tpg_list); | 350 | lacl->tpg = tpg; |
346 | mutex_unlock(&ft_lport_lock); | 351 | mutex_unlock(&ft_lport_lock); |
347 | 352 | ||
348 | return &tpg->se_tpg; | 353 | return &tpg->se_tpg; |
@@ -351,6 +356,7 @@ static struct se_portal_group *ft_add_tpg( | |||
351 | static void ft_del_tpg(struct se_portal_group *se_tpg) | 356 | static void ft_del_tpg(struct se_portal_group *se_tpg) |
352 | { | 357 | { |
353 | struct ft_tpg *tpg = container_of(se_tpg, struct ft_tpg, se_tpg); | 358 | struct ft_tpg *tpg = container_of(se_tpg, struct ft_tpg, se_tpg); |
359 | struct ft_lport_acl *lacl = tpg->lport_acl; | ||
354 | 360 | ||
355 | pr_debug("del tpg %s\n", | 361 | pr_debug("del tpg %s\n", |
356 | config_item_name(&tpg->se_tpg.tpg_group.cg_item)); | 362 | 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) | |||
361 | synchronize_rcu(); | 367 | synchronize_rcu(); |
362 | 368 | ||
363 | mutex_lock(&ft_lport_lock); | 369 | mutex_lock(&ft_lport_lock); |
364 | list_del(&tpg->list); | 370 | lacl->tpg = NULL; |
371 | |||
365 | if (tpg->tport) { | 372 | if (tpg->tport) { |
366 | tpg->tport->tpg = NULL; | 373 | tpg->tport->tpg = NULL; |
367 | tpg->tport = NULL; | 374 | tpg->tport = NULL; |
@@ -381,14 +388,10 @@ static void ft_del_tpg(struct se_portal_group *se_tpg) | |||
381 | struct ft_tpg *ft_lport_find_tpg(struct fc_lport *lport) | 388 | struct ft_tpg *ft_lport_find_tpg(struct fc_lport *lport) |
382 | { | 389 | { |
383 | struct ft_lport_acl *lacl; | 390 | struct ft_lport_acl *lacl; |
384 | struct ft_tpg *tpg; | ||
385 | 391 | ||
386 | list_for_each_entry(lacl, &ft_lport_list, list) { | 392 | list_for_each_entry(lacl, &ft_lport_list, list) { |
387 | if (lacl->wwpn == lport->wwpn) { | 393 | if (lacl->wwpn == lport->wwpn) |
388 | list_for_each_entry(tpg, &lacl->tpg_list, list) | 394 | return lacl->tpg; |
389 | return tpg; /* XXX for now return first entry */ | ||
390 | return NULL; | ||
391 | } | ||
392 | } | 395 | } |
393 | return NULL; | 396 | return NULL; |
394 | } | 397 | } |
@@ -417,7 +420,6 @@ static struct se_wwn *ft_add_lport( | |||
417 | if (!lacl) | 420 | if (!lacl) |
418 | return NULL; | 421 | return NULL; |
419 | lacl->wwpn = wwpn; | 422 | lacl->wwpn = wwpn; |
420 | INIT_LIST_HEAD(&lacl->tpg_list); | ||
421 | 423 | ||
422 | mutex_lock(&ft_lport_lock); | 424 | mutex_lock(&ft_lport_lock); |
423 | list_for_each_entry(old_lacl, &ft_lport_list, list) { | 425 | list_for_each_entry(old_lacl, &ft_lport_list, list) { |