summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-11-29 17:36:43 -0800
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-02 21:31:44 -0800
commitf973b913e18ab5a4795738ddf8a8666ac306ee12 (patch)
tree6162ce2896e1a7139f019c09dc37f09d213a211b
parent5e50da01d0ce7ef0ba3ed6cfabd62f327da0aca6 (diff)
[NET_SCHED]: Fix endless loops (part 3): HFSC
Convert HFSC to use qdisc_tree_decrease_len() and add a callback for deactivating a class when its child queue becomes empty. All queue purging goes through hfsc_purge_queue(), which is used in three cases: grafting, class creation (when a leaf class is turned into an intermediate class by attaching a new class) and class deletion. In all cases qdisc_tree_decrease_len() is needed. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sched/sch_hfsc.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 1142d298ecf..2d437447e08 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -957,11 +957,7 @@ hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
unsigned int len = cl->qdisc->q.qlen;
qdisc_reset(cl->qdisc);
- if (len > 0) {
- update_vf(cl, 0, 0);
- set_passive(cl);
- sch->q.qlen -= len;
- }
+ qdisc_tree_decrease_qlen(cl->qdisc, len);
}
static void
@@ -1295,6 +1291,17 @@ hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
return NULL;
}
+static void
+hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg)
+{
+ struct hfsc_class *cl = (struct hfsc_class *)arg;
+
+ if (cl->qdisc->q.qlen == 0) {
+ update_vf(cl, 0, 0);
+ set_passive(cl);
+ }
+}
+
static unsigned long
hfsc_get_class(struct Qdisc *sch, u32 classid)
{
@@ -1779,6 +1786,7 @@ static struct Qdisc_class_ops hfsc_class_ops = {
.delete = hfsc_delete_class,
.graft = hfsc_graft_class,
.leaf = hfsc_class_leaf,
+ .qlen_notify = hfsc_qlen_notify,
.get = hfsc_get_class,
.put = hfsc_put_class,
.bind_tcf = hfsc_bind_tcf,