Commit 066a3b5b authored by Jarek Poplawski's avatar Jarek Poplawski Committed by David S. Miller

[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 <enrico@superclick.com>,
Signed-off-by: default avatarJarek Poplawski <jarkao2@gmail.com>
Acked-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 159d8336
...@@ -386,6 +386,9 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) ...@@ -386,6 +386,9 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
if (n == 0) if (n == 0)
return; return;
while ((parentid = sch->parent)) { 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)); sch = qdisc_lookup(sch->dev, TC_H_MAJ(parentid));
if (sch == NULL) { if (sch == NULL) {
WARN_ON(parentid != TC_H_ROOT); WARN_ON(parentid != TC_H_ROOT);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment