aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
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
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')
-rw-r--r--net/tipc/bearer.c12
-rw-r--r--net/tipc/link.c31
-rw-r--r--net/tipc/link.h2
-rw-r--r--net/tipc/node.c8
4 files changed, 36 insertions, 17 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 4931eea65797..60caa45e5a41 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -51,7 +51,7 @@ static struct tipc_media * const media_info_array[] = {
51 51
52struct tipc_bearer tipc_bearers[MAX_BEARERS]; 52struct tipc_bearer tipc_bearers[MAX_BEARERS];
53 53
54static void bearer_disable(struct tipc_bearer *b_ptr); 54static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
55 55
56/** 56/**
57 * tipc_media_find - locates specified media object by name 57 * tipc_media_find - locates specified media object by name
@@ -331,7 +331,7 @@ restart:
331 331
332 res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr, disc_domain); 332 res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr, disc_domain);
333 if (res) { 333 if (res) {
334 bearer_disable(b_ptr); 334 bearer_disable(b_ptr, false);
335 pr_warn("Bearer <%s> rejected, discovery object creation failed\n", 335 pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
336 name); 336 name);
337 goto exit; 337 goto exit;
@@ -363,14 +363,14 @@ static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
363 * 363 *
364 * Note: This routine assumes caller holds tipc_net_lock. 364 * Note: This routine assumes caller holds tipc_net_lock.
365 */ 365 */
366static void bearer_disable(struct tipc_bearer *b_ptr) 366static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
367{ 367{
368 struct tipc_link_req *temp_req; 368 struct tipc_link_req *temp_req;
369 369
370 pr_info("Disabling bearer <%s>\n", b_ptr->name); 370 pr_info("Disabling bearer <%s>\n", b_ptr->name);
371 spin_lock_bh(&b_ptr->lock); 371 spin_lock_bh(&b_ptr->lock);
372 b_ptr->media->disable_media(b_ptr); 372 b_ptr->media->disable_media(b_ptr);
373 tipc_link_delete_list(b_ptr->identity); 373 tipc_link_delete_list(b_ptr->identity, shutting_down);
374 temp_req = b_ptr->link_req; 374 temp_req = b_ptr->link_req;
375 b_ptr->link_req = NULL; 375 b_ptr->link_req = NULL;
376 spin_unlock_bh(&b_ptr->lock); 376 spin_unlock_bh(&b_ptr->lock);
@@ -392,7 +392,7 @@ int tipc_disable_bearer(const char *name)
392 pr_warn("Attempt to disable unknown bearer <%s>\n", name); 392 pr_warn("Attempt to disable unknown bearer <%s>\n", name);
393 res = -EINVAL; 393 res = -EINVAL;
394 } else { 394 } else {
395 bearer_disable(b_ptr); 395 bearer_disable(b_ptr, false);
396 res = 0; 396 res = 0;
397 } 397 }
398 write_unlock_bh(&tipc_net_lock); 398 write_unlock_bh(&tipc_net_lock);
@@ -612,6 +612,6 @@ void tipc_bearer_stop(void)
612 612
613 for (i = 0; i < MAX_BEARERS; i++) { 613 for (i = 0; i < MAX_BEARERS; i++) {
614 if (tipc_bearers[i].active) 614 if (tipc_bearers[i].active)
615 bearer_disable(&tipc_bearers[i]); 615 bearer_disable(&tipc_bearers[i], true);
616 } 616 }
617} 617}
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;
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 3340fc1fc299..45b9cd071c41 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -214,7 +214,7 @@ struct tipc_port;
214struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, 214struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
215 struct tipc_bearer *b_ptr, 215 struct tipc_bearer *b_ptr,
216 const struct tipc_media_addr *media_addr); 216 const struct tipc_media_addr *media_addr);
217void tipc_link_delete_list(unsigned int bearer_id); 217void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down);
218void tipc_link_failover_send_queue(struct tipc_link *l_ptr); 218void tipc_link_failover_send_queue(struct tipc_link *l_ptr);
219void tipc_link_dup_send_queue(struct tipc_link *l_ptr, 219void tipc_link_dup_send_queue(struct tipc_link *l_ptr,
220 struct tipc_link *dest); 220 struct tipc_link *dest);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index efe4d41bf11b..833324b73fe1 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -249,7 +249,13 @@ void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
249 249
250void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) 250void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
251{ 251{
252 n_ptr->links[l_ptr->b_ptr->identity] = NULL; 252 int i;
253
254 for (i = 0; i < MAX_BEARERS; i++) {
255 if (l_ptr == n_ptr->links[i])
256 break;
257 }
258 n_ptr->links[i] = NULL;
253 atomic_dec(&tipc_num_links); 259 atomic_dec(&tipc_num_links);
254 n_ptr->link_cnt--; 260 n_ptr->link_cnt--;
255} 261}