> /** > * gnet_stats_copy_queue - copy queue statistics into statistics TLV > diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c > index 213b586..bc59f05 100644 > --- a/net/sched/sch_mq.c > +++ b/net/sched/sch_mq.c > @@ -17,6 +17,7 @@ > #include <linux/skbuff.h> > #include <net/netlink.h> > #include <net/pkt_sched.h> > +#include <net/sch_generic.h> > > struct mq_sched { > struct Qdisc **qdiscs; > @@ -103,15 +104,25 @@ static int mq_dump(struct Qdisc *sch, struct sk_buff > *skb) > memset(&sch->qstats, 0, sizeof(sch->qstats)); > > for (ntx = 0; ntx < dev->num_tx_queues; ntx++) { > + struct gnet_stats_basic_cpu __percpu *cpu_bstats = NULL; > + struct gnet_stats_queue __percpu *cpu_qstats = NULL; > + __u32 qlen = 0; > + > qdisc = netdev_get_tx_queue(dev, ntx)->qdisc_sleeping; > spin_lock_bh(qdisc_lock(qdisc)); > - sch->q.qlen += qdisc->q.qlen; > - sch->bstats.bytes += qdisc->bstats.bytes; > - sch->bstats.packets += qdisc->bstats.packets; > - sch->qstats.backlog += qdisc->qstats.backlog; > - sch->qstats.drops += qdisc->qstats.drops; > - sch->qstats.requeues += qdisc->qstats.requeues; > - sch->qstats.overlimits += qdisc->qstats.overlimits; > + > + if (qdisc_is_percpu_stats(qdisc)) { > + cpu_bstats = qdisc->cpu_bstats; > + cpu_qstats = qdisc->cpu_qstats; > + }
Else, these fields are NULL. So no need for the intermediate variables. > + > + qlen = qdisc_qlen_sum(qdisc); > + > + __gnet_stats_copy_basic(NULL, &sch->bstats, > + cpu_bstats, &qdisc->bstats); > + __gnet_stats_copy_queue(&sch->qstats, > + cpu_qstats, &qdisc->qstats, qlen); These functions add if the percpu variant is taken, but assign otherwise, so overwrite on each iteration of the loop.