Skip to content

Commit

Permalink
Merge branch 'tipc-next'
Browse files Browse the repository at this point in the history
Ying Xue says:

====================
tipc: fix two corner issues

The patch set aims at resolving the following two critical issues:

Patch #1: Resolve a deadlock which happens while all links are reset
Patch #2: Correct a mistake usage of RCU lock which is used to protect
          node list
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 29, 2015
2 parents faadb05 + 8a0f6eb commit ae7633c
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 62 deletions.
28 changes: 4 additions & 24 deletions net/tipc/bcast.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,8 @@ static void tipc_bclink_lock(struct net *net)
static void tipc_bclink_unlock(struct net *net)
{
struct tipc_net *tn = net_generic(net, tipc_net_id);
struct tipc_node *node = NULL;

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

if (tn->bclink->flags & TIPC_BCLINK_RESET) {
tn->bclink->flags &= ~TIPC_BCLINK_RESET;
node = tipc_bclink_retransmit_to(net);
}
spin_unlock_bh(&tn->bclink->lock);

if (node)
tipc_link_reset_all(node);
}

void tipc_bclink_input(struct net *net)
Expand All @@ -91,13 +78,6 @@ uint tipc_bclink_get_mtu(void)
return MAX_PKT_DEFAULT_MCAST;
}

void tipc_bclink_set_flags(struct net *net, unsigned int flags)
{
struct tipc_net *tn = net_generic(net, tipc_net_id);

tn->bclink->flags |= flags;
}

static u32 bcbuf_acks(struct sk_buff *buf)
{
return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle;
Expand Down Expand Up @@ -156,7 +136,6 @@ static void bclink_update_last_sent(struct tipc_node *node, u32 seqno)
seqno : node->bclink.last_sent;
}


/**
* tipc_bclink_retransmit_to - get most recent node to request retransmission
*
Expand Down Expand Up @@ -350,13 +329,12 @@ static void bclink_peek_nack(struct net *net, struct tipc_msg *msg)
return;

tipc_node_lock(n_ptr);

if (n_ptr->bclink.recv_permitted &&
(n_ptr->bclink.last_in != n_ptr->bclink.last_sent) &&
(n_ptr->bclink.last_in == msg_bcgap_after(msg)))
n_ptr->bclink.oos_state = 2;

tipc_node_unlock(n_ptr);
tipc_node_put(n_ptr);
}

/* tipc_bclink_xmit - deliver buffer chain to all nodes in cluster
Expand Down Expand Up @@ -476,17 +454,18 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf)
goto unlock;
if (msg_destnode(msg) == tn->own_addr) {
tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
tipc_node_unlock(node);
tipc_bclink_lock(net);
bcl->stats.recv_nacks++;
tn->bclink->retransmit_to = node;
bclink_retransmit_pkt(tn, msg_bcgap_after(msg),
msg_bcgap_to(msg));
tipc_bclink_unlock(net);
tipc_node_unlock(node);
} else {
tipc_node_unlock(node);
bclink_peek_nack(net, msg);
}
tipc_node_put(node);
goto exit;
}

Expand Down Expand Up @@ -591,6 +570,7 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf)

unlock:
tipc_node_unlock(node);
tipc_node_put(node);
exit:
kfree_skb(buf);
}
Expand Down
4 changes: 0 additions & 4 deletions net/tipc/bcast.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ struct tipc_bcbearer_pair {
struct tipc_bearer *secondary;
};

#define TIPC_BCLINK_RESET 1
#define BCBEARER MAX_BEARERS

/**
Expand Down Expand Up @@ -86,7 +85,6 @@ 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
*
Expand All @@ -96,7 +94,6 @@ struct tipc_bclink {
spinlock_t lock;
struct tipc_link link;
struct tipc_node node;
unsigned int flags;
struct sk_buff_head arrvq;
struct sk_buff_head inputq;
struct tipc_node_map bcast_nodes;
Expand All @@ -117,7 +114,6 @@ static inline int tipc_nmap_equal(struct tipc_node_map *nm_a,

int tipc_bclink_init(struct net *net);
void tipc_bclink_stop(struct net *net);
void tipc_bclink_set_flags(struct net *tn, unsigned int flags);
void tipc_bclink_add_node(struct net *net, u32 addr);
void tipc_bclink_remove_node(struct net *net, u32 addr);
struct tipc_node *tipc_bclink_retransmit_to(struct net *tn);
Expand Down
1 change: 1 addition & 0 deletions net/tipc/discover.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
}
}
tipc_node_unlock(node);
tipc_node_put(node);
}

/**
Expand Down
12 changes: 6 additions & 6 deletions net/tipc/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@ int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dnode,
if (link)
rc = __tipc_link_xmit(net, link, list);
tipc_node_unlock(node);
tipc_node_put(node);
}
if (link)
return rc;
Expand Down Expand Up @@ -980,7 +981,6 @@ static void link_retransmit_failure(struct tipc_link *l_ptr,
(unsigned long) TIPC_SKB_CB(buf)->handle);

n_ptr = tipc_bclink_retransmit_to(net);
tipc_node_lock(n_ptr);

tipc_addr_string_fill(addr_string, n_ptr->addr);
pr_info("Broadcast link info for %s\n", addr_string);
Expand All @@ -992,9 +992,7 @@ static void link_retransmit_failure(struct tipc_link *l_ptr,
n_ptr->bclink.oos_state,
n_ptr->bclink.last_sent);

tipc_node_unlock(n_ptr);

tipc_bclink_set_flags(net, TIPC_BCLINK_RESET);
n_ptr->action_flags |= TIPC_BCAST_RESET;
l_ptr->stale_count = 0;
}
}
Expand Down Expand Up @@ -1119,8 +1117,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
n_ptr = tipc_node_find(net, msg_prevnode(msg));
if (unlikely(!n_ptr))
goto discard;
tipc_node_lock(n_ptr);

tipc_node_lock(n_ptr);
/* Locate unicast link endpoint that should handle message */
l_ptr = n_ptr->links[b_ptr->identity];
if (unlikely(!l_ptr))
Expand Down Expand Up @@ -1208,6 +1206,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr)
skb = NULL;
unlock:
tipc_node_unlock(n_ptr);
tipc_node_put(n_ptr);
discard:
if (unlikely(skb))
kfree_skb(skb);
Expand Down Expand Up @@ -2239,7 +2238,6 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb)
msg.seq = cb->nlh->nlmsg_seq;

rcu_read_lock();

if (prev_node) {
node = tipc_node_find(net, prev_node);
if (!node) {
Expand All @@ -2252,13 +2250,15 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb)
cb->prev_seq = 1;
goto out;
}
tipc_node_put(node);

list_for_each_entry_continue_rcu(node, &tn->node_list,
list) {
tipc_node_lock(node);
err = __tipc_nl_add_node_links(net, &msg, node,
&prev_link);
tipc_node_unlock(node);
tipc_node_put(node);
if (err)
goto out;

Expand Down
2 changes: 2 additions & 0 deletions net/tipc/name_distr.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ static void tipc_publ_subscribe(struct net *net, struct publication *publ,
tipc_node_lock(node);
list_add_tail(&publ->nodesub_list, &node->publ_list);
tipc_node_unlock(node);
tipc_node_put(node);
}

static void tipc_publ_unsubscribe(struct net *net, struct publication *publ,
Expand All @@ -258,6 +259,7 @@ static void tipc_publ_unsubscribe(struct net *net, struct publication *publ,
tipc_node_lock(node);
list_del_init(&publ->nodesub_list);
tipc_node_unlock(node);
tipc_node_put(node);
}

/**
Expand Down
Loading

0 comments on commit ae7633c

Please sign in to comment.