diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/discover.c | 9 | ||||
-rw-r--r-- | net/tipc/link.c | 83 | ||||
-rw-r--r-- | net/tipc/link.h | 3 | ||||
-rw-r--r-- | net/tipc/node.c | 15 |
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 | ||
130 | static void tipc_link_release(struct kref *kref) | ||
131 | { | ||
132 | kfree(container_of(kref, struct tipc_link, ref)); | ||
133 | } | ||
134 | |||
135 | static void tipc_link_get(struct tipc_link *l_ptr) | ||
136 | { | ||
137 | kref_get(&l_ptr->ref); | ||
138 | } | ||
139 | |||
140 | static void tipc_link_put(struct tipc_link *l_ptr) | ||
141 | { | ||
142 | kref_put(&l_ptr->ref, tipc_link_release); | ||
143 | } | ||
144 | |||
130 | static void link_init_max_pkt(struct tipc_link *l_ptr) | 145 | static 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 | ||
227 | static void link_set_timer(struct tipc_link *link, unsigned long time) | 243 | static 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 | */ | ||
337 | void 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 | |||
318 | void tipc_link_delete_list(struct net *net, unsigned int bearer_id, | 344 | void 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 | } |
1839 | exit: | 1860 | exit: |
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; | |||
200 | struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | 202 | struct 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); |
205 | void tipc_link_delete(struct tipc_link *link); | ||
203 | void tipc_link_delete_list(struct net *net, unsigned int bearer_id, | 206 | void tipc_link_delete_list(struct net *net, unsigned int bearer_id, |
204 | bool shutting_down); | 207 | bool shutting_down); |
205 | void tipc_link_failover_send_queue(struct tipc_link *l_ptr); | 208 | void 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 | 127 | exit: | |
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; |