aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/group.c64
-rw-r--r--net/tipc/group.h2
-rw-r--r--net/tipc/socket.c8
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 {
74 u16 bc_rcv_nxt; 74 u16 bc_rcv_nxt;
75 u16 bc_syncpt; 75 u16 bc_syncpt;
76 u16 bc_acked; 76 u16 bc_acked;
77 bool usr_pending;
78}; 77};
79 78
80struct tipc_group { 79struct tipc_group {
@@ -96,11 +95,27 @@ struct tipc_group {
96 u16 bc_ackers; 95 u16 bc_ackers;
97 bool loopback; 96 bool loopback;
98 bool events; 97 bool events;
98 bool open;
99}; 99};
100 100
101static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m, 101static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m,
102 int mtyp, struct sk_buff_head *xmitq); 102 int mtyp, struct sk_buff_head *xmitq);
103 103
104bool tipc_group_is_open(struct tipc_group *grp)
105{
106 return grp->open;
107}
108
109static void tipc_group_open(struct tipc_member *m, bool *wakeup)
110{
111 *wakeup = false;
112 if (list_empty(&m->small_win))
113 return;
114 list_del_init(&m->small_win);
115 m->group->open = true;
116 *wakeup = true;
117}
118
104static void tipc_group_decr_active(struct tipc_group *grp, 119static void tipc_group_decr_active(struct tipc_group *grp,
105 struct tipc_member *m) 120 struct tipc_member *m)
106{ 121{
@@ -406,20 +421,20 @@ bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
406 int adv, state; 421 int adv, state;
407 422
408 m = tipc_group_find_dest(grp, dnode, dport); 423 m = tipc_group_find_dest(grp, dnode, dport);
409 *mbr = m; 424 if (!tipc_group_is_receiver(m)) {
410 if (!m) 425 *mbr = NULL;
411 return false; 426 return false;
412 if (m->usr_pending) 427 }
413 return true; 428 *mbr = m;
429
414 if (m->window >= len) 430 if (m->window >= len)
415 return false; 431 return false;
416 m->usr_pending = true; 432
433 grp->open = false;
417 434
418 /* If not fully advertised, do it now to prevent mutual blocking */ 435 /* If not fully advertised, do it now to prevent mutual blocking */
419 adv = m->advertised; 436 adv = m->advertised;
420 state = m->state; 437 state = m->state;
421 if (state < MBR_JOINED)
422 return true;
423 if (state == MBR_JOINED && adv == ADV_IDLE) 438 if (state == MBR_JOINED && adv == ADV_IDLE)
424 return true; 439 return true;
425 if (state == MBR_ACTIVE && adv == ADV_ACTIVE) 440 if (state == MBR_ACTIVE && adv == ADV_ACTIVE)
@@ -437,9 +452,10 @@ bool tipc_group_bc_cong(struct tipc_group *grp, int len)
437 struct tipc_member *m = NULL; 452 struct tipc_member *m = NULL;
438 453
439 /* If prev bcast was replicast, reject until all receivers have acked */ 454 /* If prev bcast was replicast, reject until all receivers have acked */
440 if (grp->bc_ackers) 455 if (grp->bc_ackers) {
456 grp->open = false;
441 return true; 457 return true;
442 458 }
443 if (list_empty(&grp->small_win)) 459 if (list_empty(&grp->small_win))
444 return false; 460 return false;
445 461
@@ -754,9 +770,7 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
754 770
755 /* Member can be taken into service */ 771 /* Member can be taken into service */
756 m->state = MBR_JOINED; 772 m->state = MBR_JOINED;
757 *usr_wakeup = true; 773 tipc_group_open(m, usr_wakeup);
758 m->usr_pending = false;
759 list_del_init(&m->small_win);
760 tipc_group_update_member(m, 0); 774 tipc_group_update_member(m, 0);
761 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq); 775 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
762 tipc_group_create_event(grp, m, TIPC_PUBLISHED, 776 tipc_group_create_event(grp, m, TIPC_PUBLISHED,
@@ -767,8 +781,7 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
767 return; 781 return;
768 m->bc_syncpt = msg_grp_bc_syncpt(hdr); 782 m->bc_syncpt = msg_grp_bc_syncpt(hdr);
769 list_del_init(&m->list); 783 list_del_init(&m->list);
770 list_del_init(&m->small_win); 784 tipc_group_open(m, usr_wakeup);
771 *usr_wakeup = true;
772 tipc_group_decr_active(grp, m); 785 tipc_group_decr_active(grp, m);
773 m->state = MBR_LEAVING; 786 m->state = MBR_LEAVING;
774 tipc_group_create_event(grp, m, TIPC_WITHDRAWN, 787 tipc_group_create_event(grp, m, TIPC_WITHDRAWN,
@@ -778,26 +791,25 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup,
778 if (!m) 791 if (!m)
779 return; 792 return;
780 m->window += msg_adv_win(hdr); 793 m->window += msg_adv_win(hdr);
781 *usr_wakeup = m->usr_pending; 794 tipc_group_open(m, usr_wakeup);
782 m->usr_pending = false;
783 list_del_init(&m->small_win);
784 return; 795 return;
785 case GRP_ACK_MSG: 796 case GRP_ACK_MSG:
786 if (!m) 797 if (!m)
787 return; 798 return;
788 m->bc_acked = msg_grp_bc_acked(hdr); 799 m->bc_acked = msg_grp_bc_acked(hdr);
789 if (--grp->bc_ackers) 800 if (--grp->bc_ackers)
790 break; 801 return;
802 list_del_init(&m->small_win);
803 m->group->open = true;
791 *usr_wakeup = true; 804 *usr_wakeup = true;
792 m->usr_pending = false; 805 tipc_group_update_member(m, 0);
793 return; 806 return;
794 case GRP_RECLAIM_MSG: 807 case GRP_RECLAIM_MSG:
795 if (!m) 808 if (!m)
796 return; 809 return;
797 *usr_wakeup = m->usr_pending;
798 m->usr_pending = false;
799 tipc_group_proto_xmit(grp, m, GRP_REMIT_MSG, xmitq); 810 tipc_group_proto_xmit(grp, m, GRP_REMIT_MSG, xmitq);
800 m->window = ADV_IDLE; 811 m->window = ADV_IDLE;
812 tipc_group_open(m, usr_wakeup);
801 return; 813 return;
802 case GRP_REMIT_MSG: 814 case GRP_REMIT_MSG:
803 if (!m || m->state != MBR_RECLAIMING) 815 if (!m || m->state != MBR_RECLAIMING)
@@ -883,9 +895,7 @@ void tipc_group_member_evt(struct tipc_group *grp,
883 /* Member can be taken into service */ 895 /* Member can be taken into service */
884 m->instance = instance; 896 m->instance = instance;
885 m->state = MBR_JOINED; 897 m->state = MBR_JOINED;
886 *usr_wakeup = true; 898 tipc_group_open(m, usr_wakeup);
887 m->usr_pending = false;
888 list_del_init(&m->small_win);
889 tipc_group_update_member(m, 0); 899 tipc_group_update_member(m, 0);
890 tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq); 900 tipc_group_proto_xmit(grp, m, GRP_JOIN_MSG, xmitq);
891 tipc_group_create_event(grp, m, TIPC_PUBLISHED, 901 tipc_group_create_event(grp, m, TIPC_PUBLISHED,
@@ -895,12 +905,10 @@ void tipc_group_member_evt(struct tipc_group *grp,
895 if (!m) 905 if (!m)
896 break; 906 break;
897 907
898 *usr_wakeup = true;
899 m->usr_pending = false;
900 tipc_group_decr_active(grp, m); 908 tipc_group_decr_active(grp, m);
901 m->state = MBR_LEAVING; 909 m->state = MBR_LEAVING;
902 list_del_init(&m->list); 910 list_del_init(&m->list);
903 list_del_init(&m->small_win); 911 tipc_group_open(m, usr_wakeup);
904 912
905 /* Only send event if no LEAVE message can be expected */ 913 /* Only send event if no LEAVE message can be expected */
906 if (!tipc_node_is_up(net, node)) 914 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);
67bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport, 67bool tipc_group_cong(struct tipc_group *grp, u32 dnode, u32 dport,
68 int len, struct tipc_member **m); 68 int len, struct tipc_member **m);
69bool tipc_group_bc_cong(struct tipc_group *grp, int len); 69bool tipc_group_bc_cong(struct tipc_group *grp, int len);
70bool tipc_group_is_open(struct tipc_group *grp);
70void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node, 71void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
71 u32 port, struct sk_buff_head *xmitq); 72 u32 port, struct sk_buff_head *xmitq);
72u16 tipc_group_bc_snd_nxt(struct tipc_group *grp); 73u16 tipc_group_bc_snd_nxt(struct tipc_group *grp);
73void tipc_group_update_member(struct tipc_member *m, int len); 74void tipc_group_update_member(struct tipc_member *m, int len);
74int tipc_group_size(struct tipc_group *grp);
75#endif 75#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,
715{ 715{
716 struct sock *sk = sock->sk; 716 struct sock *sk = sock->sk;
717 struct tipc_sock *tsk = tipc_sk(sk); 717 struct tipc_sock *tsk = tipc_sk(sk);
718 struct tipc_group *grp = tsk->group; 718 struct tipc_group *grp;
719 u32 revents = 0; 719 u32 revents = 0;
720 720
721 sock_poll_wait(file, sk_sleep(sk), wait); 721 sock_poll_wait(file, sk_sleep(sk), wait);
@@ -736,9 +736,9 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
736 revents |= POLLIN | POLLRDNORM; 736 revents |= POLLIN | POLLRDNORM;
737 break; 737 break;
738 case TIPC_OPEN: 738 case TIPC_OPEN:
739 if (!grp || tipc_group_size(grp)) 739 grp = tsk->group;
740 if (!tsk->cong_link_cnt) 740 if ((!grp || tipc_group_is_open(grp)) && !tsk->cong_link_cnt)
741 revents |= POLLOUT; 741 revents |= POLLOUT;
742 if (!tipc_sk_type_connectionless(sk)) 742 if (!tipc_sk_type_connectionless(sk))
743 break; 743 break;
744 if (skb_queue_empty(&sk->sk_receive_queue)) 744 if (skb_queue_empty(&sk->sk_receive_queue))