aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2014-05-04 20:56:12 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-05 17:26:44 -0400
commit9db9fdd1983eb960182d72f95d77b91b3a5173d0 (patch)
tree0c4d21174478529972f3b630f7b1daa6f018f134 /net/tipc
parent10f465c4966fbc8f50a59480d37a3451f6f3d564 (diff)
tipc: avoid to asynchronously notify subscriptions
Postpone the actions of notifying subscriptions until after node lock is released, avoiding to asynchronously execute registered handlers when node is lost. 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>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/node.c23
-rw-r--r--net/tipc/node.h15
-rw-r--r--net/tipc/node_subscr.c9
-rw-r--r--net/tipc/node_subscr.h2
4 files changed, 33 insertions, 16 deletions
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 2b0a0849d4cc..befbcc9eade6 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -321,10 +321,10 @@ static void node_lost_contact(struct tipc_node *n_ptr)
321 } 321 }
322 322
323 /* Notify subscribers */ 323 /* Notify subscribers */
324 tipc_nodesub_notify(n_ptr); 324 n_ptr->flags = TIPC_NODE_LOST;
325 325
326 /* Prevent re-contact with node until cleanup is done */ 326 /* Prevent re-contact with node until cleanup is done */
327 n_ptr->flags = TIPC_NODE_DOWN | TIPC_NAMES_GONE; 327 n_ptr->flags |= TIPC_NODE_DOWN | TIPC_NAMES_GONE;
328 tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr); 328 tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr);
329} 329}
330 330
@@ -465,3 +465,22 @@ int tipc_node_get_linkname(u32 bearer_id, u32 addr, char *linkname, size_t len)
465 tipc_node_unlock(node); 465 tipc_node_unlock(node);
466 return -EINVAL; 466 return -EINVAL;
467} 467}
468
469void tipc_node_unlock(struct tipc_node *node)
470{
471 LIST_HEAD(nsub_list);
472
473 if (likely(!node->flags)) {
474 spin_unlock_bh(&node->lock);
475 return;
476 }
477
478 if (node->flags & TIPC_NODE_LOST) {
479 list_replace_init(&node->nsub, &nsub_list);
480 node->flags &= ~TIPC_NODE_LOST;
481 }
482 spin_unlock_bh(&node->lock);
483
484 if (!list_empty(&nsub_list))
485 tipc_nodesub_notify(&nsub_list);
486}
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 242b918ddd14..fd86726ed192 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -51,11 +51,14 @@
51 * TIPC_NODE_DOWN: indicate node is down 51 * TIPC_NODE_DOWN: indicate node is down
52 * TIPC_NAMES_GONE: indicate the node's publications are purged 52 * TIPC_NAMES_GONE: indicate the node's publications are purged
53 * TIPC_NODE_RESET: indicate node is reset 53 * TIPC_NODE_RESET: indicate node is reset
54 * TIPC_NODE_LOST: indicate node is lost and it's used to notify subscriptions
55 * when node lock is released
54 */ 56 */
55enum { 57enum {
56 TIPC_NODE_DOWN = (1 << 1), 58 TIPC_NODE_DOWN = (1 << 1),
57 TIPC_NAMES_GONE = (1 << 2), 59 TIPC_NAMES_GONE = (1 << 2),
58 TIPC_NODE_RESET = (1 << 3) 60 TIPC_NODE_RESET = (1 << 3),
61 TIPC_NODE_LOST = (1 << 4)
59}; 62};
60 63
61/** 64/**
@@ -130,15 +133,11 @@ int tipc_node_is_up(struct tipc_node *n_ptr);
130struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space); 133struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
131struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space); 134struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
132int tipc_node_get_linkname(u32 bearer_id, u32 node, char *linkname, size_t len); 135int tipc_node_get_linkname(u32 bearer_id, u32 node, char *linkname, size_t len);
136void tipc_node_unlock(struct tipc_node *node);
133 137
134static inline void tipc_node_lock(struct tipc_node *n_ptr) 138static inline void tipc_node_lock(struct tipc_node *node)
135{ 139{
136 spin_lock_bh(&n_ptr->lock); 140 spin_lock_bh(&node->lock);
137}
138
139static inline void tipc_node_unlock(struct tipc_node *n_ptr)
140{
141 spin_unlock_bh(&n_ptr->lock);
142} 141}
143 142
144static inline bool tipc_node_blocked(struct tipc_node *node) 143static inline bool tipc_node_blocked(struct tipc_node *node)
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
index 8a7384c04add..7c59ab1d6ecb 100644
--- a/net/tipc/node_subscr.c
+++ b/net/tipc/node_subscr.c
@@ -81,14 +81,13 @@ void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub)
81 * 81 *
82 * Note: node is locked by caller 82 * Note: node is locked by caller
83 */ 83 */
84void tipc_nodesub_notify(struct tipc_node *node) 84void tipc_nodesub_notify(struct list_head *nsub_list)
85{ 85{
86 struct tipc_node_subscr *ns; 86 struct tipc_node_subscr *ns, *safe;
87 87
88 list_for_each_entry(ns, &node->nsub, nodesub_list) { 88 list_for_each_entry_safe(ns, safe, nsub_list, nodesub_list) {
89 if (ns->handle_node_down) { 89 if (ns->handle_node_down) {
90 tipc_k_signal((Handler)ns->handle_node_down, 90 ns->handle_node_down(ns->usr_handle);
91 (unsigned long)ns->usr_handle);
92 ns->handle_node_down = NULL; 91 ns->handle_node_down = NULL;
93 } 92 }
94 } 93 }
diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h
index c95d20727ded..d91b8cc81e3d 100644
--- a/net/tipc/node_subscr.h
+++ b/net/tipc/node_subscr.h
@@ -58,6 +58,6 @@ struct tipc_node_subscr {
58void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr, 58void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr,
59 void *usr_handle, net_ev_handler handle_down); 59 void *usr_handle, net_ev_handler handle_down);
60void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub); 60void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub);
61void tipc_nodesub_notify(struct tipc_node *node); 61void tipc_nodesub_notify(struct list_head *nsub_list);
62 62
63#endif 63#endif