diff options
| -rw-r--r-- | net/tipc/group.c | 64 | ||||
| -rw-r--r-- | net/tipc/group.h | 2 | ||||
| -rw-r--r-- | net/tipc/socket.c | 8 | 
3 files changed, 41 insertions, 33 deletions
| diff --git a/net/tipc/group.c b/net/tipc/group.c index 1908773c9fca..497ee34bfab9 100644 --- a/net/tipc/group.c +++ b/net/tipc/group.c @@ -74,7 +74,6 @@ struct tipc_member {  	u16 bc_rcv_nxt;  	u16 bc_syncpt;  	u16 bc_acked; -	bool usr_pending;  };  struct tipc_group { @@ -96,11 +95,27 @@ struct tipc_group {  	u16 bc_ackers;  	bool loopback;  	bool events; +	bool open;  };  static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,  				  int mtyp, struct sk_buff_head *xmitq); +bool tipc_group_is_open(struct tipc_group *grp) +{ +	return grp->open; +} + +static void tipc_group_open(struct tipc_member *m, bool *wakeup) +{ +	*wakeup = false; +	if (list_empty(&m->small_win)) +		return; +	list_del_init(&m->small_win); +	m->group->open = true; +	*wakeup = true; +} +  static void tipc_group_decr_active(struct tipc_group *grp,  				   struct tipc_member *m)  { @@ -406,20 +421,20 @@ bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,  	int adv, state;  	m = tipc_group_find_dest(grp, dnode, dport); -	*mbr = m; -	if (!m) +	if (!tipc_group_is_receiver(m)) { +		*mbr = NULL;  		return false; -	if (m->usr_pending) -		return true; +	} +	*mbr = m; +  	if (m->window >= len)  		return false; -	m->usr_pending = true; + +	grp->open = false;  	/* If not fully advertised, do it now to prevent mutual blocking */  	adv = m->advertised;  	state = m->state; -	if (state < MBR_JOINED) -		return true;  	if (state == MBR_JOINED && adv == ADV_IDLE)  		return true;  	if (state == MBR_ACTIVE && adv == ADV_ACTIVE) @@ -437,9 +452,10 @@ bool tipc_group_bc_cong(struct tipc_group *grp, int len)  	struct tipc_member *m = NULL;  	/* If prev bcast was replicast, reject until all receivers have acked */ -	if (grp->bc_ackers) +	if (grp->bc_ackers) { +		grp->open = false;  		return true; - +	}  	if (list_empty(&grp->small_win))  		return false; @@ -754,9 +770,7 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,  		/* Member can be taken into service */  		m->state = MBR_JOINED; -		*usr_wakeup = true; -		m->usr_pending = false; -		list_del_init(&m->small_win); +		tipc_group_open(m, usr_wakeup);  		tipc_group_update_member(m, 0);  		tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);  		tipc_group_create_event(grp, m, TIPC_PUBLISHED, @@ -767,8 +781,7 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,  			return;  		m->bc_syncpt = msg_grp_bc_syncpt(hdr);  		list_del_init(&m->list); -		list_del_init(&m->small_win); -		*usr_wakeup = true; +		tipc_group_open(m, usr_wakeup);  		tipc_group_decr_active(grp, m);  		m->state = MBR_LEAVING;  		tipc_group_create_event(grp, m, TIPC_WITHDRAWN, @@ -778,26 +791,25 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,  		if (!m)  			return;  		m->window += msg_adv_win(hdr); -		*usr_wakeup = m->usr_pending; -		m->usr_pending = false; -		list_del_init(&m->small_win); +		tipc_group_open(m, usr_wakeup);  		return;  	case GRP_ACK_MSG:  		if (!m)  			return;  		m->bc_acked = msg_grp_bc_acked(hdr);  		if (--grp->bc_ackers) -			break; +			return; +		list_del_init(&m->small_win); +		m->group->open = true;  		*usr_wakeup = true; -		m->usr_pending = false; +		tipc_group_update_member(m, 0);  		return;  	case GRP_RECLAIM_MSG:  		if (!m)  			return; -		*usr_wakeup = m->usr_pending; -		m->usr_pending = false;  		tipc_group_proto_xmit(grp, m, GRP_REMIT_MSG, xmitq);  		m->window = ADV_IDLE; +		tipc_group_open(m, usr_wakeup);  		return;  	case GRP_REMIT_MSG:  		if (!m || m->state != MBR_RECLAIMING) @@ -883,9 +895,7 @@ void tipc_group_member_evt(struct tipc_group *grp,  		/* Member can be taken into service */  		m->instance = instance;  		m->state = MBR_JOINED; -		*usr_wakeup = true; -		m->usr_pending = false; -		list_del_init(&m->small_win); +		tipc_group_open(m, usr_wakeup);  		tipc_group_update_member(m, 0);  		tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);  		tipc_group_create_event(grp, m, TIPC_PUBLISHED, @@ -895,12 +905,10 @@ void tipc_group_member_evt(struct tipc_group *grp,  		if (!m)  			break; -		*usr_wakeup = true; -		m->usr_pending = false;  		tipc_group_decr_active(grp, m);  		m->state = MBR_LEAVING;  		list_del_init(&m->list); -		list_del_init(&m->small_win); +		tipc_group_open(m, usr_wakeup);  		/* Only send event if no LEAVE message can be expected */  		if (!tipc_node_is_up(net, node)) diff --git a/net/tipc/group.h b/net/tipc/group.h index dee79477d499..f4a596ed9848 100644 --- a/net/tipc/group.h +++ b/net/tipc/group.h @@ -67,9 +67,9 @@ void tipc_group_update_bc_members(struct tipc_group *grp, int len, bool ack);  bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,  		     int len, struct tipc_member **m);  bool tipc_group_bc_cong(struct tipc_group *grp, int len); +bool tipc_group_is_open(struct tipc_group *grp);  void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,  			       u32 port, struct sk_buff_head *xmitq);  u16 tipc_group_bc_snd_nxt(struct tipc_group *grp);  void tipc_group_update_member(struct tipc_member *m, int len); -int tipc_group_size(struct tipc_group *grp);  #endif diff --git a/net/tipc/socket.c b/net/tipc/socket.c index b24dab3996c9..1f236271766c 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -715,7 +715,7 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,  {  	struct sock *sk = sock->sk;  	struct tipc_sock *tsk = tipc_sk(sk); -	struct tipc_group *grp = tsk->group; +	struct tipc_group *grp;  	u32 revents = 0;  	sock_poll_wait(file, sk_sleep(sk), wait); @@ -736,9 +736,9 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,  			revents |= POLLIN | POLLRDNORM;  		break;  	case TIPC_OPEN: -		if (!grp || tipc_group_size(grp)) -			if (!tsk->cong_link_cnt) -				revents |= POLLOUT; +		grp = tsk->group; +		if ((!grp || tipc_group_is_open(grp)) && !tsk->cong_link_cnt) +			revents |= POLLOUT;  		if (!tipc_sk_type_connectionless(sk))  			break;  		if (skb_queue_empty(&sk->sk_receive_queue)) | 
