aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-11-29 20:36:20 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:43 -0500
commit5e50da01d0ce7ef0ba3ed6cfabd62f327da0aca6 (patch)
tree6f2205ceae40a7fd5b498e94c60b65140740a027
parent43effa1e57fc4635e0301b27d78f9d83afe78974 (diff)
[NET_SCHED]: Fix endless loops (part 2): "simple" qdiscs
Convert the "simple" qdiscs to use qdisc_tree_decrease_qlen() where necessary: - all graft operations - destruction of old child qdiscs in prio, red and tbf change operation - purging of queue in sfq change operation Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sched/sch_cbq.c2
-rw-r--r--net/sched/sch_dsmark.c2
-rw-r--r--net/sched/sch_netem.c2
-rw-r--r--net/sched/sch_prio.c11
-rw-r--r--net/sched/sch_red.c6
-rw-r--r--net/sched/sch_sfq.c3
-rw-r--r--net/sched/sch_tbf.c6
7 files changed, 22 insertions, 10 deletions
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 908b10d0d61f..ba82dfab6043 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1687,7 +1687,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1687 sch_tree_lock(sch); 1687 sch_tree_lock(sch);
1688 *old = cl->q; 1688 *old = cl->q;
1689 cl->q = new; 1689 cl->q = new;
1690 sch->q.qlen -= (*old)->q.qlen; 1690 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
1691 qdisc_reset(*old); 1691 qdisc_reset(*old);
1692 sch_tree_unlock(sch); 1692 sch_tree_unlock(sch);
1693 1693
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index afedd92b7496..d5421816f007 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -96,8 +96,8 @@ static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
96 96
97 sch_tree_lock(sch); 97 sch_tree_lock(sch);
98 *old = xchg(&p->q, new); 98 *old = xchg(&p->q, new);
99 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
99 qdisc_reset(*old); 100 qdisc_reset(*old);
100 sch->q.qlen = 0;
101 sch_tree_unlock(sch); 101 sch_tree_unlock(sch);
102 102
103 return 0; 103 return 0;
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 90aeeb7b7167..672c35445793 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -662,8 +662,8 @@ static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
662 662
663 sch_tree_lock(sch); 663 sch_tree_lock(sch);
664 *old = xchg(&q->qdisc, new); 664 *old = xchg(&q->qdisc, new);
665 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
665 qdisc_reset(*old); 666 qdisc_reset(*old);
666 sch->q.qlen = 0;
667 sch_tree_unlock(sch); 667 sch_tree_unlock(sch);
668 668
669 return 0; 669 return 0;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 3fc0c0fa5bcc..2567b4c96c1e 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -222,8 +222,10 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
222 222
223 for (i=q->bands; i<TCQ_PRIO_BANDS; i++) { 223 for (i=q->bands; i<TCQ_PRIO_BANDS; i++) {
224 struct Qdisc *child = xchg(&q->queues[i], &noop_qdisc); 224 struct Qdisc *child = xchg(&q->queues[i], &noop_qdisc);
225 if (child != &noop_qdisc) 225 if (child != &noop_qdisc) {
226 qdisc_tree_decrease_qlen(child, child->q.qlen);
226 qdisc_destroy(child); 227 qdisc_destroy(child);
228 }
227 } 229 }
228 sch_tree_unlock(sch); 230 sch_tree_unlock(sch);
229 231
@@ -236,8 +238,11 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
236 sch_tree_lock(sch); 238 sch_tree_lock(sch);
237 child = xchg(&q->queues[i], child); 239 child = xchg(&q->queues[i], child);
238 240
239 if (child != &noop_qdisc) 241 if (child != &noop_qdisc) {
242 qdisc_tree_decrease_qlen(child,
243 child->q.qlen);
240 qdisc_destroy(child); 244 qdisc_destroy(child);
245 }
241 sch_tree_unlock(sch); 246 sch_tree_unlock(sch);
242 } 247 }
243 } 248 }
@@ -295,7 +300,7 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
295 sch_tree_lock(sch); 300 sch_tree_lock(sch);
296 *old = q->queues[band]; 301 *old = q->queues[band];
297 q->queues[band] = new; 302 q->queues[band] = new;
298 sch->q.qlen -= (*old)->q.qlen; 303 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
299 qdisc_reset(*old); 304 qdisc_reset(*old);
300 sch_tree_unlock(sch); 305 sch_tree_unlock(sch);
301 306
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index ee66c5ca80c6..acddad08850f 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -229,8 +229,10 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
229 sch_tree_lock(sch); 229 sch_tree_lock(sch);
230 q->flags = ctl->flags; 230 q->flags = ctl->flags;
231 q->limit = ctl->limit; 231 q->limit = ctl->limit;
232 if (child) 232 if (child) {
233 qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
233 qdisc_destroy(xchg(&q->qdisc, child)); 234 qdisc_destroy(xchg(&q->qdisc, child));
235 }
234 236
235 red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, 237 red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog,
236 ctl->Plog, ctl->Scell_log, 238 ctl->Plog, ctl->Scell_log,
@@ -308,8 +310,8 @@ static int red_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
308 310
309 sch_tree_lock(sch); 311 sch_tree_lock(sch);
310 *old = xchg(&q->qdisc, new); 312 *old = xchg(&q->qdisc, new);
313 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
311 qdisc_reset(*old); 314 qdisc_reset(*old);
312 sch->q.qlen = 0;
313 sch_tree_unlock(sch); 315 sch_tree_unlock(sch);
314 return 0; 316 return 0;
315} 317}
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index d0d6e595a78c..459cda258a5c 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -393,6 +393,7 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
393{ 393{
394 struct sfq_sched_data *q = qdisc_priv(sch); 394 struct sfq_sched_data *q = qdisc_priv(sch);
395 struct tc_sfq_qopt *ctl = RTA_DATA(opt); 395 struct tc_sfq_qopt *ctl = RTA_DATA(opt);
396 unsigned int qlen;
396 397
397 if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) 398 if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
398 return -EINVAL; 399 return -EINVAL;
@@ -403,8 +404,10 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
403 if (ctl->limit) 404 if (ctl->limit)
404 q->limit = min_t(u32, ctl->limit, SFQ_DEPTH); 405 q->limit = min_t(u32, ctl->limit, SFQ_DEPTH);
405 406
407 qlen = sch->q.qlen;
406 while (sch->q.qlen >= q->limit-1) 408 while (sch->q.qlen >= q->limit-1)
407 sfq_drop(sch); 409 sfq_drop(sch);
410 qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
408 411
409 del_timer(&q->perturb_timer); 412 del_timer(&q->perturb_timer);
410 if (q->perturb_period) { 413 if (q->perturb_period) {
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 2562a6040b76..23b7624354f5 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -348,8 +348,10 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
348 } 348 }
349 349
350 sch_tree_lock(sch); 350 sch_tree_lock(sch);
351 if (child) 351 if (child) {
352 qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
352 qdisc_destroy(xchg(&q->qdisc, child)); 353 qdisc_destroy(xchg(&q->qdisc, child));
354 }
353 q->limit = qopt->limit; 355 q->limit = qopt->limit;
354 q->mtu = qopt->mtu; 356 q->mtu = qopt->mtu;
355 q->max_size = max_size; 357 q->max_size = max_size;
@@ -451,8 +453,8 @@ static int tbf_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
451 453
452 sch_tree_lock(sch); 454 sch_tree_lock(sch);
453 *old = xchg(&q->qdisc, new); 455 *old = xchg(&q->qdisc, new);
456 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
454 qdisc_reset(*old); 457 qdisc_reset(*old);
455 sch->q.qlen = 0;
456 sch_tree_unlock(sch); 458 sch_tree_unlock(sch);
457 459
458 return 0; 460 return 0;