aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sched/sch_htb.c40
1 files changed, 17 insertions, 23 deletions
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 0284791169c9..d01fe3a1a623 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1226,8 +1226,6 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
1226 1226
1227static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) 1227static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
1228{ 1228{
1229 struct htb_sched *q = qdisc_priv(sch);
1230
1231 if (!cl->level) { 1229 if (!cl->level) {
1232 BUG_TRAP(cl->un.leaf.q); 1230 BUG_TRAP(cl->un.leaf.q);
1233 qdisc_destroy(cl->un.leaf.q); 1231 qdisc_destroy(cl->un.leaf.q);
@@ -1237,21 +1235,6 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
1237 qdisc_put_rtab(cl->ceil); 1235 qdisc_put_rtab(cl->ceil);
1238 1236
1239 tcf_destroy_chain(&cl->filter_list); 1237 tcf_destroy_chain(&cl->filter_list);
1240
1241 while (!list_empty(&cl->children))
1242 htb_destroy_class(sch, list_entry(cl->children.next,
1243 struct htb_class, sibling));
1244
1245 /* note: this delete may happen twice (see htb_delete) */
1246 hlist_del_init(&cl->hlist);
1247 list_del(&cl->sibling);
1248
1249 if (cl->prio_activity)
1250 htb_deactivate(q, cl);
1251
1252 if (cl->cmode != HTB_CAN_SEND)
1253 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
1254
1255 kfree(cl); 1238 kfree(cl);
1256} 1239}
1257 1240
@@ -1259,6 +1242,9 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
1259static void htb_destroy(struct Qdisc *sch) 1242static void htb_destroy(struct Qdisc *sch)
1260{ 1243{
1261 struct htb_sched *q = qdisc_priv(sch); 1244 struct htb_sched *q = qdisc_priv(sch);
1245 struct hlist_node *n, *next;
1246 struct htb_class *cl;
1247 unsigned int i;
1262 1248
1263 qdisc_watchdog_cancel(&q->watchdog); 1249 qdisc_watchdog_cancel(&q->watchdog);
1264 /* This line used to be after htb_destroy_class call below 1250 /* This line used to be after htb_destroy_class call below
@@ -1267,10 +1253,14 @@ static void htb_destroy(struct Qdisc *sch)
1267 unbind_filter on it (without Oops). */ 1253 unbind_filter on it (without Oops). */
1268 tcf_destroy_chain(&q->filter_list); 1254 tcf_destroy_chain(&q->filter_list);
1269 1255
1270 while (!list_empty(&q->root)) 1256 for (i = 0; i < HTB_HSIZE; i++) {
1271 htb_destroy_class(sch, list_entry(q->root.next, 1257 hlist_for_each_entry(cl, n, q->hash + i, hlist)
1272 struct htb_class, sibling)); 1258 tcf_destroy_chain(&cl->filter_list);
1273 1259 }
1260 for (i = 0; i < HTB_HSIZE; i++) {
1261 hlist_for_each_entry_safe(cl, n, next, q->hash + i, hlist)
1262 htb_destroy_class(sch, cl);
1263 }
1274 __skb_queue_purge(&q->direct_queue); 1264 __skb_queue_purge(&q->direct_queue);
1275} 1265}
1276 1266
@@ -1302,12 +1292,16 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
1302 qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen); 1292 qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
1303 } 1293 }
1304 1294
1305 /* delete from hash and active; remainder in destroy_class */ 1295 /* delete from hash, sibling list and active */
1306 hlist_del_init(&cl->hlist); 1296 hlist_del(&cl->hlist);
1297 list_del(&cl->sibling);
1307 1298
1308 if (cl->prio_activity) 1299 if (cl->prio_activity)
1309 htb_deactivate(q, cl); 1300 htb_deactivate(q, cl);
1310 1301
1302 if (cl->cmode != HTB_CAN_SEND)
1303 htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level);
1304
1311 if (last_child) 1305 if (last_child)
1312 htb_parent_to_leaf(q, cl, new_q); 1306 htb_parent_to_leaf(q, cl, new_q);
1313 1307