|
@@ -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);
|
|
|
|