aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2014-02-13 17:29:16 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-13 17:57:07 -0500
commit7d33939f475d403e79124e3143d7951dcfe8629f (patch)
treeebc054f8e172f038efd53cd977e78eb1ac3f78e6 /net/tipc/link.c
parenta5377831eb64c1b8a7b911dc79aec73a930e95da (diff)
tipc: delay delete of link when failover is needed
When a bearer is disabled, all its attached links are deleted. Ideally, we should do link failover to redundant links on other bearers, if there are any, in such cases. This would be consistent with current behavior when a link is reset, but not deleted. However, due to the complexity involved, and the (wrongly) perceived low demand for this feature, it was never implemented until now. We mark the doomed link for deletion with a new flag, but wait until the failover process is finished before we actually delete it. With the improved link tunnelling/failover code introduced earlier in this commit series, it is now easy to identify a spot in the code where the failover is finished and it is safe to delete the marked link. Moreover, the test for the flag and the deletion can be done synchronously, and outside the most time critical data path. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 663623c5896d..03075165665e 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -281,7 +281,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
281} 281}
282 282
283 283
284void tipc_link_delete_list(unsigned int bearer_id) 284void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down)
285{ 285{
286 struct tipc_link *l_ptr; 286 struct tipc_link *l_ptr;
287 struct tipc_node *n_ptr; 287 struct tipc_node *n_ptr;
@@ -291,12 +291,20 @@ void tipc_link_delete_list(unsigned int bearer_id)
291 l_ptr = n_ptr->links[bearer_id]; 291 l_ptr = n_ptr->links[bearer_id];
292 if (l_ptr) { 292 if (l_ptr) {
293 tipc_link_reset(l_ptr); 293 tipc_link_reset(l_ptr);
294 tipc_node_detach_link(n_ptr, l_ptr); 294 if (shutting_down || !tipc_node_is_up(n_ptr)) {
295 spin_unlock_bh(&n_ptr->lock); 295 tipc_node_detach_link(l_ptr->owner, l_ptr);
296 296 tipc_link_reset_fragments(l_ptr);
297 /* Nobody else can access this link now: */ 297 spin_unlock_bh(&n_ptr->lock);
298 del_timer_sync(&l_ptr->timer); 298
299 kfree(l_ptr); 299 /* Nobody else can access this link now: */
300 del_timer_sync(&l_ptr->timer);
301 kfree(l_ptr);
302 } else {
303 /* Detach/delete when failover is finished: */
304 l_ptr->flags |= LINK_STOPPED;
305 spin_unlock_bh(&n_ptr->lock);
306 del_timer_sync(&l_ptr->timer);
307 }
300 continue; 308 continue;
301 } 309 }
302 spin_unlock_bh(&n_ptr->lock); 310 spin_unlock_bh(&n_ptr->lock);
@@ -481,6 +489,9 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
481 struct tipc_link *other; 489 struct tipc_link *other;
482 u32 cont_intv = l_ptr->continuity_interval; 490 u32 cont_intv = l_ptr->continuity_interval;
483 491
492 if (l_ptr->flags & LINK_STOPPED)
493 return;
494
484 if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT)) 495 if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT))
485 return; /* Not yet. */ 496 return; /* Not yet. */
486 497
@@ -2167,8 +2178,11 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr,
2167 &buf); 2178 &buf);
2168 } 2179 }
2169 } 2180 }
2170
2171exit: 2181exit:
2182 if ((l_ptr->exp_msg_count == 0) && (l_ptr->flags & LINK_STOPPED)) {
2183 tipc_node_detach_link(l_ptr->owner, l_ptr);
2184 kfree(l_ptr);
2185 }
2172 return buf; 2186 return buf;
2173} 2187}
2174 2188
@@ -2201,7 +2215,6 @@ static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr,
2201 *buf = tipc_link_failover_rcv(l_ptr, t_buf); 2215 *buf = tipc_link_failover_rcv(l_ptr, t_buf);
2202 else 2216 else
2203 pr_warn("%sunknown tunnel pkt received\n", link_co_err); 2217 pr_warn("%sunknown tunnel pkt received\n", link_co_err);
2204
2205exit: 2218exit:
2206 kfree_skb(t_buf); 2219 kfree_skb(t_buf);
2207 return *buf != NULL; 2220 return *buf != NULL;