tipc: avoid to asynchronously reset all links
authorYing Xue <ying.xue@windriver.com>
Mon, 5 May 2014 00:56:17 +0000 (08:56 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 5 May 2014 21:26:45 +0000 (17:26 -0400)
Postpone the actions of resetting all links until after bclink
lock is released, avoiding to asynchronously reset all links.

Signed-off-by: Ying Xue <ying.xue@windriver.com>
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tipc/bcast.c
net/tipc/bcast.h
net/tipc/link.c
net/tipc/link.h

index ef8cff4ad7438251e36f02861dbe5180e292d47f..a0978d0890cb3376a9a6aa4b44c20190ad766cc7 100644 (file)
@@ -87,6 +87,7 @@ struct tipc_bcbearer {
  * @lock: spinlock governing access to structure
  * @link: (non-standard) broadcast link structure
  * @node: (non-standard) node structure representing b'cast link's peer node
+ * @flags: represent bclink states
  * @bcast_nodes: map of broadcast-capable nodes
  * @retransmit_to: node that most recently requested a retransmit
  *
@@ -96,6 +97,7 @@ struct tipc_bclink {
        spinlock_t lock;
        struct tipc_link link;
        struct tipc_node node;
+       unsigned int flags;
        struct tipc_node_map bcast_nodes;
        struct tipc_node *retransmit_to;
 };
@@ -119,7 +121,26 @@ static void tipc_bclink_lock(void)
 
 static void tipc_bclink_unlock(void)
 {
+       struct tipc_node *node = NULL;
+
+       if (likely(!bclink->flags)) {
+               spin_unlock_bh(&bclink->lock);
+               return;
+       }
+
+       if (bclink->flags & TIPC_BCLINK_RESET) {
+               bclink->flags &= ~TIPC_BCLINK_RESET;
+               node = tipc_bclink_retransmit_to();
+       }
        spin_unlock_bh(&bclink->lock);
+
+       if (node)
+               tipc_link_reset_all(node);
+}
+
+void tipc_bclink_set_flags(unsigned int flags)
+{
+       bclink->flags |= flags;
 }
 
 static u32 bcbuf_acks(struct sk_buff *buf)
index ea162c7b30ee61d27ab3bba4b949c7d26d79255c..00330c45df3e04d03626a31d5f2ee6ba66569298 100644 (file)
@@ -39,6 +39,7 @@
 
 #define MAX_NODES 4096
 #define WSIZE 32
+#define TIPC_BCLINK_RESET 1
 
 /**
  * struct tipc_node_map - set of node identifiers
@@ -83,6 +84,7 @@ void tipc_port_list_free(struct tipc_port_list *pl_ptr);
 
 int tipc_bclink_init(void);
 void tipc_bclink_stop(void);
+void tipc_bclink_set_flags(unsigned int flags);
 void tipc_bclink_add_node(u32 addr);
 void tipc_bclink_remove_node(u32 addr);
 struct tipc_node *tipc_bclink_retransmit_to(void);
index ac074aaf104d3f16321bf0181bb1be56adee6c94..dce2bef817206dce31aa726b23be1eb0970f5114 100644 (file)
@@ -1259,29 +1259,24 @@ void tipc_link_push_queue(struct tipc_link *l_ptr)
        } while (!res);
 }
 
-static void link_reset_all(unsigned long addr)
+void tipc_link_reset_all(struct tipc_node *node)
 {
-       struct tipc_node *n_ptr;
        char addr_string[16];
        u32 i;
 
-       n_ptr = tipc_node_find((u32)addr);
-       if (!n_ptr)
-               return; /* node no longer exists */
-
-       tipc_node_lock(n_ptr);
+       tipc_node_lock(node);
 
        pr_warn("Resetting all links to %s\n",
-               tipc_addr_string_fill(addr_string, n_ptr->addr));
+               tipc_addr_string_fill(addr_string, node->addr));
 
        for (i = 0; i < MAX_BEARERS; i++) {
-               if (n_ptr->links[i]) {
-                       link_print(n_ptr->links[i], "Resetting link\n");
-                       tipc_link_reset(n_ptr->links[i]);
+               if (node->links[i]) {
+                       link_print(node->links[i], "Resetting link\n");
+                       tipc_link_reset(node->links[i]);
                }
        }
 
-       tipc_node_unlock(n_ptr);
+       tipc_node_unlock(node);
 }
 
 static void link_retransmit_failure(struct tipc_link *l_ptr,
@@ -1318,10 +1313,9 @@ static void link_retransmit_failure(struct tipc_link *l_ptr,
                        n_ptr->bclink.oos_state,
                        n_ptr->bclink.last_sent);
 
-               tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr);
-
                tipc_node_unlock(n_ptr);
 
+               tipc_bclink_set_flags(TIPC_BCLINK_RESET);
                l_ptr->stale_count = 0;
        }
 }
index 4b556c181baeb6a580552a956328b3dad276ae1c..7ba73fa6b81ea1aedc5061770dd3d7186a363e5c 100644 (file)
@@ -230,6 +230,7 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area,
                                         int req_tlv_space);
 struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area,
                                          int req_tlv_space);
+void tipc_link_reset_all(struct tipc_node *node);
 void tipc_link_reset(struct tipc_link *l_ptr);
 void tipc_link_reset_list(unsigned int bearer_id);
 int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector);