summaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorJon Maloy <jon.maloy@ericsson.com>2019-07-30 10:23:18 -0400
committerDavid S. Miller <davem@davemloft.net>2019-08-01 18:19:28 -0400
commit7c5b42055964f587e55bd87ef334c3a27e95d144 (patch)
tree80c6d8b40074cc4914a89db971a7324274adb1ac /net/tipc
parentf7571cde6b0fd0eb410f051d1cac912e4e31e0d8 (diff)
tipc: reduce risk of wakeup queue starvation
In commit 365ad353c256 ("tipc: reduce risk of user starvation during link congestion") we allowed senders to add exactly one list of extra buffers to the link backlog queues during link congestion (aka "oversubscription"). However, the criteria for when to stop adding wakeup messages to the input queue when the overload abates is inaccurate, and may cause starvation problems during very high load. Currently, we stop adding wakeup messages after 10 total failed attempts where we find that there is no space left in the backlog queue for a certain importance level. The counter for this is accumulated across all levels, which may lead the algorithm to leave the loop prematurely, although there may still be plenty of space available at some levels. The result is sometimes that messages near the wakeup queue tail are not added to the input queue as they should be. We now introduce a more exact algorithm, where we keep adding wakeup messages to a level as long as the backlog queue has free slots for the corresponding level, and stop at the moment there are no more such slots or when there are no more wakeup messages to dequeue. Fixes: 365ad35 ("tipc: reduce risk of user starvation during link congestion") Reported-by: Tung Nguyen <tung.q.nguyen@dektech.com.au> 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/link.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2c274777b2dd..dd3155b14654 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -854,18 +854,31 @@ static int link_schedule_user(struct tipc_link *l, struct tipc_msg *hdr)
854 */ 854 */
855static void link_prepare_wakeup(struct tipc_link *l) 855static void link_prepare_wakeup(struct tipc_link *l)
856{ 856{
857 struct sk_buff_head *wakeupq = &l->wakeupq;
858 struct sk_buff_head *inputq = l->inputq;
857 struct sk_buff *skb, *tmp; 859 struct sk_buff *skb, *tmp;
858 int imp, i = 0; 860 struct sk_buff_head tmpq;
861 int avail[5] = {0,};
862 int imp = 0;
863
864 __skb_queue_head_init(&tmpq);
859 865
860 skb_queue_walk_safe(&l->wakeupq, skb, tmp) { 866 for (; imp <= TIPC_SYSTEM_IMPORTANCE; imp++)
867 avail[imp] = l->backlog[imp].limit - l->backlog[imp].len;
868
869 skb_queue_walk_safe(wakeupq, skb, tmp) {
861 imp = TIPC_SKB_CB(skb)->chain_imp; 870 imp = TIPC_SKB_CB(skb)->chain_imp;
862 if (l->backlog[imp].len < l->backlog[imp].limit) { 871 if (avail[imp] <= 0)
863 skb_unlink(skb, &l->wakeupq); 872 continue;
864 skb_queue_tail(l->inputq, skb); 873 avail[imp]--;
865 } else if (i++ > 10) { 874 __skb_unlink(skb, wakeupq);
866 break; 875 __skb_queue_tail(&tmpq, skb);
867 }
868 } 876 }
877
878 spin_lock_bh(&inputq->lock);
879 skb_queue_splice_tail(&tmpq, inputq);
880 spin_unlock_bh(&inputq->lock);
881
869} 882}
870 883
871void tipc_link_reset(struct tipc_link *l) 884void tipc_link_reset(struct tipc_link *l)