Skip to content

Commit

Permalink
tipc: avoid to asynchronously notify subscriptions
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ying Xue authored and David S. Miller committed May 5, 2014
1 parent 10f465c commit 9db9fdd
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 16 deletions.
23 changes: 21 additions & 2 deletions net/tipc/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,10 @@ static void node_lost_contact(struct tipc_node *n_ptr)
}

/* Notify subscribers */
tipc_nodesub_notify(n_ptr);
n_ptr->flags = TIPC_NODE_LOST;

/* Prevent re-contact with node until cleanup is done */
n_ptr->flags = TIPC_NODE_DOWN | TIPC_NAMES_GONE;
n_ptr->flags |= TIPC_NODE_DOWN | TIPC_NAMES_GONE;
tipc_k_signal((Handler)node_name_purge_complete, n_ptr->addr);
}

Expand Down Expand Up @@ -465,3 +465,22 @@ int tipc_node_get_linkname(u32 bearer_id, u32 addr, char *linkname, size_t len)
tipc_node_unlock(node);
return -EINVAL;
}

void tipc_node_unlock(struct tipc_node *node)
{
LIST_HEAD(nsub_list);

if (likely(!node->flags)) {
spin_unlock_bh(&node->lock);
return;
}

if (node->flags & TIPC_NODE_LOST) {
list_replace_init(&node->nsub, &nsub_list);
node->flags &= ~TIPC_NODE_LOST;
}
spin_unlock_bh(&node->lock);

if (!list_empty(&nsub_list))
tipc_nodesub_notify(&nsub_list);
}
15 changes: 7 additions & 8 deletions net/tipc/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,14 @@
* TIPC_NODE_DOWN: indicate node is down
* TIPC_NAMES_GONE: indicate the node's publications are purged
* TIPC_NODE_RESET: indicate node is reset
* TIPC_NODE_LOST: indicate node is lost and it's used to notify subscriptions
* when node lock is released
*/
enum {
TIPC_NODE_DOWN = (1 << 1),
TIPC_NAMES_GONE = (1 << 2),
TIPC_NODE_RESET = (1 << 3)
TIPC_NODE_RESET = (1 << 3),
TIPC_NODE_LOST = (1 << 4)
};

/**
Expand Down Expand Up @@ -130,15 +133,11 @@ int tipc_node_is_up(struct tipc_node *n_ptr);
struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
int tipc_node_get_linkname(u32 bearer_id, u32 node, char *linkname, size_t len);
void tipc_node_unlock(struct tipc_node *node);

static inline void tipc_node_lock(struct tipc_node *n_ptr)
static inline void tipc_node_lock(struct tipc_node *node)
{
spin_lock_bh(&n_ptr->lock);
}

static inline void tipc_node_unlock(struct tipc_node *n_ptr)
{
spin_unlock_bh(&n_ptr->lock);
spin_lock_bh(&node->lock);
}

static inline bool tipc_node_blocked(struct tipc_node *node)
Expand Down
9 changes: 4 additions & 5 deletions net/tipc/node_subscr.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,13 @@ void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub)
*
* Note: node is locked by caller
*/
void tipc_nodesub_notify(struct tipc_node *node)
void tipc_nodesub_notify(struct list_head *nsub_list)
{
struct tipc_node_subscr *ns;
struct tipc_node_subscr *ns, *safe;

list_for_each_entry(ns, &node->nsub, nodesub_list) {
list_for_each_entry_safe(ns, safe, nsub_list, nodesub_list) {
if (ns->handle_node_down) {
tipc_k_signal((Handler)ns->handle_node_down,
(unsigned long)ns->usr_handle);
ns->handle_node_down(ns->usr_handle);
ns->handle_node_down = NULL;
}
}
Expand Down
2 changes: 1 addition & 1 deletion net/tipc/node_subscr.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,6 @@ struct tipc_node_subscr {
void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr,
void *usr_handle, net_ev_handler handle_down);
void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub);
void tipc_nodesub_notify(struct tipc_node *node);
void tipc_nodesub_notify(struct list_head *nsub_list);

#endif

0 comments on commit 9db9fdd

Please sign in to comment.