aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-12-05 09:37:56 -0500
committerDavid Howells <dhowells@warthog.cambridge.redhat.com>2006-12-05 09:37:56 -0500
commit4c1ac1b49122b805adfa4efc620592f68dccf5db (patch)
tree87557f4bc2fd4fe65b7570489c2f610c45c0adcd /net/sched
parentc4028958b6ecad064b1a6303a6a5906d4fe48d73 (diff)
parentd916faace3efc0bf19fe9a615a1ab8fa1a24cd93 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/infiniband/core/iwcm.c drivers/net/chelsio/cxgb2.c drivers/net/wireless/bcm43xx/bcm43xx_main.c drivers/net/wireless/prism54/islpci_eth.c drivers/usb/core/hub.h drivers/usb/input/hid-core.c net/core/netpoll.c Fix up merge failures with Linus's head and fix new compilation failures. Signed-Off-By: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/Kconfig6
-rw-r--r--net/sched/Makefile3
-rw-r--r--net/sched/act_gact.c4
-rw-r--r--net/sched/act_ipt.c6
-rw-r--r--net/sched/act_police.c26
-rw-r--r--net/sched/act_simple.c3
-rw-r--r--net/sched/cls_api.c3
-rw-r--r--net/sched/cls_fw.c6
-rw-r--r--net/sched/cls_rsvp.h16
-rw-r--r--net/sched/cls_u32.c2
-rw-r--r--net/sched/em_meta.c13
-rw-r--r--net/sched/em_nbyte.c4
-rw-r--r--net/sched/ematch.c3
-rw-r--r--net/sched/sch_api.c41
-rw-r--r--net/sched/sch_atm.c5
-rw-r--r--net/sched/sch_cbq.c10
-rw-r--r--net/sched/sch_dsmark.c9
-rw-r--r--net/sched/sch_generic.c10
-rw-r--r--net/sched/sch_hfsc.c27
-rw-r--r--net/sched/sch_htb.c36
-rw-r--r--net/sched/sch_netem.c10
-rw-r--r--net/sched/sch_prio.c14
-rw-r--r--net/sched/sch_red.c14
-rw-r--r--net/sched/sch_sfq.c3
-rw-r--r--net/sched/sch_tbf.c16
25 files changed, 184 insertions, 106 deletions
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 8298ea9ffe19..f4544dd86476 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -6,6 +6,7 @@ menu "QoS and/or fair queueing"
6 6
7config NET_SCHED 7config NET_SCHED
8 bool "QoS and/or fair queueing" 8 bool "QoS and/or fair queueing"
9 select NET_SCH_FIFO
9 ---help--- 10 ---help---
10 When the kernel has several packets to send out over a network 11 When the kernel has several packets to send out over a network
11 device, it has to decide which ones to send first, which ones to 12 device, it has to decide which ones to send first, which ones to
@@ -40,6 +41,9 @@ config NET_SCHED
40 The available schedulers are listed in the following questions; you 41 The available schedulers are listed in the following questions; you
41 can say Y to as many as you like. If unsure, say N now. 42 can say Y to as many as you like. If unsure, say N now.
42 43
44config NET_SCH_FIFO
45 bool
46
43if NET_SCHED 47if NET_SCHED
44 48
45choice 49choice
@@ -320,7 +324,7 @@ config CLS_U32_PERF
320 324
321config CLS_U32_MARK 325config CLS_U32_MARK
322 bool "Netfilter marks support" 326 bool "Netfilter marks support"
323 depends on NET_CLS_U32 && NETFILTER 327 depends on NET_CLS_U32
324 ---help--- 328 ---help---
325 Say Y here to be able to use netfilter marks as u32 key. 329 Say Y here to be able to use netfilter marks as u32 key.
326 330
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 0f06aec66094..ff2d6e5e282c 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -4,7 +4,7 @@
4 4
5obj-y := sch_generic.o 5obj-y := sch_generic.o
6 6
7obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o sch_blackhole.o 7obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o
8obj-$(CONFIG_NET_CLS) += cls_api.o 8obj-$(CONFIG_NET_CLS) += cls_api.o
9obj-$(CONFIG_NET_CLS_ACT) += act_api.o 9obj-$(CONFIG_NET_CLS_ACT) += act_api.o
10obj-$(CONFIG_NET_ACT_POLICE) += act_police.o 10obj-$(CONFIG_NET_ACT_POLICE) += act_police.o
@@ -14,6 +14,7 @@ obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o
14obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o 14obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o
15obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o 15obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o
16obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o 16obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o
17obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o
17obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o 18obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
18obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o 19obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
19obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o 20obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 6cff56696a81..85de7efd5fea 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -48,14 +48,14 @@ static struct tcf_hashinfo gact_hash_info = {
48#ifdef CONFIG_GACT_PROB 48#ifdef CONFIG_GACT_PROB
49static int gact_net_rand(struct tcf_gact *gact) 49static int gact_net_rand(struct tcf_gact *gact)
50{ 50{
51 if (net_random() % gact->tcfg_pval) 51 if (!gact->tcfg_pval || net_random() % gact->tcfg_pval)
52 return gact->tcf_action; 52 return gact->tcf_action;
53 return gact->tcfg_paction; 53 return gact->tcfg_paction;
54} 54}
55 55
56static int gact_determ(struct tcf_gact *gact) 56static int gact_determ(struct tcf_gact *gact)
57{ 57{
58 if (gact->tcf_bstats.packets % gact->tcfg_pval) 58 if (!gact->tcfg_pval || gact->tcf_bstats.packets % gact->tcfg_pval)
59 return gact->tcf_action; 59 return gact->tcf_action;
60 return gact->tcfg_paction; 60 return gact->tcfg_paction;
61} 61}
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index d8c9310da6e5..a9608064a4c3 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -156,10 +156,9 @@ static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est,
156 rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) 156 rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ)
157 strcpy(tname, "mangle"); 157 strcpy(tname, "mangle");
158 158
159 t = kmalloc(td->u.target_size, GFP_KERNEL); 159 t = kmemdup(td, td->u.target_size, GFP_KERNEL);
160 if (unlikely(!t)) 160 if (unlikely(!t))
161 goto err2; 161 goto err2;
162 memcpy(t, td, td->u.target_size);
163 162
164 if ((err = ipt_init_target(t, tname, hook)) < 0) 163 if ((err = ipt_init_target(t, tname, hook)) < 0)
165 goto err3; 164 goto err3;
@@ -256,13 +255,12 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int
256 ** for foolproof you need to not assume this 255 ** for foolproof you need to not assume this
257 */ 256 */
258 257
259 t = kmalloc(ipt->tcfi_t->u.user.target_size, GFP_ATOMIC); 258 t = kmemdup(ipt->tcfi_t, ipt->tcfi_t->u.user.target_size, GFP_ATOMIC);
260 if (unlikely(!t)) 259 if (unlikely(!t))
261 goto rtattr_failure; 260 goto rtattr_failure;
262 261
263 c.bindcnt = ipt->tcf_bindcnt - bind; 262 c.bindcnt = ipt->tcf_bindcnt - bind;
264 c.refcnt = ipt->tcf_refcnt - ref; 263 c.refcnt = ipt->tcf_refcnt - ref;
265 memcpy(t, ipt->tcfi_t, ipt->tcfi_t->u.user.target_size);
266 strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name); 264 strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name);
267 265
268 RTA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t); 266 RTA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t);
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index fed47b658837..af68e1e83251 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -46,6 +46,18 @@ static struct tcf_hashinfo police_hash_info = {
46 .lock = &police_lock, 46 .lock = &police_lock,
47}; 47};
48 48
49/* old policer structure from before tc actions */
50struct tc_police_compat
51{
52 u32 index;
53 int action;
54 u32 limit;
55 u32 burst;
56 u32 mtu;
57 struct tc_ratespec rate;
58 struct tc_ratespec peakrate;
59};
60
49/* Each policer is serialized by its individual spinlock */ 61/* Each policer is serialized by its individual spinlock */
50 62
51#ifdef CONFIG_NET_CLS_ACT 63#ifdef CONFIG_NET_CLS_ACT
@@ -131,12 +143,15 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est,
131 struct tc_police *parm; 143 struct tc_police *parm;
132 struct tcf_police *police; 144 struct tcf_police *police;
133 struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; 145 struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
146 int size;
134 147
135 if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) 148 if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
136 return -EINVAL; 149 return -EINVAL;
137 150
138 if (tb[TCA_POLICE_TBF-1] == NULL || 151 if (tb[TCA_POLICE_TBF-1] == NULL)
139 RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm)) 152 return -EINVAL;
153 size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
154 if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
140 return -EINVAL; 155 return -EINVAL;
141 parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); 156 parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
142 157
@@ -415,12 +430,15 @@ struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est)
415 struct tcf_police *police; 430 struct tcf_police *police;
416 struct rtattr *tb[TCA_POLICE_MAX]; 431 struct rtattr *tb[TCA_POLICE_MAX];
417 struct tc_police *parm; 432 struct tc_police *parm;
433 int size;
418 434
419 if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) 435 if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0)
420 return NULL; 436 return NULL;
421 437
422 if (tb[TCA_POLICE_TBF-1] == NULL || 438 if (tb[TCA_POLICE_TBF-1] == NULL)
423 RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm)) 439 return NULL;
440 size = RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]);
441 if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
424 return NULL; 442 return NULL;
425 443
426 parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); 444 parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 901571a67707..5fe80854ca91 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -71,11 +71,10 @@ static int tcf_simp_release(struct tcf_defact *d, int bind)
71 71
72static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata) 72static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
73{ 73{
74 d->tcfd_defdata = kmalloc(datalen, GFP_KERNEL); 74 d->tcfd_defdata = kmemdup(defdata, datalen, GFP_KERNEL);
75 if (unlikely(!d->tcfd_defdata)) 75 if (unlikely(!d->tcfd_defdata))
76 return -ENOMEM; 76 return -ENOMEM;
77 d->tcfd_datalen = datalen; 77 d->tcfd_datalen = datalen;
78 memcpy(d->tcfd_defdata, defdata, datalen);
79 return 0; 78 return 0;
80} 79}
81 80
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 37a184021647..edb8fc97ae11 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -217,7 +217,7 @@ replay:
217 /* Create new proto tcf */ 217 /* Create new proto tcf */
218 218
219 err = -ENOBUFS; 219 err = -ENOBUFS;
220 if ((tp = kmalloc(sizeof(*tp), GFP_KERNEL)) == NULL) 220 if ((tp = kzalloc(sizeof(*tp), GFP_KERNEL)) == NULL)
221 goto errout; 221 goto errout;
222 err = -EINVAL; 222 err = -EINVAL;
223 tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]); 223 tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]);
@@ -247,7 +247,6 @@ replay:
247 kfree(tp); 247 kfree(tp);
248 goto errout; 248 goto errout;
249 } 249 }
250 memset(tp, 0, sizeof(*tp));
251 tp->ops = tp_ops; 250 tp->ops = tp_ops;
252 tp->protocol = protocol; 251 tp->protocol = protocol;
253 tp->prio = nprio ? : tcf_auto_prio(*back); 252 tp->prio = nprio ? : tcf_auto_prio(*back);
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index e54acc6bcccd..f59a2c4aa039 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -101,11 +101,7 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
101 struct fw_head *head = (struct fw_head*)tp->root; 101 struct fw_head *head = (struct fw_head*)tp->root;
102 struct fw_filter *f; 102 struct fw_filter *f;
103 int r; 103 int r;
104#ifdef CONFIG_NETFILTER 104 u32 id = skb->mark & head->mask;
105 u32 id = skb->nfmark & head->mask;
106#else
107 u32 id = 0;
108#endif
109 105
110 if (head != NULL) { 106 if (head != NULL) {
111 for (f=head->ht[fw_hash(id)]; f; f=f->next) { 107 for (f=head->ht[fw_hash(id)]; f; f=f->next) {
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 6e230ecfba05..587b9adab38c 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -77,7 +77,7 @@ struct rsvp_head
77struct rsvp_session 77struct rsvp_session
78{ 78{
79 struct rsvp_session *next; 79 struct rsvp_session *next;
80 u32 dst[RSVP_DST_LEN]; 80 __be32 dst[RSVP_DST_LEN];
81 struct tc_rsvp_gpi dpi; 81 struct tc_rsvp_gpi dpi;
82 u8 protocol; 82 u8 protocol;
83 u8 tunnelid; 83 u8 tunnelid;
@@ -89,7 +89,7 @@ struct rsvp_session
89struct rsvp_filter 89struct rsvp_filter
90{ 90{
91 struct rsvp_filter *next; 91 struct rsvp_filter *next;
92 u32 src[RSVP_DST_LEN]; 92 __be32 src[RSVP_DST_LEN];
93 struct tc_rsvp_gpi spi; 93 struct tc_rsvp_gpi spi;
94 u8 tunnelhdr; 94 u8 tunnelhdr;
95 95
@@ -100,17 +100,17 @@ struct rsvp_filter
100 struct rsvp_session *sess; 100 struct rsvp_session *sess;
101}; 101};
102 102
103static __inline__ unsigned hash_dst(u32 *dst, u8 protocol, u8 tunnelid) 103static __inline__ unsigned hash_dst(__be32 *dst, u8 protocol, u8 tunnelid)
104{ 104{
105 unsigned h = dst[RSVP_DST_LEN-1]; 105 unsigned h = (__force __u32)dst[RSVP_DST_LEN-1];
106 h ^= h>>16; 106 h ^= h>>16;
107 h ^= h>>8; 107 h ^= h>>8;
108 return (h ^ protocol ^ tunnelid) & 0xFF; 108 return (h ^ protocol ^ tunnelid) & 0xFF;
109} 109}
110 110
111static __inline__ unsigned hash_src(u32 *src) 111static __inline__ unsigned hash_src(__be32 *src)
112{ 112{
113 unsigned h = src[RSVP_DST_LEN-1]; 113 unsigned h = (__force __u32)src[RSVP_DST_LEN-1];
114 h ^= h>>16; 114 h ^= h>>16;
115 h ^= h>>8; 115 h ^= h>>8;
116 h ^= h>>4; 116 h ^= h>>4;
@@ -138,7 +138,7 @@ static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp,
138 struct rsvp_session *s; 138 struct rsvp_session *s;
139 struct rsvp_filter *f; 139 struct rsvp_filter *f;
140 unsigned h1, h2; 140 unsigned h1, h2;
141 u32 *dst, *src; 141 __be32 *dst, *src;
142 u8 protocol; 142 u8 protocol;
143 u8 tunnelid = 0; 143 u8 tunnelid = 0;
144 u8 *xprt; 144 u8 *xprt;
@@ -410,7 +410,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
410 struct rtattr *tb[TCA_RSVP_MAX]; 410 struct rtattr *tb[TCA_RSVP_MAX];
411 struct tcf_exts e; 411 struct tcf_exts e;
412 unsigned h1, h2; 412 unsigned h1, h2;
413 u32 *dst; 413 __be32 *dst;
414 int err; 414 int err;
415 415
416 if (opt == NULL) 416 if (opt == NULL)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 0a6cfa0005be..8b5194801995 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -143,7 +143,7 @@ next_knode:
143#endif 143#endif
144 144
145#ifdef CONFIG_CLS_U32_MARK 145#ifdef CONFIG_CLS_U32_MARK
146 if ((skb->nfmark & n->mark.mask) != n->mark.val) { 146 if ((skb->mark & n->mark.mask) != n->mark.val) {
147 n = n->next; 147 n = n->next;
148 goto next_knode; 148 goto next_knode;
149 } else { 149 } else {
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 61e3b740ab1a..45d47d37155e 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -208,13 +208,9 @@ META_COLLECTOR(int_maclen)
208 * Netfilter 208 * Netfilter
209 **************************************************************************/ 209 **************************************************************************/
210 210
211META_COLLECTOR(int_nfmark) 211META_COLLECTOR(int_mark)
212{ 212{
213#ifdef CONFIG_NETFILTER 213 dst->value = skb->mark;
214 dst->value = skb->nfmark;
215#else
216 dst->value = 0;
217#endif
218} 214}
219 215
220/************************************************************************** 216/**************************************************************************
@@ -490,7 +486,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {
490 [META_ID(PKTLEN)] = META_FUNC(int_pktlen), 486 [META_ID(PKTLEN)] = META_FUNC(int_pktlen),
491 [META_ID(DATALEN)] = META_FUNC(int_datalen), 487 [META_ID(DATALEN)] = META_FUNC(int_datalen),
492 [META_ID(MACLEN)] = META_FUNC(int_maclen), 488 [META_ID(MACLEN)] = META_FUNC(int_maclen),
493 [META_ID(NFMARK)] = META_FUNC(int_nfmark), 489 [META_ID(NFMARK)] = META_FUNC(int_mark),
494 [META_ID(TCINDEX)] = META_FUNC(int_tcindex), 490 [META_ID(TCINDEX)] = META_FUNC(int_tcindex),
495 [META_ID(RTCLASSID)] = META_FUNC(int_rtclassid), 491 [META_ID(RTCLASSID)] = META_FUNC(int_rtclassid),
496 [META_ID(RTIIF)] = META_FUNC(int_rtiif), 492 [META_ID(RTIIF)] = META_FUNC(int_rtiif),
@@ -550,10 +546,9 @@ static int meta_var_change(struct meta_value *dst, struct rtattr *rta)
550{ 546{
551 int len = RTA_PAYLOAD(rta); 547 int len = RTA_PAYLOAD(rta);
552 548
553 dst->val = (unsigned long) kmalloc(len, GFP_KERNEL); 549 dst->val = (unsigned long)kmemdup(RTA_DATA(rta), len, GFP_KERNEL);
554 if (dst->val == 0UL) 550 if (dst->val == 0UL)
555 return -ENOMEM; 551 return -ENOMEM;
556 memcpy((void *) dst->val, RTA_DATA(rta), len);
557 dst->len = len; 552 dst->len = len;
558 return 0; 553 return 0;
559} 554}
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c
index cc80babfd79f..005db409be64 100644
--- a/net/sched/em_nbyte.c
+++ b/net/sched/em_nbyte.c
@@ -34,12 +34,10 @@ static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len,
34 return -EINVAL; 34 return -EINVAL;
35 35
36 em->datalen = sizeof(*nbyte) + nbyte->len; 36 em->datalen = sizeof(*nbyte) + nbyte->len;
37 em->data = (unsigned long) kmalloc(em->datalen, GFP_KERNEL); 37 em->data = (unsigned long)kmemdup(data, em->datalen, GFP_KERNEL);
38 if (em->data == 0UL) 38 if (em->data == 0UL)
39 return -ENOBUFS; 39 return -ENOBUFS;
40 40
41 memcpy((void *) em->data, data, em->datalen);
42
43 return 0; 41 return 0;
44} 42}
45 43
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 0fd0768a17c6..8f8a16da72a8 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -251,12 +251,11 @@ static int tcf_em_validate(struct tcf_proto *tp,
251 goto errout; 251 goto errout;
252 em->data = *(u32 *) data; 252 em->data = *(u32 *) data;
253 } else { 253 } else {
254 void *v = kmalloc(data_len, GFP_KERNEL); 254 void *v = kmemdup(data, data_len, GFP_KERNEL);
255 if (v == NULL) { 255 if (v == NULL) {
256 err = -ENOBUFS; 256 err = -ENOBUFS;
257 goto errout; 257 goto errout;
258 } 258 }
259 memcpy(v, data, data_len);
260 em->data = (unsigned long) v; 259 em->data = (unsigned long) v;
261 } 260 }
262 } 261 }
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 0b6489291140..65825f4409d9 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -191,21 +191,27 @@ int unregister_qdisc(struct Qdisc_ops *qops)
191 (root qdisc, all its children, children of children etc.) 191 (root qdisc, all its children, children of children etc.)
192 */ 192 */
193 193
194struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) 194static struct Qdisc *__qdisc_lookup(struct net_device *dev, u32 handle)
195{ 195{
196 struct Qdisc *q; 196 struct Qdisc *q;
197 197
198 read_lock(&qdisc_tree_lock);
199 list_for_each_entry(q, &dev->qdisc_list, list) { 198 list_for_each_entry(q, &dev->qdisc_list, list) {
200 if (q->handle == handle) { 199 if (q->handle == handle)
201 read_unlock(&qdisc_tree_lock);
202 return q; 200 return q;
203 }
204 } 201 }
205 read_unlock(&qdisc_tree_lock);
206 return NULL; 202 return NULL;
207} 203}
208 204
205struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
206{
207 struct Qdisc *q;
208
209 read_lock(&qdisc_tree_lock);
210 q = __qdisc_lookup(dev, handle);
211 read_unlock(&qdisc_tree_lock);
212 return q;
213}
214
209static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) 215static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid)
210{ 216{
211 unsigned long cl; 217 unsigned long cl;
@@ -348,6 +354,26 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
348 return oqdisc; 354 return oqdisc;
349} 355}
350 356
357void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
358{
359 struct Qdisc_class_ops *cops;
360 unsigned long cl;
361 u32 parentid;
362
363 if (n == 0)
364 return;
365 while ((parentid = sch->parent)) {
366 sch = __qdisc_lookup(sch->dev, TC_H_MAJ(parentid));
367 cops = sch->ops->cl_ops;
368 if (cops->qlen_notify) {
369 cl = cops->get(sch, parentid);
370 cops->qlen_notify(sch, cl);
371 cops->put(sch, cl);
372 }
373 sch->q.qlen -= n;
374 }
375}
376EXPORT_SYMBOL(qdisc_tree_decrease_qlen);
351 377
352/* Graft qdisc "new" to class "classid" of qdisc "parent" or 378/* Graft qdisc "new" to class "classid" of qdisc "parent" or
353 to device "dev". 379 to device "dev".
@@ -1112,7 +1138,7 @@ int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
1112 struct tcf_result *res) 1138 struct tcf_result *res)
1113{ 1139{
1114 int err = 0; 1140 int err = 0;
1115 u32 protocol = skb->protocol; 1141 __be16 protocol = skb->protocol;
1116#ifdef CONFIG_NET_CLS_ACT 1142#ifdef CONFIG_NET_CLS_ACT
1117 struct tcf_proto *otp = tp; 1143 struct tcf_proto *otp = tp;
1118reclassify: 1144reclassify:
@@ -1277,7 +1303,6 @@ static int __init pktsched_init(void)
1277 1303
1278subsys_initcall(pktsched_init); 1304subsys_initcall(pktsched_init);
1279 1305
1280EXPORT_SYMBOL(qdisc_lookup);
1281EXPORT_SYMBOL(qdisc_get_rtab); 1306EXPORT_SYMBOL(qdisc_get_rtab);
1282EXPORT_SYMBOL(qdisc_put_rtab); 1307EXPORT_SYMBOL(qdisc_put_rtab);
1283EXPORT_SYMBOL(register_qdisc); 1308EXPORT_SYMBOL(register_qdisc);
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index dbf44da0912f..edc7bb0b9c8b 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -316,7 +316,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
316 } 316 }
317 memset(flow,0,sizeof(*flow)); 317 memset(flow,0,sizeof(*flow));
318 flow->filter_list = NULL; 318 flow->filter_list = NULL;
319 if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops))) 319 if (!(flow->q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,classid)))
320 flow->q = &noop_qdisc; 320 flow->q = &noop_qdisc;
321 DPRINTK("atm_tc_change: qdisc %p\n",flow->q); 321 DPRINTK("atm_tc_change: qdisc %p\n",flow->q);
322 flow->sock = sock; 322 flow->sock = sock;
@@ -576,7 +576,8 @@ static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt)
576 576
577 DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt); 577 DPRINTK("atm_tc_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
578 p->flows = &p->link; 578 p->flows = &p->link;
579 if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops))) 579 if(!(p->link.q = qdisc_create_dflt(sch->dev,&pfifo_qdisc_ops,
580 sch->handle)))
580 p->link.q = &noop_qdisc; 581 p->link.q = &noop_qdisc;
581 DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q); 582 DPRINTK("atm_tc_init: link (%p) qdisc %p\n",&p->link,p->link.q);
582 p->link.filter_list = NULL; 583 p->link.filter_list = NULL;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index bac881bfe362..ba82dfab6043 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1429,7 +1429,8 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
1429 q->link.sibling = &q->link; 1429 q->link.sibling = &q->link;
1430 q->link.classid = sch->handle; 1430 q->link.classid = sch->handle;
1431 q->link.qdisc = sch; 1431 q->link.qdisc = sch;
1432 if (!(q->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops))) 1432 if (!(q->link.q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
1433 sch->handle)))
1433 q->link.q = &noop_qdisc; 1434 q->link.q = &noop_qdisc;
1434 1435
1435 q->link.priority = TC_CBQ_MAXPRIO-1; 1436 q->link.priority = TC_CBQ_MAXPRIO-1;
@@ -1674,7 +1675,8 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1674 1675
1675 if (cl) { 1676 if (cl) {
1676 if (new == NULL) { 1677 if (new == NULL) {
1677 if ((new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)) == NULL) 1678 if ((new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
1679 cl->classid)) == NULL)
1678 return -ENOBUFS; 1680 return -ENOBUFS;
1679 } else { 1681 } else {
1680#ifdef CONFIG_NET_CLS_POLICE 1682#ifdef CONFIG_NET_CLS_POLICE
@@ -1685,7 +1687,7 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1685 sch_tree_lock(sch); 1687 sch_tree_lock(sch);
1686 *old = cl->q; 1688 *old = cl->q;
1687 cl->q = new; 1689 cl->q = new;
1688 sch->q.qlen -= (*old)->q.qlen; 1690 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
1689 qdisc_reset(*old); 1691 qdisc_reset(*old);
1690 sch_tree_unlock(sch); 1692 sch_tree_unlock(sch);
1691 1693
@@ -1932,7 +1934,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct rtattr **t
1932 cl->R_tab = rtab; 1934 cl->R_tab = rtab;
1933 rtab = NULL; 1935 rtab = NULL;
1934 cl->refcnt = 1; 1936 cl->refcnt = 1;
1935 if (!(cl->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops))) 1937 if (!(cl->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid)))
1936 cl->q = &noop_qdisc; 1938 cl->q = &noop_qdisc;
1937 cl->classid = classid; 1939 cl->classid = classid;
1938 cl->tparent = parent; 1940 cl->tparent = parent;
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 11c8a2119b96..d5421816f007 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -88,15 +88,16 @@ static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
88 sch, p, new, old); 88 sch, p, new, old);
89 89
90 if (new == NULL) { 90 if (new == NULL) {
91 new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); 91 new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
92 sch->handle);
92 if (new == NULL) 93 if (new == NULL)
93 new = &noop_qdisc; 94 new = &noop_qdisc;
94 } 95 }
95 96
96 sch_tree_lock(sch); 97 sch_tree_lock(sch);
97 *old = xchg(&p->q, new); 98 *old = xchg(&p->q, new);
99 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
98 qdisc_reset(*old); 100 qdisc_reset(*old);
99 sch->q.qlen = 0;
100 sch_tree_unlock(sch); 101 sch_tree_unlock(sch);
101 102
102 return 0; 103 return 0;
@@ -307,7 +308,7 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
307 if (p->mask[index] != 0xff || p->value[index]) 308 if (p->mask[index] != 0xff || p->value[index])
308 printk(KERN_WARNING "dsmark_dequeue: " 309 printk(KERN_WARNING "dsmark_dequeue: "
309 "unsupported protocol %d\n", 310 "unsupported protocol %d\n",
310 htons(skb->protocol)); 311 ntohs(skb->protocol));
311 break; 312 break;
312 }; 313 };
313 314
@@ -387,7 +388,7 @@ static int dsmark_init(struct Qdisc *sch, struct rtattr *opt)
387 p->default_index = default_index; 388 p->default_index = default_index;
388 p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]); 389 p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]);
389 390
390 p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); 391 p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, sch->handle);
391 if (p->q == NULL) 392 if (p->q == NULL)
392 p->q = &noop_qdisc; 393 p->q = &noop_qdisc;
393 394
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 88c6a99ce53c..bc116bd6937c 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -450,13 +450,15 @@ errout:
450 return ERR_PTR(-err); 450 return ERR_PTR(-err);
451} 451}
452 452
453struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) 453struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops,
454 unsigned int parentid)
454{ 455{
455 struct Qdisc *sch; 456 struct Qdisc *sch;
456 457
457 sch = qdisc_alloc(dev, ops); 458 sch = qdisc_alloc(dev, ops);
458 if (IS_ERR(sch)) 459 if (IS_ERR(sch))
459 goto errout; 460 goto errout;
461 sch->parent = parentid;
460 462
461 if (!ops->init || ops->init(sch, NULL) == 0) 463 if (!ops->init || ops->init(sch, NULL) == 0)
462 return sch; 464 return sch;
@@ -520,7 +522,8 @@ void dev_activate(struct net_device *dev)
520 if (dev->qdisc_sleeping == &noop_qdisc) { 522 if (dev->qdisc_sleeping == &noop_qdisc) {
521 struct Qdisc *qdisc; 523 struct Qdisc *qdisc;
522 if (dev->tx_queue_len) { 524 if (dev->tx_queue_len) {
523 qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops); 525 qdisc = qdisc_create_dflt(dev, &pfifo_fast_ops,
526 TC_H_ROOT);
524 if (qdisc == NULL) { 527 if (qdisc == NULL) {
525 printk(KERN_INFO "%s: activation failed\n", dev->name); 528 printk(KERN_INFO "%s: activation failed\n", dev->name);
526 return; 529 return;
@@ -606,13 +609,10 @@ void dev_shutdown(struct net_device *dev)
606 qdisc_unlock_tree(dev); 609 qdisc_unlock_tree(dev);
607} 610}
608 611
609EXPORT_SYMBOL(__netdev_watchdog_up);
610EXPORT_SYMBOL(netif_carrier_on); 612EXPORT_SYMBOL(netif_carrier_on);
611EXPORT_SYMBOL(netif_carrier_off); 613EXPORT_SYMBOL(netif_carrier_off);
612EXPORT_SYMBOL(noop_qdisc); 614EXPORT_SYMBOL(noop_qdisc);
613EXPORT_SYMBOL(noop_qdisc_ops);
614EXPORT_SYMBOL(qdisc_create_dflt); 615EXPORT_SYMBOL(qdisc_create_dflt);
615EXPORT_SYMBOL(qdisc_alloc);
616EXPORT_SYMBOL(qdisc_destroy); 616EXPORT_SYMBOL(qdisc_destroy);
617EXPORT_SYMBOL(qdisc_reset); 617EXPORT_SYMBOL(qdisc_reset);
618EXPORT_SYMBOL(qdisc_lock_tree); 618EXPORT_SYMBOL(qdisc_lock_tree);
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 6a6735a2ed35..6eefa6995777 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -946,6 +946,7 @@ qdisc_peek_len(struct Qdisc *sch)
946 if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) { 946 if (unlikely(sch->ops->requeue(skb, sch) != NET_XMIT_SUCCESS)) {
947 if (net_ratelimit()) 947 if (net_ratelimit())
948 printk("qdisc_peek_len: failed to requeue\n"); 948 printk("qdisc_peek_len: failed to requeue\n");
949 qdisc_tree_decrease_qlen(sch, 1);
949 return 0; 950 return 0;
950 } 951 }
951 return len; 952 return len;
@@ -957,11 +958,7 @@ hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
957 unsigned int len = cl->qdisc->q.qlen; 958 unsigned int len = cl->qdisc->q.qlen;
958 959
959 qdisc_reset(cl->qdisc); 960 qdisc_reset(cl->qdisc);
960 if (len > 0) { 961 qdisc_tree_decrease_qlen(cl->qdisc, len);
961 update_vf(cl, 0, 0);
962 set_passive(cl);
963 sch->q.qlen -= len;
964 }
965} 962}
966 963
967static void 964static void
@@ -1138,7 +1135,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
1138 cl->classid = classid; 1135 cl->classid = classid;
1139 cl->sched = q; 1136 cl->sched = q;
1140 cl->cl_parent = parent; 1137 cl->cl_parent = parent;
1141 cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); 1138 cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
1142 if (cl->qdisc == NULL) 1139 if (cl->qdisc == NULL)
1143 cl->qdisc = &noop_qdisc; 1140 cl->qdisc = &noop_qdisc;
1144 cl->stats_lock = &sch->dev->queue_lock; 1141 cl->stats_lock = &sch->dev->queue_lock;
@@ -1271,7 +1268,8 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1271 if (cl->level > 0) 1268 if (cl->level > 0)
1272 return -EINVAL; 1269 return -EINVAL;
1273 if (new == NULL) { 1270 if (new == NULL) {
1274 new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); 1271 new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
1272 cl->classid);
1275 if (new == NULL) 1273 if (new == NULL)
1276 new = &noop_qdisc; 1274 new = &noop_qdisc;
1277 } 1275 }
@@ -1294,6 +1292,17 @@ hfsc_class_leaf(struct Qdisc *sch, unsigned long arg)
1294 return NULL; 1292 return NULL;
1295} 1293}
1296 1294
1295static void
1296hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg)
1297{
1298 struct hfsc_class *cl = (struct hfsc_class *)arg;
1299
1300 if (cl->qdisc->q.qlen == 0) {
1301 update_vf(cl, 0, 0);
1302 set_passive(cl);
1303 }
1304}
1305
1297static unsigned long 1306static unsigned long
1298hfsc_get_class(struct Qdisc *sch, u32 classid) 1307hfsc_get_class(struct Qdisc *sch, u32 classid)
1299{ 1308{
@@ -1514,7 +1523,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt)
1514 q->root.refcnt = 1; 1523 q->root.refcnt = 1;
1515 q->root.classid = sch->handle; 1524 q->root.classid = sch->handle;
1516 q->root.sched = q; 1525 q->root.sched = q;
1517 q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); 1526 q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
1527 sch->handle);
1518 if (q->root.qdisc == NULL) 1528 if (q->root.qdisc == NULL)
1519 q->root.qdisc = &noop_qdisc; 1529 q->root.qdisc = &noop_qdisc;
1520 q->root.stats_lock = &sch->dev->queue_lock; 1530 q->root.stats_lock = &sch->dev->queue_lock;
@@ -1777,6 +1787,7 @@ static struct Qdisc_class_ops hfsc_class_ops = {
1777 .delete = hfsc_delete_class, 1787 .delete = hfsc_delete_class,
1778 .graft = hfsc_graft_class, 1788 .graft = hfsc_graft_class,
1779 .leaf = hfsc_class_leaf, 1789 .leaf = hfsc_class_leaf,
1790 .qlen_notify = hfsc_qlen_notify,
1780 .get = hfsc_get_class, 1791 .get = hfsc_get_class,
1781 .put = hfsc_put_class, 1792 .put = hfsc_put_class,
1782 .bind_tcf = hfsc_bind_tcf, 1793 .bind_tcf = hfsc_bind_tcf,
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 4b52fa78935a..215e68c2b615 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1223,17 +1223,14 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1223 struct htb_class *cl = (struct htb_class *)arg; 1223 struct htb_class *cl = (struct htb_class *)arg;
1224 1224
1225 if (cl && !cl->level) { 1225 if (cl && !cl->level) {
1226 if (new == NULL && (new = qdisc_create_dflt(sch->dev, 1226 if (new == NULL &&
1227 &pfifo_qdisc_ops)) 1227 (new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
1228 cl->classid))
1228 == NULL) 1229 == NULL)
1229 return -ENOBUFS; 1230 return -ENOBUFS;
1230 sch_tree_lock(sch); 1231 sch_tree_lock(sch);
1231 if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) { 1232 if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) {
1232 if (cl->prio_activity) 1233 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
1233 htb_deactivate(qdisc_priv(sch), cl);
1234
1235 /* TODO: is it correct ? Why CBQ doesn't do it ? */
1236 sch->q.qlen -= (*old)->q.qlen;
1237 qdisc_reset(*old); 1234 qdisc_reset(*old);
1238 } 1235 }
1239 sch_tree_unlock(sch); 1236 sch_tree_unlock(sch);
@@ -1248,6 +1245,14 @@ static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg)
1248 return (cl && !cl->level) ? cl->un.leaf.q : NULL; 1245 return (cl && !cl->level) ? cl->un.leaf.q : NULL;
1249} 1246}
1250 1247
1248static void htb_qlen_notify(struct Qdisc *sch, unsigned long arg)
1249{
1250 struct htb_class *cl = (struct htb_class *)arg;
1251
1252 if (cl->un.leaf.q->q.qlen == 0)
1253 htb_deactivate(qdisc_priv(sch), cl);
1254}
1255
1251static unsigned long htb_get(struct Qdisc *sch, u32 classid) 1256static unsigned long htb_get(struct Qdisc *sch, u32 classid)
1252{ 1257{
1253 struct htb_class *cl = htb_find(classid, sch); 1258 struct htb_class *cl = htb_find(classid, sch);
@@ -1269,9 +1274,9 @@ static void htb_destroy_filters(struct tcf_proto **fl)
1269static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) 1274static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
1270{ 1275{
1271 struct htb_sched *q = qdisc_priv(sch); 1276 struct htb_sched *q = qdisc_priv(sch);
1277
1272 if (!cl->level) { 1278 if (!cl->level) {
1273 BUG_TRAP(cl->un.leaf.q); 1279 BUG_TRAP(cl->un.leaf.q);
1274 sch->q.qlen -= cl->un.leaf.q->q.qlen;
1275 qdisc_destroy(cl->un.leaf.q); 1280 qdisc_destroy(cl->un.leaf.q);
1276 } 1281 }
1277 qdisc_put_rtab(cl->rate); 1282 qdisc_put_rtab(cl->rate);
@@ -1322,6 +1327,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
1322{ 1327{
1323 struct htb_sched *q = qdisc_priv(sch); 1328 struct htb_sched *q = qdisc_priv(sch);
1324 struct htb_class *cl = (struct htb_class *)arg; 1329 struct htb_class *cl = (struct htb_class *)arg;
1330 unsigned int qlen;
1325 1331
1326 // TODO: why don't allow to delete subtree ? references ? does 1332 // TODO: why don't allow to delete subtree ? references ? does
1327 // tc subsys quarantee us that in htb_destroy it holds no class 1333 // tc subsys quarantee us that in htb_destroy it holds no class
@@ -1334,6 +1340,12 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
1334 /* delete from hash and active; remainder in destroy_class */ 1340 /* delete from hash and active; remainder in destroy_class */
1335 hlist_del_init(&cl->hlist); 1341 hlist_del_init(&cl->hlist);
1336 1342
1343 if (!cl->level) {
1344 qlen = cl->un.leaf.q->q.qlen;
1345 qdisc_reset(cl->un.leaf.q);
1346 qdisc_tree_decrease_qlen(cl->un.leaf.q, qlen);
1347 }
1348
1337 if (cl->prio_activity) 1349 if (cl->prio_activity)
1338 htb_deactivate(q, cl); 1350 htb_deactivate(q, cl);
1339 1351
@@ -1410,11 +1422,14 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
1410 /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL) 1422 /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
1411 so that can't be used inside of sch_tree_lock 1423 so that can't be used inside of sch_tree_lock
1412 -- thanks to Karlis Peisenieks */ 1424 -- thanks to Karlis Peisenieks */
1413 new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); 1425 new_q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
1414 sch_tree_lock(sch); 1426 sch_tree_lock(sch);
1415 if (parent && !parent->level) { 1427 if (parent && !parent->level) {
1428 unsigned int qlen = parent->un.leaf.q->q.qlen;
1429
1416 /* turn parent into inner node */ 1430 /* turn parent into inner node */
1417 sch->q.qlen -= parent->un.leaf.q->q.qlen; 1431 qdisc_reset(parent->un.leaf.q);
1432 qdisc_tree_decrease_qlen(parent->un.leaf.q, qlen);
1418 qdisc_destroy(parent->un.leaf.q); 1433 qdisc_destroy(parent->un.leaf.q);
1419 if (parent->prio_activity) 1434 if (parent->prio_activity)
1420 htb_deactivate(q, parent); 1435 htb_deactivate(q, parent);
@@ -1562,6 +1577,7 @@ static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1562static struct Qdisc_class_ops htb_class_ops = { 1577static struct Qdisc_class_ops htb_class_ops = {
1563 .graft = htb_graft, 1578 .graft = htb_graft,
1564 .leaf = htb_leaf, 1579 .leaf = htb_leaf,
1580 .qlen_notify = htb_qlen_notify,
1565 .get = htb_get, 1581 .get = htb_get,
1566 .put = htb_put, 1582 .put = htb_put,
1567 .change = htb_change_class, 1583 .change = htb_change_class,
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 0441876aa1e7..79542af9dab1 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -287,13 +287,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
287 psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, now); 287 psched_tdiff_t delay = PSCHED_TDIFF(cb->time_to_send, now);
288 288
289 if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) { 289 if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
290 qdisc_tree_decrease_qlen(q->qdisc, 1);
290 sch->qstats.drops++; 291 sch->qstats.drops++;
291
292 /* After this qlen is confused */
293 printk(KERN_ERR "netem: queue discpline %s could not requeue\n", 292 printk(KERN_ERR "netem: queue discpline %s could not requeue\n",
294 q->qdisc->ops->id); 293 q->qdisc->ops->id);
295
296 sch->q.qlen--;
297 } 294 }
298 295
299 mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay)); 296 mod_timer(&q->timer, jiffies + PSCHED_US2JIFFIE(delay));
@@ -574,7 +571,8 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt)
574 q->timer.function = netem_watchdog; 571 q->timer.function = netem_watchdog;
575 q->timer.data = (unsigned long) sch; 572 q->timer.data = (unsigned long) sch;
576 573
577 q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops); 574 q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops,
575 TC_H_MAKE(sch->handle, 1));
578 if (!q->qdisc) { 576 if (!q->qdisc) {
579 pr_debug("netem: qdisc create failed\n"); 577 pr_debug("netem: qdisc create failed\n");
580 return -ENOMEM; 578 return -ENOMEM;
@@ -661,8 +659,8 @@ static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
661 659
662 sch_tree_lock(sch); 660 sch_tree_lock(sch);
663 *old = xchg(&q->qdisc, new); 661 *old = xchg(&q->qdisc, new);
662 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
664 qdisc_reset(*old); 663 qdisc_reset(*old);
665 sch->q.qlen = 0;
666 sch_tree_unlock(sch); 664 sch_tree_unlock(sch);
667 665
668 return 0; 666 return 0;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index a5fa03c0c19b..2567b4c96c1e 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -222,21 +222,27 @@ static int prio_tune(struct Qdisc *sch, struct rtattr *opt)
222 222
223 for (i=q->bands; i<TCQ_PRIO_BANDS; i++) { 223 for (i=q->bands; i<TCQ_PRIO_BANDS; i++) {
224 struct Qdisc *child = xchg(&q->queues[i], &noop_qdisc); 224 struct Qdisc *child = xchg(&q->queues[i], &noop_qdisc);
225 if (child != &noop_qdisc) 225 if (child != &noop_qdisc) {
226 qdisc_tree_decrease_qlen(child, child->q.qlen);
226 qdisc_destroy(child); 227 qdisc_destroy(child);
228 }
227 } 229 }
228 sch_tree_unlock(sch); 230 sch_tree_unlock(sch);
229 231
230 for (i=0; i<q->bands; i++) { 232 for (i=0; i<q->bands; i++) {
231 if (q->queues[i] == &noop_qdisc) { 233 if (q->queues[i] == &noop_qdisc) {
232 struct Qdisc *child; 234 struct Qdisc *child;
233 child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); 235 child = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
236 TC_H_MAKE(sch->handle, i + 1));
234 if (child) { 237 if (child) {
235 sch_tree_lock(sch); 238 sch_tree_lock(sch);
236 child = xchg(&q->queues[i], child); 239 child = xchg(&q->queues[i], child);
237 240
238 if (child != &noop_qdisc) 241 if (child != &noop_qdisc) {
242 qdisc_tree_decrease_qlen(child,
243 child->q.qlen);
239 qdisc_destroy(child); 244 qdisc_destroy(child);
245 }
240 sch_tree_unlock(sch); 246 sch_tree_unlock(sch);
241 } 247 }
242 } 248 }
@@ -294,7 +300,7 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
294 sch_tree_lock(sch); 300 sch_tree_lock(sch);
295 *old = q->queues[band]; 301 *old = q->queues[band];
296 q->queues[band] = new; 302 q->queues[band] = new;
297 sch->q.qlen -= (*old)->q.qlen; 303 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
298 qdisc_reset(*old); 304 qdisc_reset(*old);
299 sch_tree_unlock(sch); 305 sch_tree_unlock(sch);
300 306
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index d65cadddea69..acddad08850f 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -175,12 +175,14 @@ static void red_destroy(struct Qdisc *sch)
175 qdisc_destroy(q->qdisc); 175 qdisc_destroy(q->qdisc);
176} 176}
177 177
178static struct Qdisc *red_create_dflt(struct net_device *dev, u32 limit) 178static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit)
179{ 179{
180 struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops); 180 struct Qdisc *q;
181 struct rtattr *rta; 181 struct rtattr *rta;
182 int ret; 182 int ret;
183 183
184 q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
185 TC_H_MAKE(sch->handle, 1));
184 if (q) { 186 if (q) {
185 rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), 187 rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)),
186 GFP_KERNEL); 188 GFP_KERNEL);
@@ -219,7 +221,7 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
219 ctl = RTA_DATA(tb[TCA_RED_PARMS-1]); 221 ctl = RTA_DATA(tb[TCA_RED_PARMS-1]);
220 222
221 if (ctl->limit > 0) { 223 if (ctl->limit > 0) {
222 child = red_create_dflt(sch->dev, ctl->limit); 224 child = red_create_dflt(sch, ctl->limit);
223 if (child == NULL) 225 if (child == NULL)
224 return -ENOMEM; 226 return -ENOMEM;
225 } 227 }
@@ -227,8 +229,10 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt)
227 sch_tree_lock(sch); 229 sch_tree_lock(sch);
228 q->flags = ctl->flags; 230 q->flags = ctl->flags;
229 q->limit = ctl->limit; 231 q->limit = ctl->limit;
230 if (child) 232 if (child) {
233 qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
231 qdisc_destroy(xchg(&q->qdisc, child)); 234 qdisc_destroy(xchg(&q->qdisc, child));
235 }
232 236
233 red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, 237 red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog,
234 ctl->Plog, ctl->Scell_log, 238 ctl->Plog, ctl->Scell_log,
@@ -306,8 +310,8 @@ static int red_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
306 310
307 sch_tree_lock(sch); 311 sch_tree_lock(sch);
308 *old = xchg(&q->qdisc, new); 312 *old = xchg(&q->qdisc, new);
313 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
309 qdisc_reset(*old); 314 qdisc_reset(*old);
310 sch->q.qlen = 0;
311 sch_tree_unlock(sch); 315 sch_tree_unlock(sch);
312 return 0; 316 return 0;
313} 317}
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index d0d6e595a78c..459cda258a5c 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -393,6 +393,7 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
393{ 393{
394 struct sfq_sched_data *q = qdisc_priv(sch); 394 struct sfq_sched_data *q = qdisc_priv(sch);
395 struct tc_sfq_qopt *ctl = RTA_DATA(opt); 395 struct tc_sfq_qopt *ctl = RTA_DATA(opt);
396 unsigned int qlen;
396 397
397 if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) 398 if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
398 return -EINVAL; 399 return -EINVAL;
@@ -403,8 +404,10 @@ static int sfq_change(struct Qdisc *sch, struct rtattr *opt)
403 if (ctl->limit) 404 if (ctl->limit)
404 q->limit = min_t(u32, ctl->limit, SFQ_DEPTH); 405 q->limit = min_t(u32, ctl->limit, SFQ_DEPTH);
405 406
407 qlen = sch->q.qlen;
406 while (sch->q.qlen >= q->limit-1) 408 while (sch->q.qlen >= q->limit-1)
407 sfq_drop(sch); 409 sfq_drop(sch);
410 qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
408 411
409 del_timer(&q->perturb_timer); 412 del_timer(&q->perturb_timer);
410 if (q->perturb_period) { 413 if (q->perturb_period) {
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index d9a5d298d755..ed9b6d938540 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -250,7 +250,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
250 250
251 if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) { 251 if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) {
252 /* When requeue fails skb is dropped */ 252 /* When requeue fails skb is dropped */
253 sch->q.qlen--; 253 qdisc_tree_decrease_qlen(q->qdisc, 1);
254 sch->qstats.drops++; 254 sch->qstats.drops++;
255 } 255 }
256 256
@@ -273,12 +273,14 @@ static void tbf_reset(struct Qdisc* sch)
273 del_timer(&q->wd_timer); 273 del_timer(&q->wd_timer);
274} 274}
275 275
276static struct Qdisc *tbf_create_dflt_qdisc(struct net_device *dev, u32 limit) 276static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
277{ 277{
278 struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops); 278 struct Qdisc *q;
279 struct rtattr *rta; 279 struct rtattr *rta;
280 int ret; 280 int ret;
281 281
282 q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops,
283 TC_H_MAKE(sch->handle, 1));
282 if (q) { 284 if (q) {
283 rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); 285 rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL);
284 if (rta) { 286 if (rta) {
@@ -341,13 +343,15 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt)
341 goto done; 343 goto done;
342 344
343 if (qopt->limit > 0) { 345 if (qopt->limit > 0) {
344 if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL) 346 if ((child = tbf_create_dflt_qdisc(sch, qopt->limit)) == NULL)
345 goto done; 347 goto done;
346 } 348 }
347 349
348 sch_tree_lock(sch); 350 sch_tree_lock(sch);
349 if (child) 351 if (child) {
352 qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
350 qdisc_destroy(xchg(&q->qdisc, child)); 353 qdisc_destroy(xchg(&q->qdisc, child));
354 }
351 q->limit = qopt->limit; 355 q->limit = qopt->limit;
352 q->mtu = qopt->mtu; 356 q->mtu = qopt->mtu;
353 q->max_size = max_size; 357 q->max_size = max_size;
@@ -449,8 +453,8 @@ static int tbf_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
449 453
450 sch_tree_lock(sch); 454 sch_tree_lock(sch);
451 *old = xchg(&q->qdisc, new); 455 *old = xchg(&q->qdisc, new);
456 qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
452 qdisc_reset(*old); 457 qdisc_reset(*old);
453 sch->q.qlen = 0;
454 sch_tree_unlock(sch); 458 sch_tree_unlock(sch);
455 459
456 return 0; 460 return 0;