aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Fastabend <john.fastabend@gmail.com>2014-09-28 14:53:57 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-30 01:02:26 -0400
commit6401585366326fc0ecbc372ec60d1a15cd8be2f5 (patch)
treec3e8f777a579ee8b912e98d06ceb2aa1ffbb6a8b
parent25331d6ce42bcf4b34b6705fce4da15c3fabe62f (diff)
net: sched: restrict use of qstats qlen
This removes the use of qstats->qlen variable from the classifiers and makes it an explicit argument to gnet_stats_copy_queue(). The qlen represents the qdisc queue length and is packed into the qstats at the last moment before passnig to user space. By handling it explicitely we avoid, in the percpu stats case, having to figure out which per_cpu variable to put it in. It would probably be best to remove it from qstats completely but qstats is a user space ABI and can't be broken. A future patch could make an internal only qstats structure that would avoid having to allocate an additional u32 variable on the Qdisc struct. This would make the qstats struct 128bits instead of 128+32. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/gen_stats.h3
-rw-r--r--net/core/gen_stats.c6
-rw-r--r--net/sched/act_api.c4
-rw-r--r--net/sched/sch_api.c5
-rw-r--r--net/sched/sch_atm.c4
-rw-r--r--net/sched/sch_cbq.c3
-rw-r--r--net/sched/sch_drr.c7
-rw-r--r--net/sched/sch_fq_codel.c2
-rw-r--r--net/sched/sch_hfsc.c3
-rw-r--r--net/sched/sch_htb.c5
-rw-r--r--net/sched/sch_mq.c4
-rw-r--r--net/sched/sch_mqprio.c9
-rw-r--r--net/sched/sch_multiq.c3
-rw-r--r--net/sched/sch_prio.c3
-rw-r--r--net/sched/sch_qfq.c3
-rw-r--r--net/sched/sch_sfq.c2
16 files changed, 32 insertions, 34 deletions
diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h
index ce3c1281f2a0..de9b3dd5750e 100644
--- a/include/net/gen_stats.h
+++ b/include/net/gen_stats.h
@@ -40,7 +40,8 @@ void __gnet_stats_copy_basic(struct gnet_stats_basic_packed *bstats,
40int gnet_stats_copy_rate_est(struct gnet_dump *d, 40int gnet_stats_copy_rate_est(struct gnet_dump *d,
41 const struct gnet_stats_basic_packed *b, 41 const struct gnet_stats_basic_packed *b,
42 struct gnet_stats_rate_est64 *r); 42 struct gnet_stats_rate_est64 *r);
43int gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q); 43int gnet_stats_copy_queue(struct gnet_dump *d,
44 struct gnet_stats_queue *q, __u32 len);
44int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len); 45int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
45 46
46int gnet_stats_finish_copy(struct gnet_dump *d); 47int gnet_stats_finish_copy(struct gnet_dump *d);
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c
index 5ff8e80fe0bb..ad3ecb6ba835 100644
--- a/net/core/gen_stats.c
+++ b/net/core/gen_stats.c
@@ -219,6 +219,7 @@ EXPORT_SYMBOL(gnet_stats_copy_rate_est);
219 * gnet_stats_copy_queue - copy queue statistics into statistics TLV 219 * gnet_stats_copy_queue - copy queue statistics into statistics TLV
220 * @d: dumping handle 220 * @d: dumping handle
221 * @q: queue statistics 221 * @q: queue statistics
222 * @qlen: queue length statistics
222 * 223 *
223 * Appends the queue statistics to the top level TLV created by 224 * Appends the queue statistics to the top level TLV created by
224 * gnet_stats_start_copy(). 225 * gnet_stats_start_copy().
@@ -227,8 +228,11 @@ EXPORT_SYMBOL(gnet_stats_copy_rate_est);
227 * if the room in the socket buffer was not sufficient. 228 * if the room in the socket buffer was not sufficient.
228 */ 229 */
229int 230int
230gnet_stats_copy_queue(struct gnet_dump *d, struct gnet_stats_queue *q) 231gnet_stats_copy_queue(struct gnet_dump *d,
232 struct gnet_stats_queue *q, __u32 qlen)
231{ 233{
234 q->qlen = qlen;
235
232 if (d->compat_tc_stats) { 236 if (d->compat_tc_stats) {
233 d->tc_stats.drops = q->drops; 237 d->tc_stats.drops = q->drops;
234 d->tc_stats.qlen = q->qlen; 238 d->tc_stats.qlen = q->qlen;
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index eca4cf9ece2f..2e134093b8ec 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -623,7 +623,9 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
623 if (gnet_stats_copy_basic(&d, NULL, &p->tcfc_bstats) < 0 || 623 if (gnet_stats_copy_basic(&d, NULL, &p->tcfc_bstats) < 0 ||
624 gnet_stats_copy_rate_est(&d, &p->tcfc_bstats, 624 gnet_stats_copy_rate_est(&d, &p->tcfc_bstats,
625 &p->tcfc_rate_est) < 0 || 625 &p->tcfc_rate_est) < 0 ||
626 gnet_stats_copy_queue(&d, &p->tcfc_qstats) < 0) 626 gnet_stats_copy_queue(&d,
627 &p->tcfc_qstats,
628 p->tcfc_qstats.qlen) < 0)
627 goto errout; 629 goto errout;
628 630
629 if (gnet_stats_finish_copy(&d) < 0) 631 if (gnet_stats_finish_copy(&d) < 0)
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 2862bc61a358..ca00ea8e84dc 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1318,6 +1318,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
1318 unsigned char *b = skb_tail_pointer(skb); 1318 unsigned char *b = skb_tail_pointer(skb);
1319 struct gnet_dump d; 1319 struct gnet_dump d;
1320 struct qdisc_size_table *stab; 1320 struct qdisc_size_table *stab;
1321 __u32 qlen;
1321 1322
1322 cond_resched(); 1323 cond_resched();
1323 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags); 1324 nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags);
@@ -1335,7 +1336,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
1335 goto nla_put_failure; 1336 goto nla_put_failure;
1336 if (q->ops->dump && q->ops->dump(q, skb) < 0) 1337 if (q->ops->dump && q->ops->dump(q, skb) < 0)
1337 goto nla_put_failure; 1338 goto nla_put_failure;
1338 q->qstats.qlen = q->q.qlen; 1339 qlen = q->q.qlen;
1339 1340
1340 stab = rtnl_dereference(q->stab); 1341 stab = rtnl_dereference(q->stab);
1341 if (stab && qdisc_dump_stab(skb, stab) < 0) 1342 if (stab && qdisc_dump_stab(skb, stab) < 0)
@@ -1353,7 +1354,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
1353 1354
1354 if (gnet_stats_copy_basic(&d, cpu_bstats, &q->bstats) < 0 || 1355 if (gnet_stats_copy_basic(&d, cpu_bstats, &q->bstats) < 0 ||
1355 gnet_stats_copy_rate_est(&d, &q->bstats, &q->rate_est) < 0 || 1356 gnet_stats_copy_rate_est(&d, &q->bstats, &q->rate_est) < 0 ||
1356 gnet_stats_copy_queue(&d, &q->qstats) < 0) 1357 gnet_stats_copy_queue(&d, &q->qstats, qlen) < 0)
1357 goto nla_put_failure; 1358 goto nla_put_failure;
1358 1359
1359 if (gnet_stats_finish_copy(&d) < 0) 1360 if (gnet_stats_finish_copy(&d) < 0)
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 040212cab988..c145eb6279cc 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -637,10 +637,8 @@ atm_tc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
637{ 637{
638 struct atm_flow_data *flow = (struct atm_flow_data *)arg; 638 struct atm_flow_data *flow = (struct atm_flow_data *)arg;
639 639
640 flow->qstats.qlen = flow->q->q.qlen;
641
642 if (gnet_stats_copy_basic(d, NULL, &flow->bstats) < 0 || 640 if (gnet_stats_copy_basic(d, NULL, &flow->bstats) < 0 ||
643 gnet_stats_copy_queue(d, &flow->qstats) < 0) 641 gnet_stats_copy_queue(d, &flow->qstats, flow->q->q.qlen) < 0)
644 return -1; 642 return -1;
645 643
646 return 0; 644 return 0;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 60432c3d3cd4..c610081ffba5 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1594,7 +1594,6 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
1594 struct cbq_sched_data *q = qdisc_priv(sch); 1594 struct cbq_sched_data *q = qdisc_priv(sch);
1595 struct cbq_class *cl = (struct cbq_class *)arg; 1595 struct cbq_class *cl = (struct cbq_class *)arg;
1596 1596
1597 cl->qstats.qlen = cl->q->q.qlen;
1598 cl->xstats.avgidle = cl->avgidle; 1597 cl->xstats.avgidle = cl->avgidle;
1599 cl->xstats.undertime = 0; 1598 cl->xstats.undertime = 0;
1600 1599
@@ -1603,7 +1602,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
1603 1602
1604 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 || 1603 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
1605 gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 || 1604 gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
1606 gnet_stats_copy_queue(d, &cl->qstats) < 0) 1605 gnet_stats_copy_queue(d, &cl->qstats, cl->q->q.qlen) < 0)
1607 return -1; 1606 return -1;
1608 1607
1609 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats)); 1608 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 907b12fd6825..5835a93905b1 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -275,17 +275,16 @@ static int drr_dump_class_stats(struct Qdisc *sch, unsigned long arg,
275 struct gnet_dump *d) 275 struct gnet_dump *d)
276{ 276{
277 struct drr_class *cl = (struct drr_class *)arg; 277 struct drr_class *cl = (struct drr_class *)arg;
278 __u32 qlen = cl->qdisc->q.qlen;
278 struct tc_drr_stats xstats; 279 struct tc_drr_stats xstats;
279 280
280 memset(&xstats, 0, sizeof(xstats)); 281 memset(&xstats, 0, sizeof(xstats));
281 if (cl->qdisc->q.qlen) { 282 if (qlen)
282 xstats.deficit = cl->deficit; 283 xstats.deficit = cl->deficit;
283 cl->qdisc->qstats.qlen = cl->qdisc->q.qlen;
284 }
285 284
286 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 || 285 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
287 gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 || 286 gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
288 gnet_stats_copy_queue(d, &cl->qdisc->qstats) < 0) 287 gnet_stats_copy_queue(d, &cl->qdisc->qstats, qlen) < 0)
289 return -1; 288 return -1;
290 289
291 return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); 290 return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index 9270e1b2f25d..226d73597539 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -550,7 +550,7 @@ static int fq_codel_dump_class_stats(struct Qdisc *sch, unsigned long cl,
550 qs.backlog = q->backlogs[idx]; 550 qs.backlog = q->backlogs[idx];
551 qs.drops = flow->dropped; 551 qs.drops = flow->dropped;
552 } 552 }
553 if (gnet_stats_copy_queue(d, &qs) < 0) 553 if (gnet_stats_copy_queue(d, &qs, 0) < 0)
554 return -1; 554 return -1;
555 if (idx < q->flows_cnt) 555 if (idx < q->flows_cnt)
556 return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); 556 return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index ad278251d811..d364acb2ad07 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1370,7 +1370,6 @@ hfsc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
1370 struct hfsc_class *cl = (struct hfsc_class *)arg; 1370 struct hfsc_class *cl = (struct hfsc_class *)arg;
1371 struct tc_hfsc_stats xstats; 1371 struct tc_hfsc_stats xstats;
1372 1372
1373 cl->qstats.qlen = cl->qdisc->q.qlen;
1374 cl->qstats.backlog = cl->qdisc->qstats.backlog; 1373 cl->qstats.backlog = cl->qdisc->qstats.backlog;
1375 xstats.level = cl->level; 1374 xstats.level = cl->level;
1376 xstats.period = cl->cl_vtperiod; 1375 xstats.period = cl->cl_vtperiod;
@@ -1379,7 +1378,7 @@ hfsc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
1379 1378
1380 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 || 1379 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
1381 gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 || 1380 gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
1382 gnet_stats_copy_queue(d, &cl->qstats) < 0) 1381 gnet_stats_copy_queue(d, &cl->qstats, cl->qdisc->q.qlen) < 0)
1383 return -1; 1382 return -1;
1384 1383
1385 return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); 1384 return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index c40ab7a98c50..3a691fd88f99 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1138,15 +1138,16 @@ static int
1138htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d) 1138htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
1139{ 1139{
1140 struct htb_class *cl = (struct htb_class *)arg; 1140 struct htb_class *cl = (struct htb_class *)arg;
1141 __u32 qlen = 0;
1141 1142
1142 if (!cl->level && cl->un.leaf.q) 1143 if (!cl->level && cl->un.leaf.q)
1143 cl->qstats.qlen = cl->un.leaf.q->q.qlen; 1144 qlen = cl->un.leaf.q->q.qlen;
1144 cl->xstats.tokens = PSCHED_NS2TICKS(cl->tokens); 1145 cl->xstats.tokens = PSCHED_NS2TICKS(cl->tokens);
1145 cl->xstats.ctokens = PSCHED_NS2TICKS(cl->ctokens); 1146 cl->xstats.ctokens = PSCHED_NS2TICKS(cl->ctokens);
1146 1147
1147 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 || 1148 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
1148 gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 || 1149 gnet_stats_copy_rate_est(d, NULL, &cl->rate_est) < 0 ||
1149 gnet_stats_copy_queue(d, &cl->qstats) < 0) 1150 gnet_stats_copy_queue(d, &cl->qstats, qlen) < 0)
1150 return -1; 1151 return -1;
1151 1152
1152 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats)); 1153 return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index d3a27fb607af..6416a6942062 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -112,7 +112,6 @@ static int mq_dump(struct Qdisc *sch, struct sk_buff *skb)
112 sch->q.qlen += qdisc->q.qlen; 112 sch->q.qlen += qdisc->q.qlen;
113 sch->bstats.bytes += qdisc->bstats.bytes; 113 sch->bstats.bytes += qdisc->bstats.bytes;
114 sch->bstats.packets += qdisc->bstats.packets; 114 sch->bstats.packets += qdisc->bstats.packets;
115 sch->qstats.qlen += qdisc->qstats.qlen;
116 sch->qstats.backlog += qdisc->qstats.backlog; 115 sch->qstats.backlog += qdisc->qstats.backlog;
117 sch->qstats.drops += qdisc->qstats.drops; 116 sch->qstats.drops += qdisc->qstats.drops;
118 sch->qstats.requeues += qdisc->qstats.requeues; 117 sch->qstats.requeues += qdisc->qstats.requeues;
@@ -200,9 +199,8 @@ static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
200 struct netdev_queue *dev_queue = mq_queue_get(sch, cl); 199 struct netdev_queue *dev_queue = mq_queue_get(sch, cl);
201 200
202 sch = dev_queue->qdisc_sleeping; 201 sch = dev_queue->qdisc_sleeping;
203 sch->qstats.qlen = sch->q.qlen;
204 if (gnet_stats_copy_basic(d, NULL, &sch->bstats) < 0 || 202 if (gnet_stats_copy_basic(d, NULL, &sch->bstats) < 0 ||
205 gnet_stats_copy_queue(d, &sch->qstats) < 0) 203 gnet_stats_copy_queue(d, &sch->qstats, sch->q.qlen) < 0)
206 return -1; 204 return -1;
207 return 0; 205 return 0;
208} 206}
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index 8917372fddc6..03dbeb5e8181 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -236,7 +236,6 @@ static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb)
236 sch->q.qlen += qdisc->q.qlen; 236 sch->q.qlen += qdisc->q.qlen;
237 sch->bstats.bytes += qdisc->bstats.bytes; 237 sch->bstats.bytes += qdisc->bstats.bytes;
238 sch->bstats.packets += qdisc->bstats.packets; 238 sch->bstats.packets += qdisc->bstats.packets;
239 sch->qstats.qlen += qdisc->qstats.qlen;
240 sch->qstats.backlog += qdisc->qstats.backlog; 239 sch->qstats.backlog += qdisc->qstats.backlog;
241 sch->qstats.drops += qdisc->qstats.drops; 240 sch->qstats.drops += qdisc->qstats.drops;
242 sch->qstats.requeues += qdisc->qstats.requeues; 241 sch->qstats.requeues += qdisc->qstats.requeues;
@@ -327,6 +326,7 @@ static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
327 326
328 if (cl <= netdev_get_num_tc(dev)) { 327 if (cl <= netdev_get_num_tc(dev)) {
329 int i; 328 int i;
329 __u32 qlen = 0;
330 struct Qdisc *qdisc; 330 struct Qdisc *qdisc;
331 struct gnet_stats_queue qstats = {0}; 331 struct gnet_stats_queue qstats = {0};
332 struct gnet_stats_basic_packed bstats = {0}; 332 struct gnet_stats_basic_packed bstats = {0};
@@ -344,9 +344,9 @@ static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
344 344
345 qdisc = rtnl_dereference(q->qdisc); 345 qdisc = rtnl_dereference(q->qdisc);
346 spin_lock_bh(qdisc_lock(qdisc)); 346 spin_lock_bh(qdisc_lock(qdisc));
347 qlen += qdisc->q.qlen;
347 bstats.bytes += qdisc->bstats.bytes; 348 bstats.bytes += qdisc->bstats.bytes;
348 bstats.packets += qdisc->bstats.packets; 349 bstats.packets += qdisc->bstats.packets;
349 qstats.qlen += qdisc->qstats.qlen;
350 qstats.backlog += qdisc->qstats.backlog; 350 qstats.backlog += qdisc->qstats.backlog;
351 qstats.drops += qdisc->qstats.drops; 351 qstats.drops += qdisc->qstats.drops;
352 qstats.requeues += qdisc->qstats.requeues; 352 qstats.requeues += qdisc->qstats.requeues;
@@ -356,15 +356,14 @@ static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
356 /* Reclaim root sleeping lock before completing stats */ 356 /* Reclaim root sleeping lock before completing stats */
357 spin_lock_bh(d->lock); 357 spin_lock_bh(d->lock);
358 if (gnet_stats_copy_basic(d, NULL, &bstats) < 0 || 358 if (gnet_stats_copy_basic(d, NULL, &bstats) < 0 ||
359 gnet_stats_copy_queue(d, &qstats) < 0) 359 gnet_stats_copy_queue(d, &qstats, qlen) < 0)
360 return -1; 360 return -1;
361 } else { 361 } else {
362 struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl); 362 struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl);
363 363
364 sch = dev_queue->qdisc_sleeping; 364 sch = dev_queue->qdisc_sleeping;
365 sch->qstats.qlen = sch->q.qlen;
366 if (gnet_stats_copy_basic(d, NULL, &sch->bstats) < 0 || 365 if (gnet_stats_copy_basic(d, NULL, &sch->bstats) < 0 ||
367 gnet_stats_copy_queue(d, &sch->qstats) < 0) 366 gnet_stats_copy_queue(d, &sch->qstats, sch->q.qlen) < 0)
368 return -1; 367 return -1;
369 } 368 }
370 return 0; 369 return 0;
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 7f4e1d8504b0..53357b368bff 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -360,9 +360,8 @@ static int multiq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
360 struct Qdisc *cl_q; 360 struct Qdisc *cl_q;
361 361
362 cl_q = q->queues[cl - 1]; 362 cl_q = q->queues[cl - 1];
363 cl_q->qstats.qlen = cl_q->q.qlen;
364 if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 || 363 if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 ||
365 gnet_stats_copy_queue(d, &cl_q->qstats) < 0) 364 gnet_stats_copy_queue(d, &cl_q->qstats, cl_q->q.qlen) < 0)
366 return -1; 365 return -1;
367 366
368 return 0; 367 return 0;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index b411e78a02fc..4644f55242d2 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -324,9 +324,8 @@ static int prio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
324 struct Qdisc *cl_q; 324 struct Qdisc *cl_q;
325 325
326 cl_q = q->queues[cl - 1]; 326 cl_q = q->queues[cl - 1];
327 cl_q->qstats.qlen = cl_q->q.qlen;
328 if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 || 327 if (gnet_stats_copy_basic(d, NULL, &cl_q->bstats) < 0 ||
329 gnet_stats_copy_queue(d, &cl_q->qstats) < 0) 328 gnet_stats_copy_queue(d, &cl_q->qstats, cl_q->q.qlen) < 0)
330 return -1; 329 return -1;
331 330
332 return 0; 331 return 0;
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 3fb26555c79b..66df9d9e301a 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -664,14 +664,13 @@ static int qfq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
664 struct tc_qfq_stats xstats; 664 struct tc_qfq_stats xstats;
665 665
666 memset(&xstats, 0, sizeof(xstats)); 666 memset(&xstats, 0, sizeof(xstats));
667 cl->qdisc->qstats.qlen = cl->qdisc->q.qlen;
668 667
669 xstats.weight = cl->agg->class_weight; 668 xstats.weight = cl->agg->class_weight;
670 xstats.lmax = cl->agg->lmax; 669 xstats.lmax = cl->agg->lmax;
671 670
672 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 || 671 if (gnet_stats_copy_basic(d, NULL, &cl->bstats) < 0 ||
673 gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 || 672 gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
674 gnet_stats_copy_queue(d, &cl->qdisc->qstats) < 0) 673 gnet_stats_copy_queue(d, &cl->qdisc->qstats, cl->qdisc->q.qlen) < 0)
675 return -1; 674 return -1;
676 675
677 return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); 676 return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 158dfa641d18..d4afcbc1c6f7 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -871,7 +871,7 @@ static int sfq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
871 qs.qlen = slot->qlen; 871 qs.qlen = slot->qlen;
872 qs.backlog = slot->backlog; 872 qs.backlog = slot->backlog;
873 } 873 }
874 if (gnet_stats_copy_queue(d, &qs) < 0) 874 if (gnet_stats_copy_queue(d, &qs, qs.qlen) < 0)
875 return -1; 875 return -1;
876 return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); 876 return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
877} 877}