aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/discover.c9
-rw-r--r--net/tipc/link.c83
-rw-r--r--net/tipc/link.h3
-rw-r--r--net/tipc/node.c15
4 files changed, 65 insertions, 45 deletions
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 5b40cb89ff0a..a580a40d0208 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/discover.c 2 * net/tipc/discover.c
3 * 3 *
4 * Copyright (c) 2003-2006, 2014, Ericsson AB 4 * Copyright (c) 2003-2006, 2014-2015, Ericsson AB
5 * Copyright (c) 2005-2006, 2010-2011, Wind River Systems 5 * Copyright (c) 2005-2006, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -47,7 +47,6 @@
47/* indicates no timer in use */ 47/* indicates no timer in use */
48#define TIPC_LINK_REQ_INACTIVE 0xffffffff 48#define TIPC_LINK_REQ_INACTIVE 0xffffffff
49 49
50
51/** 50/**
52 * struct tipc_link_req - information about an ongoing link setup request 51 * struct tipc_link_req - information about an ongoing link setup request
53 * @bearer_id: identity of bearer issuing requests 52 * @bearer_id: identity of bearer issuing requests
@@ -163,13 +162,9 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
163 if (!tipc_in_scope(bearer->domain, onode)) 162 if (!tipc_in_scope(bearer->domain, onode))
164 return; 163 return;
165 164
166 /* Locate, or if necessary, create, node: */ 165 node = tipc_node_create(net, onode);
167 node = tipc_node_find(net, onode);
168 if (!node)
169 node = tipc_node_create(net, onode);
170 if (!node) 166 if (!node)
171 return; 167 return;
172
173 tipc_node_lock(node); 168 tipc_node_lock(node);
174 link = node->links[bearer->identity]; 169 link = node->links[bearer->identity];
175 170
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2846ad802e43..77c7ccd492b5 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -127,6 +127,21 @@ static unsigned int align(unsigned int i)
127 return (i + 3) & ~3u; 127 return (i + 3) & ~3u;
128} 128}
129 129
130static void tipc_link_release(struct kref *kref)
131{
132 kfree(container_of(kref, struct tipc_link, ref));
133}
134
135static void tipc_link_get(struct tipc_link *l_ptr)
136{
137 kref_get(&l_ptr->ref);
138}
139
140static void tipc_link_put(struct tipc_link *l_ptr)
141{
142 kref_put(&l_ptr->ref, tipc_link_release);
143}
144
130static void link_init_max_pkt(struct tipc_link *l_ptr) 145static void link_init_max_pkt(struct tipc_link *l_ptr)
131{ 146{
132 struct tipc_node *node = l_ptr->owner; 147 struct tipc_node *node = l_ptr->owner;
@@ -222,11 +237,13 @@ static void link_timeout(unsigned long data)
222 tipc_link_push_packets(l_ptr); 237 tipc_link_push_packets(l_ptr);
223 238
224 tipc_node_unlock(l_ptr->owner); 239 tipc_node_unlock(l_ptr->owner);
240 tipc_link_put(l_ptr);
225} 241}
226 242
227static void link_set_timer(struct tipc_link *link, unsigned long time) 243static void link_set_timer(struct tipc_link *link, unsigned long time)
228{ 244{
229 mod_timer(&link->timer, jiffies + time); 245 if (!mod_timer(&link->timer, jiffies + time))
246 tipc_link_get(link);
230} 247}
231 248
232/** 249/**
@@ -267,7 +284,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
267 pr_warn("Link creation failed, no memory\n"); 284 pr_warn("Link creation failed, no memory\n");
268 return NULL; 285 return NULL;
269 } 286 }
270 287 kref_init(&l_ptr->ref);
271 l_ptr->addr = peer; 288 l_ptr->addr = peer;
272 if_name = strchr(b_ptr->name, ':') + 1; 289 if_name = strchr(b_ptr->name, ':') + 1;
273 sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:unknown", 290 sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:unknown",
@@ -305,46 +322,48 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
305 skb_queue_head_init(&l_ptr->waiting_sks); 322 skb_queue_head_init(&l_ptr->waiting_sks);
306 323
307 link_reset_statistics(l_ptr); 324 link_reset_statistics(l_ptr);
308
309 tipc_node_attach_link(n_ptr, l_ptr); 325 tipc_node_attach_link(n_ptr, l_ptr);
310
311 setup_timer(&l_ptr->timer, link_timeout, (unsigned long)l_ptr); 326 setup_timer(&l_ptr->timer, link_timeout, (unsigned long)l_ptr);
312
313 link_state_event(l_ptr, STARTING_EVT); 327 link_state_event(l_ptr, STARTING_EVT);
314 328
315 return l_ptr; 329 return l_ptr;
316} 330}
317 331
332/**
333 * link_delete - Conditional deletion of link.
334 * If timer still running, real delete is done when it expires
335 * @link: link to be deleted
336 */
337void tipc_link_delete(struct tipc_link *link)
338{
339 tipc_link_reset_fragments(link);
340 tipc_node_detach_link(link->owner, link);
341 tipc_link_put(link);
342}
343
318void tipc_link_delete_list(struct net *net, unsigned int bearer_id, 344void tipc_link_delete_list(struct net *net, unsigned int bearer_id,
319 bool shutting_down) 345 bool shutting_down)
320{ 346{
321 struct tipc_net *tn = net_generic(net, tipc_net_id); 347 struct tipc_net *tn = net_generic(net, tipc_net_id);
322 struct tipc_link *l_ptr; 348 struct tipc_link *link;
323 struct tipc_node *n_ptr; 349 struct tipc_node *node;
324 350
325 rcu_read_lock(); 351 rcu_read_lock();
326 list_for_each_entry_rcu(n_ptr, &tn->node_list, list) { 352 list_for_each_entry_rcu(node, &tn->node_list, list) {
327 tipc_node_lock(n_ptr); 353 tipc_node_lock(node);
328 l_ptr = n_ptr->links[bearer_id]; 354 link = node->links[bearer_id];
329 if (l_ptr) { 355 if (!link) {
330 tipc_link_reset(l_ptr); 356 tipc_node_unlock(node);
331 if (shutting_down || !tipc_node_is_up(n_ptr)) {
332 tipc_node_detach_link(l_ptr->owner, l_ptr);
333 tipc_link_reset_fragments(l_ptr);
334 tipc_node_unlock(n_ptr);
335
336 /* Nobody else can access this link now: */
337 del_timer_sync(&l_ptr->timer);
338 kfree(l_ptr);
339 } else {
340 /* Detach/delete when failover is finished: */
341 l_ptr->flags |= LINK_STOPPED;
342 tipc_node_unlock(n_ptr);
343 del_timer_sync(&l_ptr->timer);
344 }
345 continue; 357 continue;
346 } 358 }
347 tipc_node_unlock(n_ptr); 359 tipc_link_reset(link);
360 if (del_timer(&link->timer))
361 tipc_link_put(link);
362 link->flags |= LINK_STOPPED;
363 /* Delete link now, or when failover is finished: */
364 if (shutting_down || !tipc_node_is_up(node))
365 tipc_link_delete(link);
366 tipc_node_unlock(node);
348 } 367 }
349 rcu_read_unlock(); 368 rcu_read_unlock();
350} 369}
@@ -630,7 +649,9 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
630 break; 649 break;
631 case STARTING_EVT: 650 case STARTING_EVT:
632 l_ptr->flags |= LINK_STARTED; 651 l_ptr->flags |= LINK_STARTED;
633 /* fall through */ 652 l_ptr->fsm_msg_cnt++;
653 link_set_timer(l_ptr, cont_intv);
654 break;
634 case TIMEOUT_EVT: 655 case TIMEOUT_EVT:
635 tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); 656 tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0, 0);
636 l_ptr->fsm_msg_cnt++; 657 l_ptr->fsm_msg_cnt++;
@@ -1837,10 +1858,8 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr,
1837 } 1858 }
1838 } 1859 }
1839exit: 1860exit:
1840 if ((l_ptr->exp_msg_count == 0) && (l_ptr->flags & LINK_STOPPED)) { 1861 if ((!l_ptr->exp_msg_count) && (l_ptr->flags & LINK_STOPPED))
1841 tipc_node_detach_link(l_ptr->owner, l_ptr); 1862 tipc_link_delete(l_ptr);
1842 kfree(l_ptr);
1843 }
1844 return buf; 1863 return buf;
1845} 1864}
1846 1865
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 9df7fa4d3bdd..3e3432b3044e 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -103,6 +103,7 @@ struct tipc_stats {
103 * @media_addr: media address to use when sending messages over link 103 * @media_addr: media address to use when sending messages over link
104 * @timer: link timer 104 * @timer: link timer
105 * @owner: pointer to peer node 105 * @owner: pointer to peer node
106 * @refcnt: reference counter for permanent references (owner node & timer)
106 * @flags: execution state flags for link endpoint instance 107 * @flags: execution state flags for link endpoint instance
107 * @checkpoint: reference point for triggering link continuity checking 108 * @checkpoint: reference point for triggering link continuity checking
108 * @peer_session: link session # being used by peer end of link 109 * @peer_session: link session # being used by peer end of link
@@ -142,6 +143,7 @@ struct tipc_link {
142 struct tipc_media_addr media_addr; 143 struct tipc_media_addr media_addr;
143 struct timer_list timer; 144 struct timer_list timer;
144 struct tipc_node *owner; 145 struct tipc_node *owner;
146 struct kref ref;
145 147
146 /* Management and link supervision data */ 148 /* Management and link supervision data */
147 unsigned int flags; 149 unsigned int flags;
@@ -200,6 +202,7 @@ struct tipc_port;
200struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, 202struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
201 struct tipc_bearer *b_ptr, 203 struct tipc_bearer *b_ptr,
202 const struct tipc_media_addr *media_addr); 204 const struct tipc_media_addr *media_addr);
205void tipc_link_delete(struct tipc_link *link);
203void tipc_link_delete_list(struct net *net, unsigned int bearer_id, 206void tipc_link_delete_list(struct net *net, unsigned int bearer_id,
204 bool shutting_down); 207 bool shutting_down);
205void tipc_link_failover_send_queue(struct tipc_link *l_ptr); 208void tipc_link_failover_send_queue(struct tipc_link *l_ptr);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index ee5d33cfcf80..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}
@@ -406,6 +405,10 @@ static void node_lost_contact(struct tipc_node *n_ptr)
406 l_ptr->reset_checkpoint = l_ptr->next_in_no; 405 l_ptr->reset_checkpoint = l_ptr->next_in_no;
407 l_ptr->exp_msg_count = 0; 406 l_ptr->exp_msg_count = 0;
408 tipc_link_reset_fragments(l_ptr); 407 tipc_link_reset_fragments(l_ptr);
408
409 /* Link marked for deletion after failover? => do it now */
410 if (l_ptr->flags & LINK_STOPPED)
411 tipc_link_delete(l_ptr);
409 } 412 }
410 413
411 n_ptr->action_flags &= ~TIPC_WAIT_OWN_LINKS_DOWN; 414 n_ptr->action_flags &= ~TIPC_WAIT_OWN_LINKS_DOWN;