diff options
author | Paolo Abeni <pabeni@redhat.com> | 2019-03-28 11:53:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-04-01 17:50:13 -0400 |
commit | e5f0e8f8e456589d56e4955154ed5d468cd6d286 (patch) | |
tree | 394e064316a0965588c3784a36a24fca3a7b352d /net | |
parent | 5dd431b6b92c0db324d134d2a4006dd4f87f2261 (diff) |
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: c5ad119fb6c0 ("net: sched: pfifo_fast use skb_array")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/sched/sch_cbq.c | 6 | ||||
-rw-r--r-- | net/sched/sch_drr.c | 11 | ||||
-rw-r--r-- | net/sched/sch_hfsc.c | 14 | ||||
-rw-r--r-- | net/sched/sch_htb.c | 15 | ||||
-rw-r--r-- | net/sched/sch_multiq.c | 8 | ||||
-rw-r--r-- | net/sched/sch_prio.c | 8 | ||||
-rw-r--r-- | net/sched/sch_qfq.c | 11 | ||||
-rw-r--r-- | net/sched/sch_red.c | 3 | ||||
-rw-r--r-- | net/sched/sch_sfb.c | 3 | ||||
-rw-r--r-- | net/sched/sch_tbf.c | 3 |
10 files changed, 16 insertions, 66 deletions
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 651879c1b655..114b9048ea7e 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -1667,17 +1667,13 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg) | |||
1667 | { | 1667 | { |
1668 | struct cbq_sched_data *q = qdisc_priv(sch); | 1668 | struct cbq_sched_data *q = qdisc_priv(sch); |
1669 | struct cbq_class *cl = (struct cbq_class *)arg; | 1669 | struct cbq_class *cl = (struct cbq_class *)arg; |
1670 | unsigned int qlen, backlog; | ||
1671 | 1670 | ||
1672 | if (cl->filters || cl->children || cl == &q->link) | 1671 | if (cl->filters || cl->children || cl == &q->link) |
1673 | return -EBUSY; | 1672 | return -EBUSY; |
1674 | 1673 | ||
1675 | sch_tree_lock(sch); | 1674 | sch_tree_lock(sch); |
1676 | 1675 | ||
1677 | qlen = cl->q->q.qlen; | 1676 | qdisc_purge_queue(cl->q); |
1678 | backlog = cl->q->qstats.backlog; | ||
1679 | qdisc_reset(cl->q); | ||
1680 | qdisc_tree_reduce_backlog(cl->q, qlen, backlog); | ||
1681 | 1677 | ||
1682 | if (cl->next_alive) | 1678 | if (cl->next_alive) |
1683 | cbq_deactivate_class(cl); | 1679 | cbq_deactivate_class(cl); |
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 8a181591b0ea..430df9a55ec4 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c | |||
@@ -50,15 +50,6 @@ static struct drr_class *drr_find_class(struct Qdisc *sch, u32 classid) | |||
50 | return container_of(clc, struct drr_class, common); | 50 | return container_of(clc, struct drr_class, common); |
51 | } | 51 | } |
52 | 52 | ||
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 | |||
62 | static const struct nla_policy drr_policy[TCA_DRR_MAX + 1] = { | 53 | static const struct nla_policy drr_policy[TCA_DRR_MAX + 1] = { |
63 | [TCA_DRR_QUANTUM] = { .type = NLA_U32 }, | 54 | [TCA_DRR_QUANTUM] = { .type = NLA_U32 }, |
64 | }; | 55 | }; |
@@ -167,7 +158,7 @@ static int drr_delete_class(struct Qdisc *sch, unsigned long arg) | |||
167 | 158 | ||
168 | sch_tree_lock(sch); | 159 | sch_tree_lock(sch); |
169 | 160 | ||
170 | drr_purge_queue(cl); | 161 | qdisc_purge_queue(cl->qdisc); |
171 | qdisc_class_hash_remove(&q->clhash, &cl->common); | 162 | qdisc_class_hash_remove(&q->clhash, &cl->common); |
172 | 163 | ||
173 | sch_tree_unlock(sch); | 164 | sch_tree_unlock(sch); |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index a946a419d717..d2ab463f22ae 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -845,16 +845,6 @@ qdisc_peek_len(struct Qdisc *sch) | |||
845 | } | 845 | } |
846 | 846 | ||
847 | static void | 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 | |||
857 | static void | ||
858 | hfsc_adjust_levels(struct hfsc_class *cl) | 848 | hfsc_adjust_levels(struct hfsc_class *cl) |
859 | { | 849 | { |
860 | struct hfsc_class *p; | 850 | struct hfsc_class *p; |
@@ -1076,7 +1066,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1076 | qdisc_class_hash_insert(&q->clhash, &cl->cl_common); | 1066 | qdisc_class_hash_insert(&q->clhash, &cl->cl_common); |
1077 | list_add_tail(&cl->siblings, &parent->children); | 1067 | list_add_tail(&cl->siblings, &parent->children); |
1078 | if (parent->level == 0) | 1068 | if (parent->level == 0) |
1079 | hfsc_purge_queue(sch, parent); | 1069 | qdisc_purge_queue(parent->qdisc); |
1080 | hfsc_adjust_levels(parent); | 1070 | hfsc_adjust_levels(parent); |
1081 | sch_tree_unlock(sch); | 1071 | sch_tree_unlock(sch); |
1082 | 1072 | ||
@@ -1112,7 +1102,7 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg) | |||
1112 | list_del(&cl->siblings); | 1102 | list_del(&cl->siblings); |
1113 | hfsc_adjust_levels(cl->cl_parent); | 1103 | hfsc_adjust_levels(cl->cl_parent); |
1114 | 1104 | ||
1115 | hfsc_purge_queue(sch, cl); | 1105 | qdisc_purge_queue(cl->qdisc); |
1116 | qdisc_class_hash_remove(&q->clhash, &cl->cl_common); | 1106 | qdisc_class_hash_remove(&q->clhash, &cl->cl_common); |
1117 | 1107 | ||
1118 | sch_tree_unlock(sch); | 1108 | sch_tree_unlock(sch); |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index ed92836f528a..2f9883b196e8 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -1269,13 +1269,8 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) | |||
1269 | 1269 | ||
1270 | sch_tree_lock(sch); | 1270 | sch_tree_lock(sch); |
1271 | 1271 | ||
1272 | if (!cl->level) { | 1272 | if (!cl->level) |
1273 | unsigned int qlen = cl->leaf.q->q.qlen; | 1273 | qdisc_purge_queue(cl->leaf.q); |
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 | } | ||
1279 | 1274 | ||
1280 | /* delete from hash and active; remainder in destroy_class */ | 1275 | /* delete from hash and active; remainder in destroy_class */ |
1281 | qdisc_class_hash_remove(&q->clhash, &cl->common); | 1276 | qdisc_class_hash_remove(&q->clhash, &cl->common); |
@@ -1403,12 +1398,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1403 | classid, NULL); | 1398 | classid, NULL); |
1404 | sch_tree_lock(sch); | 1399 | sch_tree_lock(sch); |
1405 | if (parent && !parent->level) { | 1400 | if (parent && !parent->level) { |
1406 | unsigned int qlen = parent->leaf.q->q.qlen; | ||
1407 | unsigned int backlog = parent->leaf.q->qstats.backlog; | ||
1408 | |||
1409 | /* turn parent into inner node */ | 1401 | /* turn parent into inner node */ |
1410 | qdisc_reset(parent->leaf.q); | 1402 | qdisc_purge_queue(parent->leaf.q); |
1411 | qdisc_tree_reduce_backlog(parent->leaf.q, qlen, backlog); | ||
1412 | qdisc_put(parent->leaf.q); | 1403 | qdisc_put(parent->leaf.q); |
1413 | if (parent->prio_activity) | 1404 | if (parent->prio_activity) |
1414 | htb_deactivate(q, parent); | 1405 | htb_deactivate(q, parent); |
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c index 53c918a11378..35b03ae08e0f 100644 --- a/net/sched/sch_multiq.c +++ b/net/sched/sch_multiq.c | |||
@@ -201,9 +201,9 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt, | |||
201 | for (i = q->bands; i < q->max_bands; i++) { | 201 | for (i = q->bands; i < q->max_bands; i++) { |
202 | if (q->queues[i] != &noop_qdisc) { | 202 | if (q->queues[i] != &noop_qdisc) { |
203 | struct Qdisc *child = q->queues[i]; | 203 | struct Qdisc *child = q->queues[i]; |
204 | |||
204 | q->queues[i] = &noop_qdisc; | 205 | q->queues[i] = &noop_qdisc; |
205 | qdisc_tree_reduce_backlog(child, child->q.qlen, | 206 | qdisc_tree_flush_backlog(child); |
206 | child->qstats.backlog); | ||
207 | qdisc_put(child); | 207 | qdisc_put(child); |
208 | } | 208 | } |
209 | } | 209 | } |
@@ -225,9 +225,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt, | |||
225 | qdisc_hash_add(child, true); | 225 | qdisc_hash_add(child, true); |
226 | 226 | ||
227 | if (old != &noop_qdisc) { | 227 | if (old != &noop_qdisc) { |
228 | qdisc_tree_reduce_backlog(old, | 228 | qdisc_tree_flush_backlog(old); |
229 | old->q.qlen, | ||
230 | old->qstats.backlog); | ||
231 | qdisc_put(old); | 229 | qdisc_put(old); |
232 | } | 230 | } |
233 | sch_tree_unlock(sch); | 231 | sch_tree_unlock(sch); |
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index dfb06d5bfacc..d519b21535b3 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c | |||
@@ -216,12 +216,8 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt, | |||
216 | q->bands = qopt->bands; | 216 | q->bands = qopt->bands; |
217 | memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); | 217 | memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); |
218 | 218 | ||
219 | for (i = q->bands; i < oldbands; i++) { | 219 | for (i = q->bands; i < oldbands; i++) |
220 | struct Qdisc *child = q->queues[i]; | 220 | qdisc_tree_flush_backlog(q->queues[i]); |
221 | |||
222 | qdisc_tree_reduce_backlog(child, child->q.qlen, | ||
223 | child->qstats.backlog); | ||
224 | } | ||
225 | 221 | ||
226 | for (i = oldbands; i < q->bands; i++) { | 222 | for (i = oldbands; i < q->bands; i++) { |
227 | q->queues[i] = queues[i]; | 223 | q->queues[i] = queues[i]; |
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index 9fbda3ec5861..1589364b54da 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c | |||
@@ -217,15 +217,6 @@ static struct qfq_class *qfq_find_class(struct Qdisc *sch, u32 classid) | |||
217 | return container_of(clc, struct qfq_class, common); | 217 | return container_of(clc, struct qfq_class, common); |
218 | } | 218 | } |
219 | 219 | ||
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 | |||
229 | static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = { | 220 | static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = { |
230 | [TCA_QFQ_WEIGHT] = { .type = NLA_U32 }, | 221 | [TCA_QFQ_WEIGHT] = { .type = NLA_U32 }, |
231 | [TCA_QFQ_LMAX] = { .type = NLA_U32 }, | 222 | [TCA_QFQ_LMAX] = { .type = NLA_U32 }, |
@@ -551,7 +542,7 @@ static int qfq_delete_class(struct Qdisc *sch, unsigned long arg) | |||
551 | 542 | ||
552 | sch_tree_lock(sch); | 543 | sch_tree_lock(sch); |
553 | 544 | ||
554 | qfq_purge_queue(cl); | 545 | qdisc_purge_queue(cl->qdisc); |
555 | qdisc_class_hash_remove(&q->clhash, &cl->common); | 546 | qdisc_class_hash_remove(&q->clhash, &cl->common); |
556 | 547 | ||
557 | sch_tree_unlock(sch); | 548 | sch_tree_unlock(sch); |
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 9df9942340ea..4e8c0abf6194 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c | |||
@@ -233,8 +233,7 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt, | |||
233 | q->flags = ctl->flags; | 233 | q->flags = ctl->flags; |
234 | q->limit = ctl->limit; | 234 | q->limit = ctl->limit; |
235 | if (child) { | 235 | if (child) { |
236 | qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen, | 236 | qdisc_tree_flush_backlog(q->qdisc); |
237 | q->qdisc->qstats.backlog); | ||
238 | old_child = q->qdisc; | 237 | old_child = q->qdisc; |
239 | q->qdisc = child; | 238 | q->qdisc = child; |
240 | } | 239 | } |
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index bab506b01a32..2419fdb75966 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c | |||
@@ -521,8 +521,7 @@ static int sfb_change(struct Qdisc *sch, struct nlattr *opt, | |||
521 | qdisc_hash_add(child, true); | 521 | qdisc_hash_add(child, true); |
522 | sch_tree_lock(sch); | 522 | sch_tree_lock(sch); |
523 | 523 | ||
524 | qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen, | 524 | qdisc_tree_flush_backlog(q->qdisc); |
525 | q->qdisc->qstats.backlog); | ||
526 | qdisc_put(q->qdisc); | 525 | qdisc_put(q->qdisc); |
527 | q->qdisc = child; | 526 | q->qdisc = child; |
528 | 527 | ||
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 7f272a9070c5..f71578dbb9e3 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -391,8 +391,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt, | |||
391 | 391 | ||
392 | sch_tree_lock(sch); | 392 | sch_tree_lock(sch); |
393 | if (child) { | 393 | if (child) { |
394 | qdisc_tree_reduce_backlog(q->qdisc, q->qdisc->q.qlen, | 394 | qdisc_tree_flush_backlog(q->qdisc); |
395 | q->qdisc->qstats.backlog); | ||
396 | qdisc_put(q->qdisc); | 395 | qdisc_put(q->qdisc); |
397 | q->qdisc = child; | 396 | q->qdisc = child; |
398 | } | 397 | } |