Skip to content

Commit e5f0e8f

Browse files
Paolo Abenidavem330
authored andcommitted
net: sched: introduce and use qdisc tree flush/purge helpers
The same code to flush qdisc tree and purge the qdisc queue is duplicated in many places and in most cases it does not respect NOLOCK qdisc: the global backlog len is used and the per CPU values are ignored. This change addresses the above, factoring-out the relevant code and using the helpers introduced by the previous patch to fetch the correct backlog len. 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 5dd431b commit e5f0e8f

File tree

11 files changed

+35
-73
lines changed

11 files changed

+35
-73
lines changed

include/net/sch_generic.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,23 @@ static inline void qdisc_qstats_qlen_backlog(struct Qdisc *sch, __u32 *qlen,
941941
*backlog = qstats.backlog;
942942
}
943943

944+
static inline void qdisc_tree_flush_backlog(struct Qdisc *sch)
945+
{
946+
__u32 qlen, backlog;
947+
948+
qdisc_qstats_qlen_backlog(sch, &qlen, &backlog);
949+
qdisc_tree_reduce_backlog(sch, qlen, backlog);
950+
}
951+
952+
static inline void qdisc_purge_queue(struct Qdisc *sch)
953+
{
954+
__u32 qlen, backlog;
955+
956+
qdisc_qstats_qlen_backlog(sch, &qlen, &backlog);
957+
qdisc_reset(sch);
958+
qdisc_tree_reduce_backlog(sch, qlen, backlog);
959+
}
960+
944961
static inline void qdisc_skb_head_init(struct qdisc_skb_head *qh)
945962
{
946963
qh->head = NULL;
@@ -1124,13 +1141,8 @@ static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new,
11241141
sch_tree_lock(sch);
11251142
old = *pold;
11261143
*pold = new;
1127-
if (old != NULL) {
1128-
unsigned int qlen = old->q.qlen;
1129-
unsigned int backlog = old->qstats.backlog;
1130-
1131-
qdisc_reset(old);
1132-
qdisc_tree_reduce_backlog(old, qlen, backlog);
1133-
}
1144+
if (old != NULL)
1145+
qdisc_tree_flush_backlog(old);
11341146
sch_tree_unlock(sch);
11351147

11361148
return old;

net/sched/sch_cbq.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,17 +1667,13 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg)
16671667
{
16681668
struct cbq_sched_data *q = qdisc_priv(sch);
16691669
struct cbq_class *cl = (struct cbq_class *)arg;
1670-
unsigned int qlen, backlog;
16711670

16721671
if (cl->filters || cl->children || cl == &q->link)
16731672
return -EBUSY;
16741673

16751674
sch_tree_lock(sch);
16761675

1677-
qlen = cl->q->q.qlen;
1678-
backlog = cl->q->qstats.backlog;
1679-
qdisc_reset(cl->q);
1680-
qdisc_tree_reduce_backlog(cl->q, qlen, backlog);
1676+
qdisc_purge_queue(cl->q);
16811677

16821678
if (cl->next_alive)
16831679
cbq_deactivate_class(cl);

net/sched/sch_drr.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,6 @@ static struct drr_class *drr_find_class(struct Qdisc *sch, u32 classid)
5050
return container_of(clc, struct drr_class, common);
5151
}
5252

53-
static void drr_purge_queue(struct drr_class *cl)
54-
{
55-
unsigned int len = cl->qdisc->q.qlen;
56-
unsigned int backlog = cl->qdisc->qstats.backlog;
57-
58-
qdisc_reset(cl->qdisc);
59-
qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
60-
}
61-
6253
static const struct nla_policy drr_policy[TCA_DRR_MAX + 1] = {
6354
[TCA_DRR_QUANTUM] = { .type = NLA_U32 },
6455
};
@@ -167,7 +158,7 @@ static int drr_delete_class(struct Qdisc *sch, unsigned long arg)
167158

168159
sch_tree_lock(sch);
169160

170-
drr_purge_queue(cl);
161+
qdisc_purge_queue(cl->qdisc);
171162
qdisc_class_hash_remove(&q->clhash, &cl->common);
172163

173164
sch_tree_unlock(sch);

net/sched/sch_hfsc.c

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -844,16 +844,6 @@ qdisc_peek_len(struct Qdisc *sch)
844844
return len;
845845
}
846846

847-
static void
848-
hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
849-
{
850-
unsigned int len = cl->qdisc->q.qlen;
851-
unsigned int backlog = cl->qdisc->qstats.backlog;
852-
853-
qdisc_reset(cl->qdisc);
854-
qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
855-
}
856-
857847
static void
858848
hfsc_adjust_levels(struct hfsc_class *cl)
859849
{
@@ -1076,7 +1066,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
10761066
qdisc_class_hash_insert(&q->clhash, &cl->cl_common);
10771067
list_add_tail(&cl->siblings, &parent->children);
10781068
if (parent->level == 0)
1079-
hfsc_purge_queue(sch, parent);
1069+
qdisc_purge_queue(parent->qdisc);
10801070
hfsc_adjust_levels(parent);
10811071
sch_tree_unlock(sch);
10821072

@@ -1112,7 +1102,7 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg)
11121102
list_del(&cl->siblings);
11131103
hfsc_adjust_levels(cl->cl_parent);
11141104

1115-
hfsc_purge_queue(sch, cl);
1105+
qdisc_purge_queue(cl->qdisc);
11161106
qdisc_class_hash_remove(&q->clhash, &cl->cl_common);
11171107

11181108
sch_tree_unlock(sch);

net/sched/sch_htb.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,13 +1269,8 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
12691269

12701270
sch_tree_lock(sch);
12711271

1272-
if (!cl->level) {
1273-
unsigned int qlen = cl->leaf.q->q.qlen;
1274-
unsigned int backlog = cl->leaf.q->qstats.backlog;
1275-
1276-
qdisc_reset(cl->leaf.q);
1277-
qdisc_tree_reduce_backlog(cl->leaf.q, qlen, backlog);
1278-
}
1272+
if (!cl->level)
1273+
qdisc_purge_queue(cl->leaf.q);
12791274

12801275
/* delete from hash and active; remainder in destroy_class */
12811276
qdisc_class_hash_remove(&q->clhash, &cl->common);
@@ -1403,12 +1398,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
14031398
classid, NULL);
14041399
sch_tree_lock(sch);
14051400
if (parent && !parent->level) {
1406-
unsigned int qlen = parent->leaf.q->q.qlen;
1407-
unsigned int backlog = parent->leaf.q->qstats.backlog;
1408-
14091401
/* turn parent into inner node */
1410-
qdisc_reset(parent->leaf.q);
1411-
qdisc_tree_reduce_backlog(parent->leaf.q, qlen, backlog);
1402+
qdisc_purge_queue(parent->leaf.q);
14121403
qdisc_put(parent->leaf.q);
14131404
if (parent->prio_activity)
14141405
htb_deactivate(q, parent);

net/sched/sch_multiq.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,9 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt,
201201
for (i = q->bands; i < q->max_bands; i++) {
202202
if (q->queues[i] != &noop_qdisc) {
203203
struct Qdisc *child = q->queues[i];
204+
204205
q->queues[i] = &noop_qdisc;
205-
qdisc_tree_reduce_backlog(child, child->q.qlen,
206-
child->qstats.backlog);
206+
qdisc_tree_flush_backlog(child);
207207
qdisc_put(child);
208208
}
209209
}
@@ -225,9 +225,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt,
225225
qdisc_hash_add(child, true);
226226

227227
if (old != &noop_qdisc) {
228-
qdisc_tree_reduce_backlog(old,
229-
old->q.qlen,
230-
old->qstats.backlog);
228+
qdisc_tree_flush_backlog(old);
231229
qdisc_put(old);
232230
}
233231
sch_tree_unlock(sch);

net/sched/sch_prio.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,8 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
216216
q->bands = qopt->bands;
217217
memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
218218

219-
for (i = q->bands; i < oldbands; i++) {
220-
struct Qdisc *child = q->queues[i];
221-
222-
qdisc_tree_reduce_backlog(child, child->q.qlen,
223-
child->qstats.backlog);
224-
}
219+
for (i = q->bands; i < oldbands; i++)
220+
qdisc_tree_flush_backlog(q->queues[i]);
225221

226222
for (i = oldbands; i < q->bands; i++) {
227223
q->queues[i] = queues[i];

net/sched/sch_qfq.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,6 @@ static struct qfq_class *qfq_find_class(struct Qdisc *sch, u32 classid)
217217
return container_of(clc, struct qfq_class, common);
218218
}
219219

220-
static void qfq_purge_queue(struct qfq_class *cl)
221-
{
222-
unsigned int len = cl->qdisc->q.qlen;
223-
unsigned int backlog = cl->qdisc->qstats.backlog;
224-
225-
qdisc_reset(cl->qdisc);
226-
qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
227-
}
228-
229220
static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = {
230221
[TCA_QFQ_WEIGHT] = { .type = NLA_U32 },
231222
[TCA_QFQ_LMAX] = { .type = NLA_U32 },
@@ -551,7 +542,7 @@ static int qfq_delete_class(struct Qdisc *sch, unsigned long arg)
551542

552543
sch_tree_lock(sch);
553544

554-
qfq_purge_queue(cl);
545+
qdisc_purge_queue(cl->qdisc);
555546
qdisc_class_hash_remove(&q->clhash, &cl->common);
556547

557548
sch_tree_unlock(sch);

net/sched/sch_red.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,7 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt,
233233
q->flags = ctl->flags;
234234
q->limit = ctl->limit;
235235
if (child) {
236-
qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
237-
q->qdisc->qstats.backlog);
236+
qdisc_tree_flush_backlog(q->qdisc);
238237
old_child = q->qdisc;
239238
q->qdisc = child;
240239
}

net/sched/sch_sfb.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,7 @@ static int sfb_change(struct Qdisc *sch, struct nlattr *opt,
521521
qdisc_hash_add(child, true);
522522
sch_tree_lock(sch);
523523

524-
qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
525-
q->qdisc->qstats.backlog);
524+
qdisc_tree_flush_backlog(q->qdisc);
526525
qdisc_put(q->qdisc);
527526
q->qdisc = child;
528527

net/sched/sch_tbf.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
391391

392392
sch_tree_lock(sch);
393393
if (child) {
394-
qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen,
395-
q->qdisc->qstats.backlog);
394+
qdisc_tree_flush_backlog(q->qdisc);
396395
qdisc_put(q->qdisc);
397396
q->qdisc = child;
398397
}

0 commit comments

Comments
 (0)