diff options
Diffstat (limited to 'net/sched/sch_htb.c')
-rw-r--r-- | net/sched/sch_htb.c | 195 |
1 files changed, 81 insertions, 114 deletions
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 3fb58f428f72..30c999c61b01 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -24,8 +24,6 @@ | |||
24 | * Jiri Fojtasek | 24 | * Jiri Fojtasek |
25 | * fixed requeue routine | 25 | * fixed requeue routine |
26 | * and many others. thanks. | 26 | * and many others. thanks. |
27 | * | ||
28 | * $Id: sch_htb.c,v 1.25 2003/12/07 11:08:25 devik Exp devik $ | ||
29 | */ | 27 | */ |
30 | #include <linux/module.h> | 28 | #include <linux/module.h> |
31 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
@@ -53,7 +51,6 @@ | |||
53 | one less than their parent. | 51 | one less than their parent. |
54 | */ | 52 | */ |
55 | 53 | ||
56 | #define HTB_HSIZE 16 /* classid hash size */ | ||
57 | static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis for speedup */ | 54 | static int htb_hysteresis __read_mostly = 0; /* whether to use mode hysteresis for speedup */ |
58 | #define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */ | 55 | #define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */ |
59 | 56 | ||
@@ -74,8 +71,8 @@ enum htb_cmode { | |||
74 | 71 | ||
75 | /* interior & leaf nodes; props specific to leaves are marked L: */ | 72 | /* interior & leaf nodes; props specific to leaves are marked L: */ |
76 | struct htb_class { | 73 | struct htb_class { |
74 | struct Qdisc_class_common common; | ||
77 | /* general class parameters */ | 75 | /* general class parameters */ |
78 | u32 classid; | ||
79 | struct gnet_stats_basic bstats; | 76 | struct gnet_stats_basic bstats; |
80 | struct gnet_stats_queue qstats; | 77 | struct gnet_stats_queue qstats; |
81 | struct gnet_stats_rate_est rate_est; | 78 | struct gnet_stats_rate_est rate_est; |
@@ -84,10 +81,8 @@ struct htb_class { | |||
84 | 81 | ||
85 | /* topology */ | 82 | /* topology */ |
86 | int level; /* our level (see above) */ | 83 | int level; /* our level (see above) */ |
84 | unsigned int children; | ||
87 | struct htb_class *parent; /* parent class */ | 85 | struct htb_class *parent; /* parent class */ |
88 | struct hlist_node hlist; /* classid hash list item */ | ||
89 | struct list_head sibling; /* sibling list item */ | ||
90 | struct list_head children; /* children list */ | ||
91 | 86 | ||
92 | union { | 87 | union { |
93 | struct htb_class_leaf { | 88 | struct htb_class_leaf { |
@@ -142,8 +137,7 @@ static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate, | |||
142 | } | 137 | } |
143 | 138 | ||
144 | struct htb_sched { | 139 | struct htb_sched { |
145 | struct list_head root; /* root classes list */ | 140 | struct Qdisc_class_hash clhash; |
146 | struct hlist_head hash[HTB_HSIZE]; /* hashed by classid */ | ||
147 | struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */ | 141 | struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */ |
148 | 142 | ||
149 | /* self list - roots of self generating tree */ | 143 | /* self list - roots of self generating tree */ |
@@ -165,7 +159,6 @@ struct htb_sched { | |||
165 | 159 | ||
166 | /* filters for qdisc itself */ | 160 | /* filters for qdisc itself */ |
167 | struct tcf_proto *filter_list; | 161 | struct tcf_proto *filter_list; |
168 | int filter_cnt; | ||
169 | 162 | ||
170 | int rate2quantum; /* quant = rate / rate2quantum */ | 163 | int rate2quantum; /* quant = rate / rate2quantum */ |
171 | psched_time_t now; /* cached dequeue time */ | 164 | psched_time_t now; /* cached dequeue time */ |
@@ -178,32 +171,16 @@ struct htb_sched { | |||
178 | long direct_pkts; | 171 | long direct_pkts; |
179 | }; | 172 | }; |
180 | 173 | ||
181 | /* compute hash of size HTB_HSIZE for given handle */ | ||
182 | static inline int htb_hash(u32 h) | ||
183 | { | ||
184 | #if HTB_HSIZE != 16 | ||
185 | #error "Declare new hash for your HTB_HSIZE" | ||
186 | #endif | ||
187 | h ^= h >> 8; /* stolen from cbq_hash */ | ||
188 | h ^= h >> 4; | ||
189 | return h & 0xf; | ||
190 | } | ||
191 | |||
192 | /* find class in global hash table using given handle */ | 174 | /* find class in global hash table using given handle */ |
193 | static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch) | 175 | static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch) |
194 | { | 176 | { |
195 | struct htb_sched *q = qdisc_priv(sch); | 177 | struct htb_sched *q = qdisc_priv(sch); |
196 | struct hlist_node *p; | 178 | struct Qdisc_class_common *clc; |
197 | struct htb_class *cl; | ||
198 | 179 | ||
199 | if (TC_H_MAJ(handle) != sch->handle) | 180 | clc = qdisc_class_find(&q->clhash, handle); |
181 | if (clc == NULL) | ||
200 | return NULL; | 182 | return NULL; |
201 | 183 | return container_of(clc, struct htb_class, common); | |
202 | hlist_for_each_entry(cl, p, q->hash + htb_hash(handle), hlist) { | ||
203 | if (cl->classid == handle) | ||
204 | return cl; | ||
205 | } | ||
206 | return NULL; | ||
207 | } | 184 | } |
208 | 185 | ||
209 | /** | 186 | /** |
@@ -284,7 +261,7 @@ static void htb_add_to_id_tree(struct rb_root *root, | |||
284 | parent = *p; | 261 | parent = *p; |
285 | c = rb_entry(parent, struct htb_class, node[prio]); | 262 | c = rb_entry(parent, struct htb_class, node[prio]); |
286 | 263 | ||
287 | if (cl->classid > c->classid) | 264 | if (cl->common.classid > c->common.classid) |
288 | p = &parent->rb_right; | 265 | p = &parent->rb_right; |
289 | else | 266 | else |
290 | p = &parent->rb_left; | 267 | p = &parent->rb_left; |
@@ -448,7 +425,7 @@ static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl) | |||
448 | /* we are removing child which is pointed to from | 425 | /* we are removing child which is pointed to from |
449 | parent feed - forget the pointer but remember | 426 | parent feed - forget the pointer but remember |
450 | classid */ | 427 | classid */ |
451 | p->un.inner.last_ptr_id[prio] = cl->classid; | 428 | p->un.inner.last_ptr_id[prio] = cl->common.classid; |
452 | p->un.inner.ptr[prio] = NULL; | 429 | p->un.inner.ptr[prio] = NULL; |
453 | } | 430 | } |
454 | 431 | ||
@@ -595,21 +572,20 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
595 | kfree_skb(skb); | 572 | kfree_skb(skb); |
596 | return ret; | 573 | return ret; |
597 | #endif | 574 | #endif |
598 | } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != | 575 | } else if (qdisc_enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) { |
599 | NET_XMIT_SUCCESS) { | ||
600 | sch->qstats.drops++; | 576 | sch->qstats.drops++; |
601 | cl->qstats.drops++; | 577 | cl->qstats.drops++; |
602 | return NET_XMIT_DROP; | 578 | return NET_XMIT_DROP; |
603 | } else { | 579 | } else { |
604 | cl->bstats.packets += | 580 | cl->bstats.packets += |
605 | skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1; | 581 | skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1; |
606 | cl->bstats.bytes += skb->len; | 582 | cl->bstats.bytes += qdisc_pkt_len(skb); |
607 | htb_activate(q, cl); | 583 | htb_activate(q, cl); |
608 | } | 584 | } |
609 | 585 | ||
610 | sch->q.qlen++; | 586 | sch->q.qlen++; |
611 | sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1; | 587 | sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1; |
612 | sch->bstats.bytes += skb->len; | 588 | sch->bstats.bytes += qdisc_pkt_len(skb); |
613 | return NET_XMIT_SUCCESS; | 589 | return NET_XMIT_SUCCESS; |
614 | } | 590 | } |
615 | 591 | ||
@@ -666,7 +642,7 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) | |||
666 | static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, | 642 | static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, |
667 | int level, struct sk_buff *skb) | 643 | int level, struct sk_buff *skb) |
668 | { | 644 | { |
669 | int bytes = skb->len; | 645 | int bytes = qdisc_pkt_len(skb); |
670 | long toks, diff; | 646 | long toks, diff; |
671 | enum htb_cmode old_mode; | 647 | enum htb_cmode old_mode; |
672 | 648 | ||
@@ -753,10 +729,10 @@ static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n, | |||
753 | while (n) { | 729 | while (n) { |
754 | struct htb_class *cl = | 730 | struct htb_class *cl = |
755 | rb_entry(n, struct htb_class, node[prio]); | 731 | rb_entry(n, struct htb_class, node[prio]); |
756 | if (id == cl->classid) | 732 | if (id == cl->common.classid) |
757 | return n; | 733 | return n; |
758 | 734 | ||
759 | if (id > cl->classid) { | 735 | if (id > cl->common.classid) { |
760 | n = n->rb_right; | 736 | n = n->rb_right; |
761 | } else { | 737 | } else { |
762 | r = n; | 738 | r = n; |
@@ -866,7 +842,7 @@ next: | |||
866 | if (!cl->warned) { | 842 | if (!cl->warned) { |
867 | printk(KERN_WARNING | 843 | printk(KERN_WARNING |
868 | "htb: class %X isn't work conserving ?!\n", | 844 | "htb: class %X isn't work conserving ?!\n", |
869 | cl->classid); | 845 | cl->common.classid); |
870 | cl->warned = 1; | 846 | cl->warned = 1; |
871 | } | 847 | } |
872 | q->nwc_hit++; | 848 | q->nwc_hit++; |
@@ -879,7 +855,8 @@ next: | |||
879 | } while (cl != start); | 855 | } while (cl != start); |
880 | 856 | ||
881 | if (likely(skb != NULL)) { | 857 | if (likely(skb != NULL)) { |
882 | if ((cl->un.leaf.deficit[level] -= skb->len) < 0) { | 858 | cl->un.leaf.deficit[level] -= qdisc_pkt_len(skb); |
859 | if (cl->un.leaf.deficit[level] < 0) { | ||
883 | cl->un.leaf.deficit[level] += cl->un.leaf.quantum; | 860 | cl->un.leaf.deficit[level] += cl->un.leaf.quantum; |
884 | htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> | 861 | htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> |
885 | ptr[0]) + prio); | 862 | ptr[0]) + prio); |
@@ -977,13 +954,12 @@ static unsigned int htb_drop(struct Qdisc *sch) | |||
977 | static void htb_reset(struct Qdisc *sch) | 954 | static void htb_reset(struct Qdisc *sch) |
978 | { | 955 | { |
979 | struct htb_sched *q = qdisc_priv(sch); | 956 | struct htb_sched *q = qdisc_priv(sch); |
980 | int i; | 957 | struct htb_class *cl; |
981 | 958 | struct hlist_node *n; | |
982 | for (i = 0; i < HTB_HSIZE; i++) { | 959 | unsigned int i; |
983 | struct hlist_node *p; | ||
984 | struct htb_class *cl; | ||
985 | 960 | ||
986 | hlist_for_each_entry(cl, p, q->hash + i, hlist) { | 961 | for (i = 0; i < q->clhash.hashsize; i++) { |
962 | hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) { | ||
987 | if (cl->level) | 963 | if (cl->level) |
988 | memset(&cl->un.inner, 0, sizeof(cl->un.inner)); | 964 | memset(&cl->un.inner, 0, sizeof(cl->un.inner)); |
989 | else { | 965 | else { |
@@ -1041,16 +1017,16 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt) | |||
1041 | return -EINVAL; | 1017 | return -EINVAL; |
1042 | } | 1018 | } |
1043 | 1019 | ||
1044 | INIT_LIST_HEAD(&q->root); | 1020 | err = qdisc_class_hash_init(&q->clhash); |
1045 | for (i = 0; i < HTB_HSIZE; i++) | 1021 | if (err < 0) |
1046 | INIT_HLIST_HEAD(q->hash + i); | 1022 | return err; |
1047 | for (i = 0; i < TC_HTB_NUMPRIO; i++) | 1023 | for (i = 0; i < TC_HTB_NUMPRIO; i++) |
1048 | INIT_LIST_HEAD(q->drops + i); | 1024 | INIT_LIST_HEAD(q->drops + i); |
1049 | 1025 | ||
1050 | qdisc_watchdog_init(&q->watchdog, sch); | 1026 | qdisc_watchdog_init(&q->watchdog, sch); |
1051 | skb_queue_head_init(&q->direct_queue); | 1027 | skb_queue_head_init(&q->direct_queue); |
1052 | 1028 | ||
1053 | q->direct_qlen = sch->dev->tx_queue_len; | 1029 | q->direct_qlen = qdisc_dev(sch)->tx_queue_len; |
1054 | if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */ | 1030 | if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */ |
1055 | q->direct_qlen = 2; | 1031 | q->direct_qlen = 2; |
1056 | 1032 | ||
@@ -1063,11 +1039,12 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt) | |||
1063 | 1039 | ||
1064 | static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) | 1040 | static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) |
1065 | { | 1041 | { |
1042 | spinlock_t *root_lock = qdisc_root_lock(sch); | ||
1066 | struct htb_sched *q = qdisc_priv(sch); | 1043 | struct htb_sched *q = qdisc_priv(sch); |
1067 | struct nlattr *nest; | 1044 | struct nlattr *nest; |
1068 | struct tc_htb_glob gopt; | 1045 | struct tc_htb_glob gopt; |
1069 | 1046 | ||
1070 | spin_lock_bh(&sch->dev->queue_lock); | 1047 | spin_lock_bh(root_lock); |
1071 | 1048 | ||
1072 | gopt.direct_pkts = q->direct_pkts; | 1049 | gopt.direct_pkts = q->direct_pkts; |
1073 | gopt.version = HTB_VER; | 1050 | gopt.version = HTB_VER; |
@@ -1081,11 +1058,11 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
1081 | NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt); | 1058 | NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt); |
1082 | nla_nest_end(skb, nest); | 1059 | nla_nest_end(skb, nest); |
1083 | 1060 | ||
1084 | spin_unlock_bh(&sch->dev->queue_lock); | 1061 | spin_unlock_bh(root_lock); |
1085 | return skb->len; | 1062 | return skb->len; |
1086 | 1063 | ||
1087 | nla_put_failure: | 1064 | nla_put_failure: |
1088 | spin_unlock_bh(&sch->dev->queue_lock); | 1065 | spin_unlock_bh(root_lock); |
1089 | nla_nest_cancel(skb, nest); | 1066 | nla_nest_cancel(skb, nest); |
1090 | return -1; | 1067 | return -1; |
1091 | } | 1068 | } |
@@ -1094,12 +1071,13 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, | |||
1094 | struct sk_buff *skb, struct tcmsg *tcm) | 1071 | struct sk_buff *skb, struct tcmsg *tcm) |
1095 | { | 1072 | { |
1096 | struct htb_class *cl = (struct htb_class *)arg; | 1073 | struct htb_class *cl = (struct htb_class *)arg; |
1074 | spinlock_t *root_lock = qdisc_root_lock(sch); | ||
1097 | struct nlattr *nest; | 1075 | struct nlattr *nest; |
1098 | struct tc_htb_opt opt; | 1076 | struct tc_htb_opt opt; |
1099 | 1077 | ||
1100 | spin_lock_bh(&sch->dev->queue_lock); | 1078 | spin_lock_bh(root_lock); |
1101 | tcm->tcm_parent = cl->parent ? cl->parent->classid : TC_H_ROOT; | 1079 | tcm->tcm_parent = cl->parent ? cl->parent->common.classid : TC_H_ROOT; |
1102 | tcm->tcm_handle = cl->classid; | 1080 | tcm->tcm_handle = cl->common.classid; |
1103 | if (!cl->level && cl->un.leaf.q) | 1081 | if (!cl->level && cl->un.leaf.q) |
1104 | tcm->tcm_info = cl->un.leaf.q->handle; | 1082 | tcm->tcm_info = cl->un.leaf.q->handle; |
1105 | 1083 | ||
@@ -1119,11 +1097,11 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, | |||
1119 | NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt); | 1097 | NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt); |
1120 | 1098 | ||
1121 | nla_nest_end(skb, nest); | 1099 | nla_nest_end(skb, nest); |
1122 | spin_unlock_bh(&sch->dev->queue_lock); | 1100 | spin_unlock_bh(root_lock); |
1123 | return skb->len; | 1101 | return skb->len; |
1124 | 1102 | ||
1125 | nla_put_failure: | 1103 | nla_put_failure: |
1126 | spin_unlock_bh(&sch->dev->queue_lock); | 1104 | spin_unlock_bh(root_lock); |
1127 | nla_nest_cancel(skb, nest); | 1105 | nla_nest_cancel(skb, nest); |
1128 | return -1; | 1106 | return -1; |
1129 | } | 1107 | } |
@@ -1153,8 +1131,9 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | |||
1153 | 1131 | ||
1154 | if (cl && !cl->level) { | 1132 | if (cl && !cl->level) { |
1155 | if (new == NULL && | 1133 | if (new == NULL && |
1156 | (new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, | 1134 | (new = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue, |
1157 | cl->classid)) | 1135 | &pfifo_qdisc_ops, |
1136 | cl->common.classid)) | ||
1158 | == NULL) | 1137 | == NULL) |
1159 | return -ENOBUFS; | 1138 | return -ENOBUFS; |
1160 | sch_tree_lock(sch); | 1139 | sch_tree_lock(sch); |
@@ -1195,12 +1174,9 @@ static inline int htb_parent_last_child(struct htb_class *cl) | |||
1195 | if (!cl->parent) | 1174 | if (!cl->parent) |
1196 | /* the root class */ | 1175 | /* the root class */ |
1197 | return 0; | 1176 | return 0; |
1198 | 1177 | if (cl->parent->children > 1) | |
1199 | if (!(cl->parent->children.next == &cl->sibling && | ||
1200 | cl->parent->children.prev == &cl->sibling)) | ||
1201 | /* not the last child */ | 1178 | /* not the last child */ |
1202 | return 0; | 1179 | return 0; |
1203 | |||
1204 | return 1; | 1180 | return 1; |
1205 | } | 1181 | } |
1206 | 1182 | ||
@@ -1228,8 +1204,6 @@ static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl, | |||
1228 | 1204 | ||
1229 | static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) | 1205 | static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) |
1230 | { | 1206 | { |
1231 | struct htb_sched *q = qdisc_priv(sch); | ||
1232 | |||
1233 | if (!cl->level) { | 1207 | if (!cl->level) { |
1234 | BUG_TRAP(cl->un.leaf.q); | 1208 | BUG_TRAP(cl->un.leaf.q); |
1235 | qdisc_destroy(cl->un.leaf.q); | 1209 | qdisc_destroy(cl->un.leaf.q); |
@@ -1239,21 +1213,6 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) | |||
1239 | qdisc_put_rtab(cl->ceil); | 1213 | qdisc_put_rtab(cl->ceil); |
1240 | 1214 | ||
1241 | tcf_destroy_chain(&cl->filter_list); | 1215 | tcf_destroy_chain(&cl->filter_list); |
1242 | |||
1243 | while (!list_empty(&cl->children)) | ||
1244 | htb_destroy_class(sch, list_entry(cl->children.next, | ||
1245 | struct htb_class, sibling)); | ||
1246 | |||
1247 | /* note: this delete may happen twice (see htb_delete) */ | ||
1248 | hlist_del_init(&cl->hlist); | ||
1249 | list_del(&cl->sibling); | ||
1250 | |||
1251 | if (cl->prio_activity) | ||
1252 | htb_deactivate(q, cl); | ||
1253 | |||
1254 | if (cl->cmode != HTB_CAN_SEND) | ||
1255 | htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level); | ||
1256 | |||
1257 | kfree(cl); | 1216 | kfree(cl); |
1258 | } | 1217 | } |
1259 | 1218 | ||
@@ -1261,6 +1220,9 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) | |||
1261 | static void htb_destroy(struct Qdisc *sch) | 1220 | static void htb_destroy(struct Qdisc *sch) |
1262 | { | 1221 | { |
1263 | struct htb_sched *q = qdisc_priv(sch); | 1222 | struct htb_sched *q = qdisc_priv(sch); |
1223 | struct hlist_node *n, *next; | ||
1224 | struct htb_class *cl; | ||
1225 | unsigned int i; | ||
1264 | 1226 | ||
1265 | qdisc_watchdog_cancel(&q->watchdog); | 1227 | qdisc_watchdog_cancel(&q->watchdog); |
1266 | /* This line used to be after htb_destroy_class call below | 1228 | /* This line used to be after htb_destroy_class call below |
@@ -1269,10 +1231,16 @@ static void htb_destroy(struct Qdisc *sch) | |||
1269 | unbind_filter on it (without Oops). */ | 1231 | unbind_filter on it (without Oops). */ |
1270 | tcf_destroy_chain(&q->filter_list); | 1232 | tcf_destroy_chain(&q->filter_list); |
1271 | 1233 | ||
1272 | while (!list_empty(&q->root)) | 1234 | for (i = 0; i < q->clhash.hashsize; i++) { |
1273 | htb_destroy_class(sch, list_entry(q->root.next, | 1235 | hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) |
1274 | struct htb_class, sibling)); | 1236 | tcf_destroy_chain(&cl->filter_list); |
1275 | 1237 | } | |
1238 | for (i = 0; i < q->clhash.hashsize; i++) { | ||
1239 | hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i], | ||
1240 | common.hnode) | ||
1241 | htb_destroy_class(sch, cl); | ||
1242 | } | ||
1243 | qdisc_class_hash_destroy(&q->clhash); | ||
1276 | __skb_queue_purge(&q->direct_queue); | 1244 | __skb_queue_purge(&q->direct_queue); |
1277 | } | 1245 | } |
1278 | 1246 | ||
@@ -1287,12 +1255,13 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) | |||
1287 | // TODO: why don't allow to delete subtree ? references ? does | 1255 | // TODO: why don't allow to delete subtree ? references ? does |
1288 | // tc subsys quarantee us that in htb_destroy it holds no class | 1256 | // tc subsys quarantee us that in htb_destroy it holds no class |
1289 | // refs so that we can remove children safely there ? | 1257 | // refs so that we can remove children safely there ? |
1290 | if (!list_empty(&cl->children) || cl->filter_cnt) | 1258 | if (cl->children || cl->filter_cnt) |
1291 | return -EBUSY; | 1259 | return -EBUSY; |
1292 | 1260 | ||
1293 | if (!cl->level && htb_parent_last_child(cl)) { | 1261 | if (!cl->level && htb_parent_last_child(cl)) { |
1294 | new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, | 1262 | new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue, |
1295 | cl->parent->classid); | 1263 | &pfifo_qdisc_ops, |
1264 | cl->parent->common.classid); | ||
1296 | last_child = 1; | 1265 | last_child = 1; |
1297 | } | 1266 | } |
1298 | 1267 | ||
@@ -1305,11 +1274,15 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) | |||
1305 | } | 1274 | } |
1306 | 1275 | ||
1307 | /* delete from hash and active; remainder in destroy_class */ | 1276 | /* delete from hash and active; remainder in destroy_class */ |
1308 | hlist_del_init(&cl->hlist); | 1277 | qdisc_class_hash_remove(&q->clhash, &cl->common); |
1278 | cl->parent->children--; | ||
1309 | 1279 | ||
1310 | if (cl->prio_activity) | 1280 | if (cl->prio_activity) |
1311 | htb_deactivate(q, cl); | 1281 | htb_deactivate(q, cl); |
1312 | 1282 | ||
1283 | if (cl->cmode != HTB_CAN_SEND) | ||
1284 | htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level); | ||
1285 | |||
1313 | if (last_child) | 1286 | if (last_child) |
1314 | htb_parent_to_leaf(q, cl, new_q); | 1287 | htb_parent_to_leaf(q, cl, new_q); |
1315 | 1288 | ||
@@ -1394,12 +1367,10 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1394 | goto failure; | 1367 | goto failure; |
1395 | 1368 | ||
1396 | gen_new_estimator(&cl->bstats, &cl->rate_est, | 1369 | gen_new_estimator(&cl->bstats, &cl->rate_est, |
1397 | &sch->dev->queue_lock, | 1370 | qdisc_root_lock(sch), |
1398 | tca[TCA_RATE] ? : &est.nla); | 1371 | tca[TCA_RATE] ? : &est.nla); |
1399 | cl->refcnt = 1; | 1372 | cl->refcnt = 1; |
1400 | INIT_LIST_HEAD(&cl->sibling); | 1373 | cl->children = 0; |
1401 | INIT_HLIST_NODE(&cl->hlist); | ||
1402 | INIT_LIST_HEAD(&cl->children); | ||
1403 | INIT_LIST_HEAD(&cl->un.leaf.drop_list); | 1374 | INIT_LIST_HEAD(&cl->un.leaf.drop_list); |
1404 | RB_CLEAR_NODE(&cl->pq_node); | 1375 | RB_CLEAR_NODE(&cl->pq_node); |
1405 | 1376 | ||
@@ -1409,7 +1380,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1409 | /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL) | 1380 | /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL) |
1410 | so that can't be used inside of sch_tree_lock | 1381 | so that can't be used inside of sch_tree_lock |
1411 | -- thanks to Karlis Peisenieks */ | 1382 | -- thanks to Karlis Peisenieks */ |
1412 | new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid); | 1383 | new_q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue, |
1384 | &pfifo_qdisc_ops, classid); | ||
1413 | sch_tree_lock(sch); | 1385 | sch_tree_lock(sch); |
1414 | if (parent && !parent->level) { | 1386 | if (parent && !parent->level) { |
1415 | unsigned int qlen = parent->un.leaf.q->q.qlen; | 1387 | unsigned int qlen = parent->un.leaf.q->q.qlen; |
@@ -1433,7 +1405,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1433 | /* leaf (we) needs elementary qdisc */ | 1405 | /* leaf (we) needs elementary qdisc */ |
1434 | cl->un.leaf.q = new_q ? new_q : &noop_qdisc; | 1406 | cl->un.leaf.q = new_q ? new_q : &noop_qdisc; |
1435 | 1407 | ||
1436 | cl->classid = classid; | 1408 | cl->common.classid = classid; |
1437 | cl->parent = parent; | 1409 | cl->parent = parent; |
1438 | 1410 | ||
1439 | /* set class to be in HTB_CAN_SEND state */ | 1411 | /* set class to be in HTB_CAN_SEND state */ |
@@ -1444,13 +1416,13 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1444 | cl->cmode = HTB_CAN_SEND; | 1416 | cl->cmode = HTB_CAN_SEND; |
1445 | 1417 | ||
1446 | /* attach to the hash list and parent's family */ | 1418 | /* attach to the hash list and parent's family */ |
1447 | hlist_add_head(&cl->hlist, q->hash + htb_hash(classid)); | 1419 | qdisc_class_hash_insert(&q->clhash, &cl->common); |
1448 | list_add_tail(&cl->sibling, | 1420 | if (parent) |
1449 | parent ? &parent->children : &q->root); | 1421 | parent->children++; |
1450 | } else { | 1422 | } else { |
1451 | if (tca[TCA_RATE]) | 1423 | if (tca[TCA_RATE]) |
1452 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | 1424 | gen_replace_estimator(&cl->bstats, &cl->rate_est, |
1453 | &sch->dev->queue_lock, | 1425 | qdisc_root_lock(sch), |
1454 | tca[TCA_RATE]); | 1426 | tca[TCA_RATE]); |
1455 | sch_tree_lock(sch); | 1427 | sch_tree_lock(sch); |
1456 | } | 1428 | } |
@@ -1462,13 +1434,13 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1462 | if (!hopt->quantum && cl->un.leaf.quantum < 1000) { | 1434 | if (!hopt->quantum && cl->un.leaf.quantum < 1000) { |
1463 | printk(KERN_WARNING | 1435 | printk(KERN_WARNING |
1464 | "HTB: quantum of class %X is small. Consider r2q change.\n", | 1436 | "HTB: quantum of class %X is small. Consider r2q change.\n", |
1465 | cl->classid); | 1437 | cl->common.classid); |
1466 | cl->un.leaf.quantum = 1000; | 1438 | cl->un.leaf.quantum = 1000; |
1467 | } | 1439 | } |
1468 | if (!hopt->quantum && cl->un.leaf.quantum > 200000) { | 1440 | if (!hopt->quantum && cl->un.leaf.quantum > 200000) { |
1469 | printk(KERN_WARNING | 1441 | printk(KERN_WARNING |
1470 | "HTB: quantum of class %X is big. Consider r2q change.\n", | 1442 | "HTB: quantum of class %X is big. Consider r2q change.\n", |
1471 | cl->classid); | 1443 | cl->common.classid); |
1472 | cl->un.leaf.quantum = 200000; | 1444 | cl->un.leaf.quantum = 200000; |
1473 | } | 1445 | } |
1474 | if (hopt->quantum) | 1446 | if (hopt->quantum) |
@@ -1491,6 +1463,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1491 | cl->ceil = ctab; | 1463 | cl->ceil = ctab; |
1492 | sch_tree_unlock(sch); | 1464 | sch_tree_unlock(sch); |
1493 | 1465 | ||
1466 | qdisc_class_hash_grow(sch, &q->clhash); | ||
1467 | |||
1494 | *arg = (unsigned long)cl; | 1468 | *arg = (unsigned long)cl; |
1495 | return 0; | 1469 | return 0; |
1496 | 1470 | ||
@@ -1514,7 +1488,6 @@ static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg) | |||
1514 | static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, | 1488 | static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, |
1515 | u32 classid) | 1489 | u32 classid) |
1516 | { | 1490 | { |
1517 | struct htb_sched *q = qdisc_priv(sch); | ||
1518 | struct htb_class *cl = htb_find(classid, sch); | 1491 | struct htb_class *cl = htb_find(classid, sch); |
1519 | 1492 | ||
1520 | /*if (cl && !cl->level) return 0; | 1493 | /*if (cl && !cl->level) return 0; |
@@ -1528,35 +1501,29 @@ static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, | |||
1528 | */ | 1501 | */ |
1529 | if (cl) | 1502 | if (cl) |
1530 | cl->filter_cnt++; | 1503 | cl->filter_cnt++; |
1531 | else | ||
1532 | q->filter_cnt++; | ||
1533 | return (unsigned long)cl; | 1504 | return (unsigned long)cl; |
1534 | } | 1505 | } |
1535 | 1506 | ||
1536 | static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg) | 1507 | static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg) |
1537 | { | 1508 | { |
1538 | struct htb_sched *q = qdisc_priv(sch); | ||
1539 | struct htb_class *cl = (struct htb_class *)arg; | 1509 | struct htb_class *cl = (struct htb_class *)arg; |
1540 | 1510 | ||
1541 | if (cl) | 1511 | if (cl) |
1542 | cl->filter_cnt--; | 1512 | cl->filter_cnt--; |
1543 | else | ||
1544 | q->filter_cnt--; | ||
1545 | } | 1513 | } |
1546 | 1514 | ||
1547 | static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg) | 1515 | static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg) |
1548 | { | 1516 | { |
1549 | struct htb_sched *q = qdisc_priv(sch); | 1517 | struct htb_sched *q = qdisc_priv(sch); |
1550 | int i; | 1518 | struct htb_class *cl; |
1519 | struct hlist_node *n; | ||
1520 | unsigned int i; | ||
1551 | 1521 | ||
1552 | if (arg->stop) | 1522 | if (arg->stop) |
1553 | return; | 1523 | return; |
1554 | 1524 | ||
1555 | for (i = 0; i < HTB_HSIZE; i++) { | 1525 | for (i = 0; i < q->clhash.hashsize; i++) { |
1556 | struct hlist_node *p; | 1526 | hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) { |
1557 | struct htb_class *cl; | ||
1558 | |||
1559 | hlist_for_each_entry(cl, p, q->hash + i, hlist) { | ||
1560 | if (arg->count < arg->skip) { | 1527 | if (arg->count < arg->skip) { |
1561 | arg->count++; | 1528 | arg->count++; |
1562 | continue; | 1529 | continue; |