Skip to content

Commit

Permalink
net-sched: sch_htb: move hash and sibling list removal to htb_delete
Browse files Browse the repository at this point in the history
Hash list removal currently happens twice (once in htb_delete, once
in htb_destroy_class), which makes it harder to use the dynamically
sized class hash without adding special cases for HTB. The reason is
that qdisc destruction destroys classes in hierarchical order, which
is not necessary if filters are destroyed in a separate iteration
during qdisc destruction.

Adjust qdisc destruction to follow the same scheme as other hierarchical
qdiscs by first performing a filter destruction pass, then destroying
all classes in hash order.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Jul 6, 2008
1 parent d77fea2 commit fbd8f13
Showing 1 changed file with 17 additions and 23 deletions.
40 changes: 17 additions & 23 deletions net/sched/sch_htb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -1237,28 +1235,16 @@ 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);
}

/* always caled under BH & queue lock */
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
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit fbd8f13

Please sign in to comment.