diff options
author | David S. Miller <davem@davemloft.net> | 2016-06-15 14:08:36 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-06-15 14:08:36 -0700 |
commit | 88da48f4977a4b31e03cac1b6ea38f24d7916d10 (patch) | |
tree | 462e30cb64cf066c1d13cd98eb0ea502115bafda /net/sched/sch_choke.c | |
parent | 35c55c9877f8de0ab129fa1a309271d0ecc868b9 (diff) | |
parent | fea024784f588a1c50e7718d6053697ebdcc033e (diff) | |
download | linux-stericsson-88da48f4977a4b31e03cac1b6ea38f24d7916d10.tar.gz |
Merge branch 'sched_skb_free_defer'
Eric Dumazet says:
====================
net_sched: defer skb freeing while changing qdiscs
qdiscs/classes are changed under RTNL protection and often
while blocking BH and root qdisc spinlock.
When lots of skbs need to be dropped, we free
them under these locks causing TX/RX freezes,
and more generally latency spikes.
I saw spikes of 50+ ms on quite fast hardware...
This patch series adds a simple queue protected by RTNL
where skbs can be placed until RTNL is released.
Note that this might also serve in the future for optional
reinjection of packets when a qdisc is replaced.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_choke.c')
-rw-r--r-- | net/sched/sch_choke.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index 04e0b0583e00..789b69ee9e51 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -375,11 +375,11 @@ static void choke_reset(struct Qdisc *sch) q->head = (q->head + 1) & q->tab_mask; if (!skb) continue; - qdisc_qstats_backlog_dec(sch, skb); - --sch->q.qlen; - qdisc_drop(skb, sch); + rtnl_qdisc_drop(skb, sch); } + sch->q.qlen = 0; + sch->qstats.backlog = 0; memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *)); q->head = q->tail = 0; red_restart(&q->vars); @@ -455,7 +455,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt) dropped += qdisc_pkt_len(skb); qdisc_qstats_backlog_dec(sch, skb); --sch->q.qlen; - qdisc_drop(skb, sch); + rtnl_qdisc_drop(skb, sch); } qdisc_tree_reduce_backlog(sch, oqlen - sch->q.qlen, dropped); q->head = 0; |