Skip to content

Commit 5dd431b

Browse files
Paolo Abenidavem330
authored andcommitted
net: sched: introduce and use qstats read helpers
Classful qdiscs can't access directly the child qdiscs backlog length: if such qdisc is NOLOCK, per CPU values should be accounted instead. Most qdiscs no not respect the above. As a result, qstats fetching for most classful qdisc is currently incorrect: if the child qdisc is NOLOCK, it always reports 0 len backlog. This change introduces a pair of helpers to safely fetch both backlog and qlen and use them in stats class dumping functions, fixing the above issue and cleaning a bit the code. DRR needs also to access the child qdisc queue length, so it needs custom handling. Fixes: c5ad119 ("net: sched: pfifo_fast use skb_array") Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0db6f8b commit 5dd431b

File tree

11 files changed

+36
-17
lines changed

11 files changed

+36
-17
lines changed

include/net/sch_generic.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,24 @@ static inline void qdisc_qstats_overlimit(struct Qdisc *sch)
923923
sch->qstats.overlimits++;
924924
}
925925

926+
static inline int qdisc_qstats_copy(struct gnet_dump *d, struct Qdisc *sch)
927+
{
928+
__u32 qlen = qdisc_qlen_sum(sch);
929+
930+
return gnet_stats_copy_queue(d, sch->cpu_qstats, &sch->qstats, qlen);
931+
}
932+
933+
static inline void qdisc_qstats_qlen_backlog(struct Qdisc *sch, __u32 *qlen,
934+
__u32 *backlog)
935+
{
936+
struct gnet_stats_queue qstats = { 0 };
937+
__u32 len = qdisc_qlen_sum(sch);
938+
939+
__gnet_stats_copy_queue(&qstats, sch->cpu_qstats, &sch->qstats, len);
940+
*qlen = qstats.qlen;
941+
*backlog = qstats.backlog;
942+
}
943+
926944
static inline void qdisc_skb_head_init(struct qdisc_skb_head *qh)
927945
{
928946
qh->head = NULL;

net/sched/sch_cbq.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,17 +1358,19 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
13581358
{
13591359
struct cbq_sched_data *q = qdisc_priv(sch);
13601360
struct cbq_class *cl = (struct cbq_class *)arg;
1361+
__u32 qlen;
13611362

13621363
cl->xstats.avgidle = cl->avgidle;
13631364
cl->xstats.undertime = 0;
1365+
qdisc_qstats_qlen_backlog(cl->q, &qlen, &cl->qstats.backlog);
13641366

13651367
if (cl->undertime != PSCHED_PASTPERFECT)
13661368
cl->xstats.undertime = cl->undertime - q->now;
13671369

13681370
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
13691371
d, NULL, &cl->bstats) < 0 ||
13701372
gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
1371-
gnet_stats_copy_queue(d, NULL, &cl->qstats, cl->q->q.qlen) < 0)
1373+
gnet_stats_copy_queue(d, NULL, &cl->qstats, qlen) < 0)
13721374
return -1;
13731375

13741376
return gnet_stats_copy_app(d, &cl->xstats, sizeof(cl->xstats));

net/sched/sch_drr.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ static int drr_dump_class_stats(struct Qdisc *sch, unsigned long arg,
269269
struct gnet_dump *d)
270270
{
271271
struct drr_class *cl = (struct drr_class *)arg;
272-
__u32 qlen = cl->qdisc->q.qlen;
272+
__u32 qlen = qdisc_qlen_sum(cl->qdisc);
273+
struct Qdisc *cl_q = cl->qdisc;
273274
struct tc_drr_stats xstats;
274275

275276
memset(&xstats, 0, sizeof(xstats));
@@ -279,7 +280,7 @@ static int drr_dump_class_stats(struct Qdisc *sch, unsigned long arg,
279280
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
280281
d, NULL, &cl->bstats) < 0 ||
281282
gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
282-
gnet_stats_copy_queue(d, NULL, &cl->qdisc->qstats, qlen) < 0)
283+
gnet_stats_copy_queue(d, cl_q->cpu_qstats, &cl_q->qstats, qlen) < 0)
283284
return -1;
284285

285286
return gnet_stats_copy_app(d, &xstats, sizeof(xstats));

net/sched/sch_hfsc.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,16 +1328,17 @@ hfsc_dump_class_stats(struct Qdisc *sch, unsigned long arg,
13281328
{
13291329
struct hfsc_class *cl = (struct hfsc_class *)arg;
13301330
struct tc_hfsc_stats xstats;
1331+
__u32 qlen;
13311332

1332-
cl->qstats.backlog = cl->qdisc->qstats.backlog;
1333+
qdisc_qstats_qlen_backlog(cl->qdisc, &qlen, &cl->qstats.backlog);
13331334
xstats.level = cl->level;
13341335
xstats.period = cl->cl_vtperiod;
13351336
xstats.work = cl->cl_total;
13361337
xstats.rtwork = cl->cl_cumul;
13371338

13381339
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch), d, NULL, &cl->bstats) < 0 ||
13391340
gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
1340-
gnet_stats_copy_queue(d, NULL, &cl->qstats, cl->qdisc->q.qlen) < 0)
1341+
gnet_stats_copy_queue(d, NULL, &cl->qstats, qlen) < 0)
13411342
return -1;
13421343

13431344
return gnet_stats_copy_app(d, &xstats, sizeof(xstats));

net/sched/sch_htb.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,10 +1127,9 @@ htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d)
11271127
};
11281128
__u32 qlen = 0;
11291129

1130-
if (!cl->level && cl->leaf.q) {
1131-
qlen = cl->leaf.q->q.qlen;
1132-
qs.backlog = cl->leaf.q->qstats.backlog;
1133-
}
1130+
if (!cl->level && cl->leaf.q)
1131+
qdisc_qstats_qlen_backlog(cl->leaf.q, &qlen, &qs.backlog);
1132+
11341133
cl->xstats.tokens = clamp_t(s64, PSCHED_NS2TICKS(cl->tokens),
11351134
INT_MIN, INT_MAX);
11361135
cl->xstats.ctokens = clamp_t(s64, PSCHED_NS2TICKS(cl->ctokens),

net/sched/sch_mq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ static int mq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
249249

250250
sch = dev_queue->qdisc_sleeping;
251251
if (gnet_stats_copy_basic(&sch->running, d, NULL, &sch->bstats) < 0 ||
252-
gnet_stats_copy_queue(d, NULL, &sch->qstats, sch->q.qlen) < 0)
252+
qdisc_qstats_copy(d, sch) < 0)
253253
return -1;
254254
return 0;
255255
}

net/sched/sch_mqprio.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,7 @@ static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
561561
sch = dev_queue->qdisc_sleeping;
562562
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
563563
d, NULL, &sch->bstats) < 0 ||
564-
gnet_stats_copy_queue(d, NULL,
565-
&sch->qstats, sch->q.qlen) < 0)
564+
qdisc_qstats_copy(d, sch) < 0)
566565
return -1;
567566
}
568567
return 0;

net/sched/sch_multiq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ static int multiq_dump_class_stats(struct Qdisc *sch, unsigned long cl,
344344
cl_q = q->queues[cl - 1];
345345
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
346346
d, NULL, &cl_q->bstats) < 0 ||
347-
gnet_stats_copy_queue(d, NULL, &cl_q->qstats, cl_q->q.qlen) < 0)
347+
qdisc_qstats_copy(d, cl_q) < 0)
348348
return -1;
349349

350350
return 0;

net/sched/sch_prio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ static int prio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
365365
cl_q = q->queues[cl - 1];
366366
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
367367
d, NULL, &cl_q->bstats) < 0 ||
368-
gnet_stats_copy_queue(d, NULL, &cl_q->qstats, cl_q->q.qlen) < 0)
368+
qdisc_qstats_copy(d, cl_q) < 0)
369369
return -1;
370370

371371
return 0;

net/sched/sch_qfq.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,7 @@ static int qfq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
655655
if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch),
656656
d, NULL, &cl->bstats) < 0 ||
657657
gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
658-
gnet_stats_copy_queue(d, NULL,
659-
&cl->qdisc->qstats, cl->qdisc->q.qlen) < 0)
658+
qdisc_qstats_copy(d, cl->qdisc) < 0)
660659
return -1;
661660

662661
return gnet_stats_copy_app(d, &xstats, sizeof(xstats));

net/sched/sch_taprio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ static int taprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
895895

896896
sch = dev_queue->qdisc_sleeping;
897897
if (gnet_stats_copy_basic(&sch->running, d, NULL, &sch->bstats) < 0 ||
898-
gnet_stats_copy_queue(d, NULL, &sch->qstats, sch->q.qlen) < 0)
898+
qdisc_qstats_copy(d, sch) < 0)
899899
return -1;
900900
return 0;
901901
}

0 commit comments

Comments
 (0)