diff options
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/bearer.c | 5 | ||||
| -rw-r--r-- | net/tipc/group.c | 71 | ||||
| -rw-r--r-- | net/tipc/monitor.c | 6 | ||||
| -rw-r--r-- | net/tipc/node.c | 26 | ||||
| -rw-r--r-- | net/tipc/server.c | 3 | ||||
| -rw-r--r-- | net/tipc/socket.c | 4 | ||||
| -rw-r--r-- | net/tipc/udp_media.c | 4 | 
7 files changed, 75 insertions, 44 deletions
| diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 47ec121574ce..c8001471da6c 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -324,6 +324,7 @@ restart:  	if (res) {  		pr_warn("Bearer <%s> rejected, enable failure (%d)\n",  			name, -res); +		kfree(b);  		return -EINVAL;  	} @@ -347,8 +348,10 @@ restart:  	if (skb)  		tipc_bearer_xmit_skb(net, bearer_id, skb, &b->bcast_addr); -	if (tipc_mon_create(net, bearer_id)) +	if (tipc_mon_create(net, bearer_id)) { +		bearer_disable(net, b);  		return -ENOMEM; +	}  	pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",  		name, diff --git a/net/tipc/group.c b/net/tipc/group.c index 12777cac638a..5f4ffae807ee 100644 --- a/net/tipc/group.c +++ b/net/tipc/group.c @@ -109,7 +109,8 @@ static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,  static void tipc_group_decr_active(struct tipc_group *grp,  				   struct tipc_member *m)  { -	if (m->state == MBR_ACTIVE || m->state == MBR_RECLAIMING) +	if (m->state == MBR_ACTIVE || m->state == MBR_RECLAIMING || +	    m->state == MBR_REMITTED)  		grp->active_cnt--;  } @@ -351,8 +352,7 @@ void tipc_group_update_member(struct tipc_member *m, int len)  	if (m->window >= ADV_IDLE)  		return; -	if (!list_empty(&m->congested)) -		return; +	list_del_init(&m->congested);  	/* Sort member into congested members' list */  	list_for_each_entry_safe(_m, tmp, &grp->congested, congested) { @@ -369,18 +369,20 @@ void tipc_group_update_bc_members(struct tipc_group *grp, int len, bool ack)  	u16 prev = grp->bc_snd_nxt - 1;  	struct tipc_member *m;  	struct rb_node *n; +	u16 ackers = 0;  	for (n = rb_first(&grp->members); n; n = rb_next(n)) {  		m = container_of(n, struct tipc_member, tree_node);  		if (tipc_group_is_enabled(m)) {  			tipc_group_update_member(m, len);  			m->bc_acked = prev; +			ackers++;  		}  	}  	/* Mark number of acknowledges to expect, if any */  	if (ack) -		grp->bc_ackers = grp->member_cnt; +		grp->bc_ackers = ackers;  	grp->bc_snd_nxt++;  } @@ -497,6 +499,7 @@ void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,  	while ((skb = skb_peek(defq))) {  		hdr = buf_msg(skb);  		mtyp = msg_type(hdr); +		blks = msg_blocks(hdr);  		deliver = true;  		ack = false;  		update = false; @@ -546,7 +549,6 @@ void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq,  		if (!update)  			continue; -		blks = msg_blocks(hdr);  		tipc_group_update_rcv_win(grp, blks, node, port, xmitq);  	}  	return; @@ -561,7 +563,7 @@ void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,  	int max_active = grp->max_active;  	int reclaim_limit = max_active * 3 / 4;  	int active_cnt = grp->active_cnt; -	struct tipc_member *m, *rm; +	struct tipc_member *m, *rm, *pm;  	m = tipc_group_find_member(grp, node, port);  	if (!m) @@ -604,6 +606,17 @@ void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,  			pr_warn_ratelimited("Rcv unexpected msg after REMIT\n");  			tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);  		} +		grp->active_cnt--; +		list_del_init(&m->list); +		if (list_empty(&grp->pending)) +			return; + +		/* Set oldest pending member to active and advertise */ +		pm = list_first_entry(&grp->pending, struct tipc_member, list); +		pm->state = MBR_ACTIVE; +		list_move_tail(&pm->list, &grp->active); +		grp->active_cnt++; +		tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);  		break;  	case MBR_RECLAIMING:  	case MBR_DISCOVERED: @@ -648,6 +661,7 @@ static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,  	} else if (mtyp == GRP_REMIT_MSG) {  		msg_set_grp_remitted(hdr, m->window);  	} +	msg_set_dest_droppable(hdr, true);  	__skb_queue_tail(xmitq, skb);  } @@ -689,15 +703,16 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,  			msg_set_grp_bc_seqno(ehdr, m->bc_syncpt);  			__skb_queue_tail(inputq, m->event_msg);  		} -		if (m->window < ADV_IDLE) -			tipc_group_update_member(m, 0); -		else -			list_del_init(&m->congested); +		list_del_init(&m->congested); +		tipc_group_update_member(m, 0);  		return;  	case GRP_LEAVE_MSG:  		if (!m)  			return;  		m->bc_syncpt = msg_grp_bc_syncpt(hdr); +		list_del_init(&m->list); +		list_del_init(&m->congested); +		*usr_wakeup = true;  		/* Wait until WITHDRAW event is received */  		if (m->state != MBR_LEAVING) { @@ -709,8 +724,6 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,  		ehdr = buf_msg(m->event_msg);  		msg_set_grp_bc_seqno(ehdr, m->bc_syncpt);  		__skb_queue_tail(inputq, m->event_msg); -		*usr_wakeup = true; -		list_del_init(&m->congested);  		return;  	case GRP_ADV_MSG:  		if (!m) @@ -741,14 +754,14 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,  		if (!m || m->state != MBR_RECLAIMING)  			return; -		list_del_init(&m->list); -		grp->active_cnt--;  		remitted = msg_grp_remitted(hdr);  		/* Messages preceding the REMIT still in receive queue */  		if (m->advertised > remitted) {  			m->state = MBR_REMITTED;  			in_flight = m->advertised - remitted; +			m->advertised = ADV_IDLE + in_flight; +			return;  		}  		/* All messages preceding the REMIT have been read */  		if (m->advertised <= remitted) { @@ -760,6 +773,8 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,  			tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);  		m->advertised = ADV_IDLE + in_flight; +		grp->active_cnt--; +		list_del_init(&m->list);  		/* Set oldest pending member to active and advertise */  		if (list_empty(&grp->pending)) @@ -849,19 +864,29 @@ void tipc_group_member_evt(struct tipc_group *grp,  		*usr_wakeup = true;  		m->usr_pending = false;  		node_up = tipc_node_is_up(net, node); - -		/* Hold back event if more messages might be expected */ -		if (m->state != MBR_LEAVING && node_up) { -			m->event_msg = skb; -			tipc_group_decr_active(grp, m); -			m->state = MBR_LEAVING; -		} else { -			if (node_up) +		m->event_msg = NULL; + +		if (node_up) { +			/* Hold back event if a LEAVE msg should be expected */ +			if (m->state != MBR_LEAVING) { +				m->event_msg = skb; +				tipc_group_decr_active(grp, m); +				m->state = MBR_LEAVING; +			} else {  				msg_set_grp_bc_seqno(hdr, m->bc_syncpt); -			else +				__skb_queue_tail(inputq, skb); +			} +		} else { +			if (m->state != MBR_LEAVING) { +				tipc_group_decr_active(grp, m); +				m->state = MBR_LEAVING;  				msg_set_grp_bc_seqno(hdr, m->bc_rcv_nxt); +			} else { +				msg_set_grp_bc_seqno(hdr, m->bc_syncpt); +			}  			__skb_queue_tail(inputq, skb);  		} +		list_del_init(&m->list);  		list_del_init(&m->congested);  	}  	*sk_rcvbuf = tipc_group_rcvbuf_limit(grp); diff --git a/net/tipc/monitor.c b/net/tipc/monitor.c index 8e884ed06d4b..32dc33a94bc7 100644 --- a/net/tipc/monitor.c +++ b/net/tipc/monitor.c @@ -642,9 +642,13 @@ void tipc_mon_delete(struct net *net, int bearer_id)  {  	struct tipc_net *tn = tipc_net(net);  	struct tipc_monitor *mon = tipc_monitor(net, bearer_id); -	struct tipc_peer *self = get_self(net, bearer_id); +	struct tipc_peer *self;  	struct tipc_peer *peer, *tmp; +	if (!mon) +		return; + +	self = get_self(net, bearer_id);  	write_lock_bh(&mon->lock);  	tn->monitors[bearer_id] = NULL;  	list_for_each_entry_safe(peer, tmp, &self->list, list) { diff --git a/net/tipc/node.c b/net/tipc/node.c index 507017fe0f1b..9036d8756e73 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1880,36 +1880,38 @@ int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info)  	if (strcmp(name, tipc_bclink_name) == 0) {  		err = tipc_nl_add_bc_link(net, &msg); -		if (err) { -			nlmsg_free(msg.skb); -			return err; -		} +		if (err) +			goto err_free;  	} else {  		int bearer_id;  		struct tipc_node *node;  		struct tipc_link *link;  		node = tipc_node_find_by_name(net, name, &bearer_id); -		if (!node) -			return -EINVAL; +		if (!node) { +			err = -EINVAL; +			goto err_free; +		}  		tipc_node_read_lock(node);  		link = node->links[bearer_id].link;  		if (!link) {  			tipc_node_read_unlock(node); -			nlmsg_free(msg.skb); -			return -EINVAL; +			err = -EINVAL; +			goto err_free;  		}  		err = __tipc_nl_add_link(net, &msg, link, 0);  		tipc_node_read_unlock(node); -		if (err) { -			nlmsg_free(msg.skb); -			return err; -		} +		if (err) +			goto err_free;  	}  	return genlmsg_reply(msg.skb, info); + +err_free: +	nlmsg_free(msg.skb); +	return err;  }  int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info *info) diff --git a/net/tipc/server.c b/net/tipc/server.c index acaef80fb88c..d60c30342327 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -314,6 +314,7 @@ static int tipc_accept_from_sock(struct tipc_conn *con)  	newcon->usr_data = s->tipc_conn_new(newcon->conid);  	if (!newcon->usr_data) {  		sock_release(newsock); +		conn_put(newcon);  		return -ENOMEM;  	} @@ -511,7 +512,7 @@ bool tipc_topsrv_kern_subscr(struct net *net, u32 port, u32 type,  	s = con->server;  	scbr = s->tipc_conn_new(*conid);  	if (!scbr) { -		tipc_close_conn(con); +		conn_put(con);  		return false;  	} diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 5d18c0caa92b..3b4084480377 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -727,11 +727,11 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,  	switch (sk->sk_state) {  	case TIPC_ESTABLISHED: +	case TIPC_CONNECTING:  		if (!tsk->cong_link_cnt && !tsk_conn_cong(tsk))  			revents |= POLLOUT;  		/* fall thru' */  	case TIPC_LISTEN: -	case TIPC_CONNECTING:  		if (!skb_queue_empty(&sk->sk_receive_queue))  			revents |= POLLIN | POLLRDNORM;  		break; @@ -1140,7 +1140,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,  				__skb_dequeue(arrvq);  				__skb_queue_tail(inputq, skb);  			} -			refcount_dec(&skb->users); +			kfree_skb(skb);  			spin_unlock_bh(&inputq->lock);  			continue;  		} diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index ecca64fc6a6f..3deabcab4882 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c @@ -371,10 +371,6 @@ static int tipc_udp_recv(struct sock *sk, struct sk_buff *skb)  			goto rcu_out;  	} -	tipc_rcv(sock_net(sk), skb, b); -	rcu_read_unlock(); -	return 0; -  rcu_out:  	rcu_read_unlock();  out: |