aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/iscsi
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-02-19 00:01:02 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2013-02-19 20:58:12 -0500
commit6e5459353de4ac80924e94fafa8b3e31a086c5dd (patch)
tree18066f37c9070b23b30754052d113b2f6fb9022c /drivers/target/iscsi
parent05b9689245c1b2f0dea38c1cb4882810ce3adda8 (diff)
iscsi-target: Enforce individual network portal export once per TargetName
This patch enforces individual network portal export on a once per TargetName basis, thus preventing a network portal from being exported multiple times across multiple TargetPortalGroups in a single TargetName instance. This is done in iscsit_tpg_check_network_portal() by walking tiqn->tiqn_tpg_list and tpg->tpg_gnp_list using iscsit_check_np_match() looking for an existing network portal mapping from iscsit_tpg_add_network_portal() context, but only when no pre-existing tpg_np_parent pointer is present. Reported-by: Andy Grover <agrover@redhat.com> Tested-by: Andy Grover <agrover@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/iscsi')
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index de9ea32b6104..ee8f8c66248d 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -422,6 +422,35 @@ struct iscsi_tpg_np *iscsit_tpg_locate_child_np(
422 return NULL; 422 return NULL;
423} 423}
424 424
425static bool iscsit_tpg_check_network_portal(
426 struct iscsi_tiqn *tiqn,
427 struct __kernel_sockaddr_storage *sockaddr,
428 int network_transport)
429{
430 struct iscsi_portal_group *tpg;
431 struct iscsi_tpg_np *tpg_np;
432 struct iscsi_np *np;
433 bool match = false;
434
435 spin_lock(&tiqn->tiqn_tpg_lock);
436 list_for_each_entry(tpg, &tiqn->tiqn_tpg_list, tpg_list) {
437
438 spin_lock(&tpg->tpg_np_lock);
439 list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) {
440 np = tpg_np->tpg_np;
441
442 match = iscsit_check_np_match(sockaddr, np,
443 network_transport);
444 if (match == true)
445 break;
446 }
447 spin_unlock(&tpg->tpg_np_lock);
448 }
449 spin_unlock(&tiqn->tiqn_tpg_lock);
450
451 return match;
452}
453
425struct iscsi_tpg_np *iscsit_tpg_add_network_portal( 454struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
426 struct iscsi_portal_group *tpg, 455 struct iscsi_portal_group *tpg,
427 struct __kernel_sockaddr_storage *sockaddr, 456 struct __kernel_sockaddr_storage *sockaddr,
@@ -432,6 +461,16 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
432 struct iscsi_np *np; 461 struct iscsi_np *np;
433 struct iscsi_tpg_np *tpg_np; 462 struct iscsi_tpg_np *tpg_np;
434 463
464 if (!tpg_np_parent) {
465 if (iscsit_tpg_check_network_portal(tpg->tpg_tiqn, sockaddr,
466 network_transport) == true) {
467 pr_err("Network Portal: %s already exists on a"
468 " different TPG on %s\n", ip_str,
469 tpg->tpg_tiqn->tiqn);
470 return ERR_PTR(-EEXIST);
471 }
472 }
473
435 tpg_np = kzalloc(sizeof(struct iscsi_tpg_np), GFP_KERNEL); 474 tpg_np = kzalloc(sizeof(struct iscsi_tpg_np), GFP_KERNEL);
436 if (!tpg_np) { 475 if (!tpg_np) {
437 pr_err("Unable to allocate memory for" 476 pr_err("Unable to allocate memory for"