tipc: Prevent missing name table entries when link flip-flops rapidly
authorAllan Stephens <allan.stephens@windriver.com>
Tue, 17 Aug 2010 11:00:16 +0000 (11:00 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 18 Aug 2010 00:32:00 +0000 (17:32 -0700)
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>
net/tipc/discover.c
net/tipc/link.c
net/tipc/node.c
net/tipc/node.h

index fc1fcf5e6b53625e4bc22ad29228af151de6288f..f28d1ae931257275607911d766405fdfa0b79c47 100644 (file)
@@ -203,6 +203,14 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)
                                return;
                }
                spin_lock_bh(&n_ptr->lock);
+
+               /* Don't talk to neighbor during cleanup after last session */
+
+               if (n_ptr->cleanup_required) {
+                       spin_unlock_bh(&n_ptr->lock);
+                       return;
+               }
+
                link = n_ptr->links[b_ptr->identity];
                if (!link) {
                        dbg("creating link\n");
index 9d18c9b7638bd879086c9ced39dea5ae22b09486..a6a3102bb4d6b9acb78d7e5a9dca11aca0ac5c54 100644 (file)
@@ -1869,13 +1869,22 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
                                goto cont;
                }
 
-               /* Locate unicast link endpoint that should handle message */
+               /* Locate neighboring node that sent message */
 
                n_ptr = tipc_node_find(msg_prevnode(msg));
                if (unlikely(!n_ptr))
                        goto cont;
                tipc_node_lock(n_ptr);
 
+               /* Don't talk to neighbor during cleanup after last session */
+
+               if (n_ptr->cleanup_required) {
+                       tipc_node_unlock(n_ptr);
+                       goto cont;
+               }
+
+               /* Locate unicast link endpoint that should handle message */
+
                l_ptr = n_ptr->links[b_ptr->identity];
                if (unlikely(!l_ptr)) {
                        tipc_node_unlock(n_ptr);
index 9408517976158b4a1c3e2b29c46a6b9727efcdc8..b702c7bf580f8d9a2a780d2a24c6cc8c46a630bb 100644 (file)
@@ -383,6 +383,20 @@ static void node_established_contact(struct tipc_node *n_ptr)
                                  tipc_highest_allowed_slave);
 }
 
+static void node_cleanup_finished(unsigned long node_addr)
+{
+       struct tipc_node *n_ptr;
+
+       read_lock_bh(&tipc_net_lock);
+       n_ptr = tipc_node_find(node_addr);
+       if (n_ptr) {
+               tipc_node_lock(n_ptr);
+               n_ptr->cleanup_required = 0;
+               tipc_node_unlock(n_ptr);
+       }
+       read_unlock_bh(&tipc_net_lock);
+}
+
 static void node_lost_contact(struct tipc_node *n_ptr)
 {
        struct cluster *c_ptr;
@@ -457,6 +471,11 @@ static void node_lost_contact(struct tipc_node *n_ptr)
                tipc_k_signal((Handler)ns->handle_node_down,
                              (unsigned long)ns->usr_handle);
        }
+
+       /* Prevent re-contact with node until all cleanup is done */
+
+       n_ptr->cleanup_required = 1;
+       tipc_k_signal((Handler)node_cleanup_finished, n_ptr->addr);
 }
 
 /**
index 6f990da5d143cb30b63a87576c21f483186fbbc6..45f3db3a595d0d9b7fd7f5cb14a84a5df73613e3 100644 (file)
@@ -52,6 +52,7 @@
  * @active_links: pointers to active links to node
  * @links: pointers to all links to node
  * @working_links: number of working links to node (both active and standby)
+ * @cleanup_required: non-zero if cleaning up after a prior loss of contact
  * @link_cnt: number of links to node
  * @permit_changeover: non-zero if node has redundant links to this system
  * @routers: bitmap (used for multicluster communication)
@@ -78,6 +79,7 @@ struct tipc_node {
        struct link *links[MAX_BEARERS];
        int link_cnt;
        int working_links;
+       int cleanup_required;
        int permit_changeover;
        u32 routers[512/32];
        int last_router;