Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae7633c8 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tipc-next'



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: default avatarDavid S. Miller <davem@davemloft.net>
parents faadb05f 8a0f6ebe
Loading
Loading
Loading
Loading
+4 −24
Original line number Diff line number Diff line
@@ -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)
@@ -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;
@@ -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
 *
@@ -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
@@ -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;
	}

@@ -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);
}
+0 −4
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ struct tipc_bcbearer_pair {
	struct tipc_bearer *secondary;
};

#define TIPC_BCLINK_RESET	1
#define	BCBEARER		MAX_BEARERS

/**
@@ -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
 *
@@ -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;
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -260,6 +260,7 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
		}
	}
	tipc_node_unlock(node);
	tipc_node_put(node);
}

/**
+6 −6
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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;
	}
}
@@ -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))
@@ -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);
@@ -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) {
@@ -2252,6 +2250,7 @@ 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) {
@@ -2259,6 +2258,7 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb)
			err = __tipc_nl_add_node_links(net, &msg, node,
						       &prev_link);
			tipc_node_unlock(node);
			tipc_node_put(node);
			if (err)
				goto out;

+2 −0
Original line number Diff line number Diff line
@@ -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,
@@ -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);
}

/**
Loading