diff options
Diffstat (limited to 'net/tipc/group.c')
| -rw-r--r-- | net/tipc/group.c | 71 |
1 files changed, 48 insertions, 23 deletions
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, | |||
| 109 | static void tipc_group_decr_active(struct tipc_group *grp, | 109 | static void tipc_group_decr_active(struct tipc_group *grp, |
| 110 | struct tipc_member *m) | 110 | struct tipc_member *m) |
| 111 | { | 111 | { |
| 112 | if (m->state == MBR_ACTIVE || m->state == MBR_RECLAIMING) | 112 | if (m->state == MBR_ACTIVE || m->state == MBR_RECLAIMING || |
| 113 | m->state == MBR_REMITTED) | ||
| 113 | grp->active_cnt--; | 114 | grp->active_cnt--; |
| 114 | } | 115 | } |
| 115 | 116 | ||
| @@ -351,8 +352,7 @@ void tipc_group_update_member(struct tipc_member *m, int len) | |||
| 351 | if (m->window >= ADV_IDLE) | 352 | if (m->window >= ADV_IDLE) |
| 352 | return; | 353 | return; |
| 353 | 354 | ||
| 354 | if (!list_empty(&m->congested)) | 355 | list_del_init(&m->congested); |
| 355 | return; | ||
| 356 | 356 | ||
| 357 | /* Sort member into congested members' list */ | 357 | /* Sort member into congested members' list */ |
| 358 | list_for_each_entry_safe(_m, tmp, &grp->congested, congested) { | 358 | 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) | |||
| 369 | u16 prev = grp->bc_snd_nxt - 1; | 369 | u16 prev = grp->bc_snd_nxt - 1; |
| 370 | struct tipc_member *m; | 370 | struct tipc_member *m; |
| 371 | struct rb_node *n; | 371 | struct rb_node *n; |
| 372 | u16 ackers = 0; | ||
| 372 | 373 | ||
| 373 | for (n = rb_first(&grp->members); n; n = rb_next(n)) { | 374 | for (n = rb_first(&grp->members); n; n = rb_next(n)) { |
| 374 | m = container_of(n, struct tipc_member, tree_node); | 375 | m = container_of(n, struct tipc_member, tree_node); |
| 375 | if (tipc_group_is_enabled(m)) { | 376 | if (tipc_group_is_enabled(m)) { |
| 376 | tipc_group_update_member(m, len); | 377 | tipc_group_update_member(m, len); |
| 377 | m->bc_acked = prev; | 378 | m->bc_acked = prev; |
| 379 | ackers++; | ||
| 378 | } | 380 | } |
| 379 | } | 381 | } |
| 380 | 382 | ||
| 381 | /* Mark number of acknowledges to expect, if any */ | 383 | /* Mark number of acknowledges to expect, if any */ |
| 382 | if (ack) | 384 | if (ack) |
| 383 | grp->bc_ackers = grp->member_cnt; | 385 | grp->bc_ackers = ackers; |
| 384 | grp->bc_snd_nxt++; | 386 | grp->bc_snd_nxt++; |
| 385 | } | 387 | } |
| 386 | 388 | ||
| @@ -497,6 +499,7 @@ void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq, | |||
| 497 | while ((skb = skb_peek(defq))) { | 499 | while ((skb = skb_peek(defq))) { |
| 498 | hdr = buf_msg(skb); | 500 | hdr = buf_msg(skb); |
| 499 | mtyp = msg_type(hdr); | 501 | mtyp = msg_type(hdr); |
| 502 | blks = msg_blocks(hdr); | ||
| 500 | deliver = true; | 503 | deliver = true; |
| 501 | ack = false; | 504 | ack = false; |
| 502 | update = false; | 505 | update = false; |
| @@ -546,7 +549,6 @@ void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq, | |||
| 546 | if (!update) | 549 | if (!update) |
| 547 | continue; | 550 | continue; |
| 548 | 551 | ||
| 549 | blks = msg_blocks(hdr); | ||
| 550 | tipc_group_update_rcv_win(grp, blks, node, port, xmitq); | 552 | tipc_group_update_rcv_win(grp, blks, node, port, xmitq); |
| 551 | } | 553 | } |
| 552 | return; | 554 | return; |
| @@ -561,7 +563,7 @@ void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node, | |||
| 561 | int max_active = grp->max_active; | 563 | int max_active = grp->max_active; |
| 562 | int reclaim_limit = max_active * 3 / 4; | 564 | int reclaim_limit = max_active * 3 / 4; |
| 563 | int active_cnt = grp->active_cnt; | 565 | int active_cnt = grp->active_cnt; |
| 564 | struct tipc_member *m, *rm; | 566 | struct tipc_member *m, *rm, *pm; |
| 565 | 567 | ||
| 566 | m = tipc_group_find_member(grp, node, port); | 568 | m = tipc_group_find_member(grp, node, port); |
| 567 | if (!m) | 569 | if (!m) |
| @@ -604,6 +606,17 @@ void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node, | |||
| 604 | pr_warn_ratelimited("Rcv unexpected msg after REMIT\n"); | 606 | pr_warn_ratelimited("Rcv unexpected msg after REMIT\n"); |
| 605 | tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq); | 607 | tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq); |
| 606 | } | 608 | } |
| 609 | grp->active_cnt--; | ||
| 610 | list_del_init(&m->list); | ||
| 611 | if (list_empty(&grp->pending)) | ||
| 612 | return; | ||
| 613 | |||
| 614 | /* Set oldest pending member to active and advertise */ | ||
| 615 | pm = list_first_entry(&grp->pending, struct tipc_member, list); | ||
| 616 | pm->state = MBR_ACTIVE; | ||
| 617 | list_move_tail(&pm->list, &grp->active); | ||
| 618 | grp->active_cnt++; | ||
| 619 | tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq); | ||
| 607 | break; | 620 | break; |
| 608 | case MBR_RECLAIMING: | 621 | case MBR_RECLAIMING: |
| 609 | case MBR_DISCOVERED: | 622 | case MBR_DISCOVERED: |
| @@ -648,6 +661,7 @@ static void tipc_group_proto_xmit(struct tipc_group *grp, struct tipc_member *m, | |||
| 648 | } else if (mtyp == GRP_REMIT_MSG) { | 661 | } else if (mtyp == GRP_REMIT_MSG) { |
| 649 | msg_set_grp_remitted(hdr, m->window); | 662 | msg_set_grp_remitted(hdr, m->window); |
| 650 | } | 663 | } |
| 664 | msg_set_dest_droppable(hdr, true); | ||
| 651 | __skb_queue_tail(xmitq, skb); | 665 | __skb_queue_tail(xmitq, skb); |
| 652 | } | 666 | } |
| 653 | 667 | ||
| @@ -689,15 +703,16 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup, | |||
| 689 | msg_set_grp_bc_seqno(ehdr, m->bc_syncpt); | 703 | msg_set_grp_bc_seqno(ehdr, m->bc_syncpt); |
| 690 | __skb_queue_tail(inputq, m->event_msg); | 704 | __skb_queue_tail(inputq, m->event_msg); |
| 691 | } | 705 | } |
| 692 | if (m->window < ADV_IDLE) | 706 | list_del_init(&m->congested); |
| 693 | tipc_group_update_member(m, 0); | 707 | tipc_group_update_member(m, 0); |
| 694 | else | ||
| 695 | list_del_init(&m->congested); | ||
| 696 | return; | 708 | return; |
| 697 | case GRP_LEAVE_MSG: | 709 | case GRP_LEAVE_MSG: |
| 698 | if (!m) | 710 | if (!m) |
| 699 | return; | 711 | return; |
| 700 | m->bc_syncpt = msg_grp_bc_syncpt(hdr); | 712 | m->bc_syncpt = msg_grp_bc_syncpt(hdr); |
| 713 | list_del_init(&m->list); | ||
| 714 | list_del_init(&m->congested); | ||
| 715 | *usr_wakeup = true; | ||
| 701 | 716 | ||
| 702 | /* Wait until WITHDRAW event is received */ | 717 | /* Wait until WITHDRAW event is received */ |
| 703 | if (m->state != MBR_LEAVING) { | 718 | if (m->state != MBR_LEAVING) { |
| @@ -709,8 +724,6 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup, | |||
| 709 | ehdr = buf_msg(m->event_msg); | 724 | ehdr = buf_msg(m->event_msg); |
| 710 | msg_set_grp_bc_seqno(ehdr, m->bc_syncpt); | 725 | msg_set_grp_bc_seqno(ehdr, m->bc_syncpt); |
| 711 | __skb_queue_tail(inputq, m->event_msg); | 726 | __skb_queue_tail(inputq, m->event_msg); |
| 712 | *usr_wakeup = true; | ||
| 713 | list_del_init(&m->congested); | ||
| 714 | return; | 727 | return; |
| 715 | case GRP_ADV_MSG: | 728 | case GRP_ADV_MSG: |
| 716 | if (!m) | 729 | if (!m) |
| @@ -741,14 +754,14 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup, | |||
| 741 | if (!m || m->state != MBR_RECLAIMING) | 754 | if (!m || m->state != MBR_RECLAIMING) |
| 742 | return; | 755 | return; |
| 743 | 756 | ||
| 744 | list_del_init(&m->list); | ||
| 745 | grp->active_cnt--; | ||
| 746 | remitted = msg_grp_remitted(hdr); | 757 | remitted = msg_grp_remitted(hdr); |
| 747 | 758 | ||
| 748 | /* Messages preceding the REMIT still in receive queue */ | 759 | /* Messages preceding the REMIT still in receive queue */ |
| 749 | if (m->advertised > remitted) { | 760 | if (m->advertised > remitted) { |
| 750 | m->state = MBR_REMITTED; | 761 | m->state = MBR_REMITTED; |
| 751 | in_flight = m->advertised - remitted; | 762 | in_flight = m->advertised - remitted; |
| 763 | m->advertised = ADV_IDLE + in_flight; | ||
| 764 | return; | ||
| 752 | } | 765 | } |
| 753 | /* All messages preceding the REMIT have been read */ | 766 | /* All messages preceding the REMIT have been read */ |
| 754 | if (m->advertised <= remitted) { | 767 | if (m->advertised <= remitted) { |
| @@ -760,6 +773,8 @@ void tipc_group_proto_rcv(struct tipc_group *grp, bool *usr_wakeup, | |||
| 760 | tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq); | 773 | tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq); |
| 761 | 774 | ||
| 762 | m->advertised = ADV_IDLE + in_flight; | 775 | m->advertised = ADV_IDLE + in_flight; |
| 776 | grp->active_cnt--; | ||
| 777 | list_del_init(&m->list); | ||
| 763 | 778 | ||
| 764 | /* Set oldest pending member to active and advertise */ | 779 | /* Set oldest pending member to active and advertise */ |
| 765 | if (list_empty(&grp->pending)) | 780 | if (list_empty(&grp->pending)) |
| @@ -849,19 +864,29 @@ void tipc_group_member_evt(struct tipc_group *grp, | |||
| 849 | *usr_wakeup = true; | 864 | *usr_wakeup = true; |
| 850 | m->usr_pending = false; | 865 | m->usr_pending = false; |
| 851 | node_up = tipc_node_is_up(net, node); | 866 | node_up = tipc_node_is_up(net, node); |
| 852 | 867 | m->event_msg = NULL; | |
| 853 | /* Hold back event if more messages might be expected */ | 868 | |
| 854 | if (m->state != MBR_LEAVING && node_up) { | 869 | if (node_up) { |
| 855 | m->event_msg = skb; | 870 | /* Hold back event if a LEAVE msg should be expected */ |
| 856 | tipc_group_decr_active(grp, m); | 871 | if (m->state != MBR_LEAVING) { |
| 857 | m->state = MBR_LEAVING; | 872 | m->event_msg = skb; |
| 858 | } else { | 873 | tipc_group_decr_active(grp, m); |
| 859 | if (node_up) | 874 | m->state = MBR_LEAVING; |
| 875 | } else { | ||
| 860 | msg_set_grp_bc_seqno(hdr, m->bc_syncpt); | 876 | msg_set_grp_bc_seqno(hdr, m->bc_syncpt); |
| 861 | else | 877 | __skb_queue_tail(inputq, skb); |
| 878 | } | ||
| 879 | } else { | ||
| 880 | if (m->state != MBR_LEAVING) { | ||
| 881 | tipc_group_decr_active(grp, m); | ||
| 882 | m->state = MBR_LEAVING; | ||
| 862 | msg_set_grp_bc_seqno(hdr, m->bc_rcv_nxt); | 883 | msg_set_grp_bc_seqno(hdr, m->bc_rcv_nxt); |
| 884 | } else { | ||
| 885 | msg_set_grp_bc_seqno(hdr, m->bc_syncpt); | ||
| 886 | } | ||
| 863 | __skb_queue_tail(inputq, skb); | 887 | __skb_queue_tail(inputq, skb); |
| 864 | } | 888 | } |
| 889 | list_del_init(&m->list); | ||
| 865 | list_del_init(&m->congested); | 890 | list_del_init(&m->congested); |
| 866 | } | 891 | } |
| 867 | *sk_rcvbuf = tipc_group_rcvbuf_limit(grp); | 892 | *sk_rcvbuf = tipc_group_rcvbuf_limit(grp); |
