aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/link.c79
-rw-r--r--net/tipc/link.h2
2 files changed, 50 insertions, 31 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2846ad802e43..46aa59955299 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}
@@ -1837,10 +1856,8 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr,
1837 } 1856 }
1838 } 1857 }
1839exit: 1858exit:
1840 if ((l_ptr->exp_msg_count == 0) && (l_ptr->flags & LINK_STOPPED)) { 1859 if ((!l_ptr->exp_msg_count) && (l_ptr->flags & LINK_STOPPED))
1841 tipc_node_detach_link(l_ptr->owner, l_ptr); 1860 tipc_link_delete(l_ptr);
1842 kfree(l_ptr);
1843 }
1844 return buf; 1861 return buf;
1845} 1862}
1846 1863
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 9df7fa4d3bdd..f06b779c9f75 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;