Commit 2ecb0924 authored by Allan Stephens's avatar Allan Stephens Committed by David S. Miller

tipc: Prevent node object duplication due to simultaneous discovery

This patch ensures that the simultaneous discovery of the same
neighboring node by multiple interfaces does not cause TIPC to add
the node into its internal data structures more than once.
Signed-off-by: default avatarAllan Stephens <allan.stephens@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 59f0c452
...@@ -52,16 +52,40 @@ static void node_established_contact(struct node *n_ptr); ...@@ -52,16 +52,40 @@ static void node_established_contact(struct node *n_ptr);
struct node *tipc_nodes = NULL; /* sorted list of nodes within cluster */ struct node *tipc_nodes = NULL; /* sorted list of nodes within cluster */
static DEFINE_SPINLOCK(node_create_lock);
u32 tipc_own_tag = 0; u32 tipc_own_tag = 0;
/**
* tipc_node_create - create neighboring node
*
* Currently, this routine is called by neighbor discovery code, which holds
* net_lock for reading only. We must take node_create_lock to ensure a node
* isn't created twice if two different bearers discover the node at the same
* time. (It would be preferable to switch to holding net_lock in write mode,
* but this is a non-trivial change.)
*/
struct node *tipc_node_create(u32 addr) struct node *tipc_node_create(u32 addr)
{ {
struct cluster *c_ptr; struct cluster *c_ptr;
struct node *n_ptr; struct node *n_ptr;
struct node **curr_node; struct node **curr_node;
spin_lock_bh(&node_create_lock);
for (n_ptr = tipc_nodes; n_ptr; n_ptr = n_ptr->next) {
if (addr < n_ptr->addr)
break;
if (addr == n_ptr->addr) {
spin_unlock_bh(&node_create_lock);
return n_ptr;
}
}
n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC); n_ptr = kzalloc(sizeof(*n_ptr),GFP_ATOMIC);
if (!n_ptr) { if (!n_ptr) {
spin_unlock_bh(&node_create_lock);
warn("Node creation failed, no memory\n"); warn("Node creation failed, no memory\n");
return NULL; return NULL;
} }
...@@ -71,6 +95,7 @@ struct node *tipc_node_create(u32 addr) ...@@ -71,6 +95,7 @@ struct node *tipc_node_create(u32 addr)
c_ptr = tipc_cltr_create(addr); c_ptr = tipc_cltr_create(addr);
} }
if (!c_ptr) { if (!c_ptr) {
spin_unlock_bh(&node_create_lock);
kfree(n_ptr); kfree(n_ptr);
return NULL; return NULL;
} }
...@@ -91,6 +116,7 @@ struct node *tipc_node_create(u32 addr) ...@@ -91,6 +116,7 @@ struct node *tipc_node_create(u32 addr)
} }
} }
(*curr_node) = n_ptr; (*curr_node) = n_ptr;
spin_unlock_bh(&node_create_lock);
return n_ptr; return n_ptr;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment