From 066a3b5b2346febf9a655b444567b7138e3bb939 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 14 Apr 2008 15:10:42 -0700 Subject: [PATCH] [NET_SCHED] sch_api: fix qdisc_tree_decrease_qlen() loop TC_H_MAJ(parentid) for root classes is the same as for ingress, and if ingress qdisc is created qdisc_lookup() returns its pointer (without ingress NULL is returned). After this all qdisc_lookups give the same, and we get endless loop. (I don't know how this could hide for so long - it should trigger with every leaf class deleted if it's qdisc isn't empty.) After this fix qdisc_lookup() is omitted both for ingress and root parents, but looking for root is only wasting a little time here... Many thanks to Enrico Demarin for finding a test for catching this bug, which probably bothered quite a lot of admins. Reported-by: Enrico Demarin , Signed-off-by: Jarek Poplawski Acked-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/sch_api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 7e3c048ba9b1..fc8708a0a25e 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -386,6 +386,9 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) if (n == 0) return; while ((parentid = sch->parent)) { + if (TC_H_MAJ(parentid) == TC_H_MAJ(TC_H_INGRESS)) + return; + sch = qdisc_lookup(sch->dev, TC_H_MAJ(parentid)); if (sch == NULL) { WARN_ON(parentid != TC_H_ROOT);