aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2018-01-08 15:03:24 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-09 12:35:57 -0500
commit4ea5dab541717fc55cad609360b100857af770b0 (patch)
tree57ab48f7b7bb99a56a81f4a4644659a0da2a94c8 /net/tipc
parent8d5dee21f6f01f4632c10b750709a1383eefc7aa (diff)
tipc: let group member stay in JOINED mode if unable to reclaim
We handle a corner case in the function tipc_group_update_rcv_win(). During extreme pessure it might happen that a message receiver has all its active senders in RECLAIMING or REMITTED mode, meaning that there is nobody to reclaim advertisements from if an additional sender tries to go active. Currently we just set the new sender to ACTIVE anyway, hence at least theoretically opening up for a receiver queue overflow by exceeding the MAX_ACTIVE limit. The correct solution to this is to instead add the member to the pending queue, while letting the oldest member in that queue revert to JOINED state. In this commit we refactor the code for handling message arrival from a JOINED member, both to make it more comprehensible and to cover the case described above. Acked-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/group.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/net/tipc/group.c b/net/tipc/group.c
index e5daeb093879..652fa66a87f6 100644
--- a/net/tipc/group.c
+++ b/net/tipc/group.c
@@ -569,24 +569,34 @@ void tipc_group_update_rcv_win(struct tipc_group *grp, int blks, u32 node,
569 569
570 switch (m->state) { 570 switch (m->state) {
571 case MBR_JOINED: 571 case MBR_JOINED:
572 /* Reclaim advertised space from least active member */ 572 /* First, decide if member can go active */
573 if (!list_empty(active) && active_cnt >= reclaim_limit) { 573 if (active_cnt <= max_active) {
574 m->state = MBR_ACTIVE;
575 list_add_tail(&m->list, active);
576 grp->active_cnt++;
577 tipc_group_proto_xmit(grp, m, GRP_ADV_MSG, xmitq);
578 } else {
579 m->state = MBR_PENDING;
580 list_add_tail(&m->list, &grp->pending);
581 }
582
583 if (active_cnt < reclaim_limit)
584 break;
585
586 /* Reclaim from oldest active member, if possible */
587 if (!list_empty(active)) {
574 rm = list_first_entry(active, struct tipc_member, list); 588 rm = list_first_entry(active, struct tipc_member, list);
575 rm->state = MBR_RECLAIMING; 589 rm->state = MBR_RECLAIMING;
576 list_del_init(&rm->list); 590 list_del_init(&rm->list);
577 tipc_group_proto_xmit(grp, rm, GRP_RECLAIM_MSG, xmitq); 591 tipc_group_proto_xmit(grp, rm, GRP_RECLAIM_MSG, xmitq);
578 }
579 /* If max active, become pending and wait for reclaimed space */
580 if (active_cnt >= max_active) {
581 m->state = MBR_PENDING;
582 list_add_tail(&m->list, &grp->pending);
583 break; 592 break;
584 } 593 }
585 /* Otherwise become active */ 594 /* Nobody to reclaim from; - revert oldest pending to JOINED */
586 m->state = MBR_ACTIVE; 595 pm = list_first_entry(&grp->pending, struct tipc_member, list);
587 list_add_tail(&m->list, &grp->active); 596 list_del_init(&pm->list);
588 grp->active_cnt++; 597 pm->state = MBR_JOINED;
589 /* Fall through */ 598 tipc_group_proto_xmit(grp, pm, GRP_ADV_MSG, xmitq);
599 break;
590 case MBR_ACTIVE: 600 case MBR_ACTIVE:
591 if (!list_is_last(&m->list, &grp->active)) 601 if (!list_is_last(&m->list, &grp->active))
592 list_move_tail(&m->list, &grp->active); 602 list_move_tail(&m->list, &grp->active);