aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/node.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2015-02-03 08:59:19 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-04 19:09:31 -0500
commitb45db71b525d75e520d7ef46c796f49c5d26c07c (patch)
treee19c1c7f6bc27d63e28a1315b7b19ce1d099e02d /net/tipc/node.c
parent7d24dcdb3f3132e0ec36f19c49bd004bc874b8aa (diff)
tipc: eliminate race during node creation
Instances of struct node are created in the function tipc_disc_rcv() under the assumption that there is no race between received discovery messages arriving from the same node. This assumption is wrong. When we use more than one bearer, it is possible that discovery messages from the same node arrive at the same moment, resulting in creation of two instances of struct tipc_node. This may later cause confusion during link establishment, and may result in one of the links never becoming activated. We fix this by making lookup and potential creation of nodes atomic. Instead of first looking up the node, and in case of failure, create it, we now start with looking up the node inside node_link_create(), and return a reference to that one if found. Otherwise, we go ahead and create the node as we did before. Reviewed-by: Erik Hugne <erik.hugne@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/node.c')
-rw-r--r--net/tipc/node.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index d4cb8c127063..842bd7ad4b17 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -96,14 +96,14 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)
96 struct tipc_node *n_ptr, *temp_node; 96 struct tipc_node *n_ptr, *temp_node;
97 97
98 spin_lock_bh(&tn->node_list_lock); 98 spin_lock_bh(&tn->node_list_lock);
99 99 n_ptr = tipc_node_find(net, addr);
100 if (n_ptr)
101 goto exit;
100 n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); 102 n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC);
101 if (!n_ptr) { 103 if (!n_ptr) {
102 spin_unlock_bh(&tn->node_list_lock);
103 pr_warn("Node creation failed, no memory\n"); 104 pr_warn("Node creation failed, no memory\n");
104 return NULL; 105 goto exit;
105 } 106 }
106
107 n_ptr->addr = addr; 107 n_ptr->addr = addr;
108 n_ptr->net = net; 108 n_ptr->net = net;
109 spin_lock_init(&n_ptr->lock); 109 spin_lock_init(&n_ptr->lock);
@@ -123,9 +123,8 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr)
123 list_add_tail_rcu(&n_ptr->list, &temp_node->list); 123 list_add_tail_rcu(&n_ptr->list, &temp_node->list);
124 n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN; 124 n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN;
125 n_ptr->signature = INVALID_NODE_SIG; 125 n_ptr->signature = INVALID_NODE_SIG;
126
127 tn->num_nodes++; 126 tn->num_nodes++;
128 127exit:
129 spin_unlock_bh(&tn->node_list_lock); 128 spin_unlock_bh(&tn->node_list_lock);
130 return n_ptr; 129 return n_ptr;
131} 130}