aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2010-08-17 07:00:16 -0400
committerDavid S. Miller <davem@davemloft.net>2010-08-17 20:32:00 -0400
commit5a68d5ee000bb784c4856391b4861739c8bbd341 (patch)
treebf00540edd8adae24f3805b08d53ba37af6366d7 /net/tipc
parent564e83b51a12b794e3f63a2d872398e1ee21616f (diff)
tipc: Prevent missing name table entries when link flip-flops rapidly
Ensure that TIPC does not re-establish communication with a neighboring node until it has finished updating all data structures containing information about that node to reflect the earlier loss of contact. Previously, it was possible for TIPC to perform its purge of name table entries relating to the node once contact had already been re-established, resulting in the unwanted removal of valid name table entries. Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/discover.c8
-rw-r--r--net/tipc/link.c11
-rw-r--r--net/tipc/node.c19
-rw-r--r--net/tipc/node.h2
4 files changed, 39 insertions, 1 deletions
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index fc1fcf5e6b53..f28d1ae93125 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -203,6 +203,14 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)
203 return; 203 return;
204 } 204 }
205 spin_lock_bh(&n_ptr->lock); 205 spin_lock_bh(&n_ptr->lock);
206
207 /* Don't talk to neighbor during cleanup after last session */
208
209 if (n_ptr->cleanup_required) {
210 spin_unlock_bh(&n_ptr->lock);
211 return;
212 }
213
206 link = n_ptr->links[b_ptr->identity]; 214 link = n_ptr->links[b_ptr->identity];
207 if (!link) { 215 if (!link) {
208 dbg("creating link\n"); 216 dbg("creating link\n");
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 9d18c9b7638b..a6a3102bb4d6 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1869,13 +1869,22 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
1869 goto cont; 1869 goto cont;
1870 } 1870 }
1871 1871
1872 /* Locate unicast link endpoint that should handle message */ 1872 /* Locate neighboring node that sent message */
1873 1873
1874 n_ptr = tipc_node_find(msg_prevnode(msg)); 1874 n_ptr = tipc_node_find(msg_prevnode(msg));
1875 if (unlikely(!n_ptr)) 1875 if (unlikely(!n_ptr))
1876 goto cont; 1876 goto cont;
1877 tipc_node_lock(n_ptr); 1877 tipc_node_lock(n_ptr);
1878 1878
1879 /* Don't talk to neighbor during cleanup after last session */
1880
1881 if (n_ptr->cleanup_required) {
1882 tipc_node_unlock(n_ptr);
1883 goto cont;
1884 }
1885
1886 /* Locate unicast link endpoint that should handle message */
1887
1879 l_ptr = n_ptr->links[b_ptr->identity]; 1888 l_ptr = n_ptr->links[b_ptr->identity];
1880 if (unlikely(!l_ptr)) { 1889 if (unlikely(!l_ptr)) {
1881 tipc_node_unlock(n_ptr); 1890 tipc_node_unlock(n_ptr);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 940851797615..b702c7bf580f 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -383,6 +383,20 @@ static void node_established_contact(struct tipc_node *n_ptr)
383 tipc_highest_allowed_slave); 383 tipc_highest_allowed_slave);
384} 384}
385 385
386static void node_cleanup_finished(unsigned long node_addr)
387{
388 struct tipc_node *n_ptr;
389
390 read_lock_bh(&tipc_net_lock);
391 n_ptr = tipc_node_find(node_addr);
392 if (n_ptr) {
393 tipc_node_lock(n_ptr);
394 n_ptr->cleanup_required = 0;
395 tipc_node_unlock(n_ptr);
396 }
397 read_unlock_bh(&tipc_net_lock);
398}
399
386static void node_lost_contact(struct tipc_node *n_ptr) 400static void node_lost_contact(struct tipc_node *n_ptr)
387{ 401{
388 struct cluster *c_ptr; 402 struct cluster *c_ptr;
@@ -457,6 +471,11 @@ static void node_lost_contact(struct tipc_node *n_ptr)
457 tipc_k_signal((Handler)ns->handle_node_down, 471 tipc_k_signal((Handler)ns->handle_node_down,
458 (unsigned long)ns->usr_handle); 472 (unsigned long)ns->usr_handle);
459 } 473 }
474
475 /* Prevent re-contact with node until all cleanup is done */
476
477 n_ptr->cleanup_required = 1;
478 tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr);
460} 479}
461 480
462/** 481/**
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 6f990da5d143..45f3db3a595d 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -52,6 +52,7 @@
52 * @active_links: pointers to active links to node 52 * @active_links: pointers to active links to node
53 * @links: pointers to all links to node 53 * @links: pointers to all links to node
54 * @working_links: number of working links to node (both active and standby) 54 * @working_links: number of working links to node (both active and standby)
55 * @cleanup_required: non-zero if cleaning up after a prior loss of contact
55 * @link_cnt: number of links to node 56 * @link_cnt: number of links to node
56 * @permit_changeover: non-zero if node has redundant links to this system 57 * @permit_changeover: non-zero if node has redundant links to this system
57 * @routers: bitmap (used for multicluster communication) 58 * @routers: bitmap (used for multicluster communication)
@@ -78,6 +79,7 @@ struct tipc_node {
78 struct link *links[MAX_BEARERS]; 79 struct link *links[MAX_BEARERS];
79 int link_cnt; 80 int link_cnt;
80 int working_links; 81 int working_links;
82 int cleanup_required;
81 int permit_changeover; 83 int permit_changeover;
82 u32 routers[512/32]; 84 u32 routers[512/32];
83 int last_router; 85 int last_router;