diff options
author | Patrick McHardy <kaber@trash.net> | 2006-11-29 20:36:43 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:31:44 -0500 |
commit | f973b913e18ab5a4795738ddf8a8666ac306ee12 (patch) | |
tree | 6162ce2896e1a7139f019c09dc37f09d213a211b /net/sched | |
parent | 5e50da01d0ce7ef0ba3ed6cfabd62f327da0aca6 (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>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/sch_hfsc.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 1142d298ecf6..2d437447e085 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) | |||
957 | unsigned int len = cl->qdisc->q.qlen; | 957 | unsigned int len = cl->qdisc->q.qlen; |
958 | 958 | ||
959 | qdisc_reset(cl->qdisc); | 959 | qdisc_reset(cl->qdisc); |
960 | if (len > 0) { | 960 | qdisc_tree_decrease_qlen(cl->qdisc, len); |
961 | update_vf(cl, 0, 0); | ||
962 | set_passive(cl); | ||
963 | sch->q.qlen -= len; | ||
964 | } | ||
965 | } | 961 | } |
966 | 962 | ||
967 | static void | 963 | static void |
@@ -1295,6 +1291,17 @@ hfsc_class_leaf(struct Qdisc *sch, unsigned long arg) | |||
1295 | return NULL; | 1291 | return NULL; |
1296 | } | 1292 | } |
1297 | 1293 | ||
1294 | static void | ||
1295 | hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg) | ||
1296 | { | ||
1297 | struct hfsc_class *cl = (struct hfsc_class *)arg; | ||
1298 | |||
1299 | if (cl->qdisc->q.qlen == 0) { | ||
1300 | update_vf(cl, 0, 0); | ||
1301 | set_passive(cl); | ||
1302 | } | ||
1303 | } | ||
1304 | |||
1298 | static unsigned long | 1305 | static unsigned long |
1299 | hfsc_get_class(struct Qdisc *sch, u32 classid) | 1306 | hfsc_get_class(struct Qdisc *sch, u32 classid) |
1300 | { | 1307 | { |
@@ -1779,6 +1786,7 @@ static struct Qdisc_class_ops hfsc_class_ops = { | |||
1779 | .delete = hfsc_delete_class, | 1786 | .delete = hfsc_delete_class, |
1780 | .graft = hfsc_graft_class, | 1787 | .graft = hfsc_graft_class, |
1781 | .leaf = hfsc_class_leaf, | 1788 | .leaf = hfsc_class_leaf, |
1789 | .qlen_notify = hfsc_qlen_notify, | ||
1782 | .get = hfsc_get_class, | 1790 | .get = hfsc_get_class, |
1783 | .put = hfsc_put_class, | 1791 | .put = hfsc_put_class, |
1784 | .bind_tcf = hfsc_bind_tcf, | 1792 | .bind_tcf = hfsc_bind_tcf, |