net: sched: do not acquire qdisc spinlock in qdisc/class stats dump
Large tc dumps (tc -s {qdisc|class} sh dev ethX) done by Google BwE host agent [1] are problematic at scale : For each qdisc/class found in the dump, we currently lock the root qdisc spinlock in order to get stats. Sampling stats every 5 seconds from thousands of HTB classes is a challenge when the root qdisc spinlock is under high pressure. Not only the dumps take time, they also slow down the fast path (queue/dequeue packets) by 10 % to 20 % in some cases. An audit of existing qdiscs showed that sch_fq_codel is the only qdisc that might need the qdisc lock in fq_codel_dump_stats() and fq_codel_dump_class_stats() In v2 of this patch, I now use the Qdisc running seqcount to provide consistent reads of packets/bytes counters, regardless of 32/64 bit arches. I also changed rate estimators to use the same infrastructure so that they no longer need to lock root qdisc lock. [1] http://static.googleusercontent.com/media/research.google.com/en//pubs/archive/43838.pdf Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Cong Wang <xiyou.wangcong@gmail.com> Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: John Fastabend <john.fastabend@gmail.com> Cc: Kevin Athey <kda@google.com> Cc: Xiaotian Pei <xiaotian@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

zatwierdzone przez
David S. Miller

rodzic
f9eb8aea2a
commit
edb09eb17e
@@ -1141,7 +1141,8 @@ htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
|
||||
cl->xstats.tokens = PSCHED_NS2TICKS(cl->tokens);
|
||||
cl->xstats.ctokens = PSCHED_NS2TICKS(cl->ctokens);
|
||||
|
||||
if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
|
||||
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
|
||||
d, NULL, &cl->bstats) < 0 ||
|
||||
gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 ||
|
||||
gnet_stats_copy_queue(d, NULL, &cl->qstats, qlen) < 0)
|
||||
return -1;
|
||||
@@ -1395,7 +1396,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
|
||||
if (htb_rate_est || tca[TCA_RATE]) {
|
||||
err = gen_new_estimator(&cl->bstats, NULL,
|
||||
&cl->rate_est,
|
||||
qdisc_root_sleeping_lock(sch),
|
||||
NULL,
|
||||
qdisc_root_sleeping_running(sch),
|
||||
tca[TCA_RATE] ? : &est.nla);
|
||||
if (err) {
|
||||
kfree(cl);
|
||||
@@ -1457,11 +1459,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
|
||||
parent->children++;
|
||||
} else {
|
||||
if (tca[TCA_RATE]) {
|
||||
spinlock_t *lock = qdisc_root_sleeping_lock(sch);
|
||||
|
||||
err = gen_replace_estimator(&cl->bstats, NULL,
|
||||
&cl->rate_est,
|
||||
lock,
|
||||
NULL,
|
||||
qdisc_root_sleeping_running(sch),
|
||||
tca[TCA_RATE]);
|
||||
if (err)
|
||||
return err;
|
||||
|
Reference in New Issue
Block a user