]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sched/sch_htb.c
net-sched: sch_htb: move hash and sibling list removal to htb_delete
[linux-2.6-omap-h63xx.git] / net / sched / sch_htb.c
index 0284791169c99163bdb39742ff8a06fbf0e69fbf..d01fe3a1a623bc2b7f7dc2baa48a8bb96fe17571 100644 (file)
@@ -1226,8 +1226,6 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
 
 static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
 {
-       struct htb_sched *q = qdisc_priv(sch);
-
        if (!cl->level) {
                BUG_TRAP(cl->un.leaf.q);
                qdisc_destroy(cl->un.leaf.q);
@@ -1237,21 +1235,6 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
        qdisc_put_rtab(cl->ceil);
 
        tcf_destroy_chain(&cl->filter_list);
-
-       while (!list_empty(&cl->children))
-               htb_destroy_class(sch, list_entry(cl->children.next,
-                                                 struct htb_class, sibling));
-
-       /* note: this delete may happen twice (see htb_delete) */
-       hlist_del_init(&cl->hlist);
-       list_del(&cl->sibling);
-
-       if (cl->prio_activity)
-               htb_deactivate(q, cl);
-
-       if (cl->cmode != HTB_CAN_SEND)
-               htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
-
        kfree(cl);
 }
 
@@ -1259,6 +1242,9 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
 static void htb_destroy(struct Qdisc *sch)
 {
        struct htb_sched *q = qdisc_priv(sch);
+       struct hlist_node *n, *next;
+       struct htb_class *cl;
+       unsigned int i;
 
        qdisc_watchdog_cancel(&q->watchdog);
        /* This line used to be after htb_destroy_class call below
@@ -1267,10 +1253,14 @@ static void htb_destroy(struct Qdisc *sch)
           unbind_filter on it (without Oops). */
        tcf_destroy_chain(&q->filter_list);
 
-       while (!list_empty(&q->root))
-               htb_destroy_class(sch, list_entry(q->root.next,
-                                                 struct htb_class, sibling));
-
+       for (i = 0; i < HTB_HSIZE; i++) {
+               hlist_for_each_entry(cl, n, q->hash + i, hlist)
+                       tcf_destroy_chain(&cl->filter_list);
+       }
+       for (i = 0; i < HTB_HSIZE; i++) {
+               hlist_for_each_entry_safe(cl, n, next, q->hash + i, hlist)
+                       htb_destroy_class(sch, cl);
+       }
        __skb_queue_purge(&q->direct_queue);
 }
 
@@ -1302,12 +1292,16 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
                qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
        }
 
-       /* delete from hash and active; remainder in destroy_class */
-       hlist_del_init(&cl->hlist);
+       /* delete from hash, sibling list and active */
+       hlist_del(&cl->hlist);
+       list_del(&cl->sibling);
 
        if (cl->prio_activity)
                htb_deactivate(q, cl);
 
+       if (cl->cmode != HTB_CAN_SEND)
+               htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
+
        if (last_child)
                htb_parent_to_leaf(q, cl, new_q);