diff options
author | David Howells <dhowells@redhat.com> | 2006-12-05 09:37:56 -0500 |
---|---|---|
committer | David Howells <dhowells@warthog.cambridge.redhat.com> | 2006-12-05 09:37:56 -0500 |
commit | 4c1ac1b49122b805adfa4efc620592f68dccf5db (patch) | |
tree | 87557f4bc2fd4fe65b7570489c2f610c45c0adcd /net/sched | |
parent | c4028958b6ecad064b1a6303a6a5906d4fe48d73 (diff) | |
parent | d916faace3efc0bf19fe9a615a1ab8fa1a24cd93 (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/Kconfig | 6 | ||||
-rw-r--r-- | net/sched/Makefile | 3 | ||||
-rw-r--r-- | net/sched/act_gact.c | 4 | ||||
-rw-r--r-- | net/sched/act_ipt.c | 6 | ||||
-rw-r--r-- | net/sched/act_police.c | 26 | ||||
-rw-r--r-- | net/sched/act_simple.c | 3 | ||||
-rw-r--r-- | net/sched/cls_api.c | 3 | ||||
-rw-r--r-- | net/sched/cls_fw.c | 6 | ||||
-rw-r--r-- | net/sched/cls_rsvp.h | 16 | ||||
-rw-r--r-- | net/sched/cls_u32.c | 2 | ||||
-rw-r--r-- | net/sched/em_meta.c | 13 | ||||
-rw-r--r-- | net/sched/em_nbyte.c | 4 | ||||
-rw-r--r-- | net/sched/ematch.c | 3 | ||||
-rw-r--r-- | net/sched/sch_api.c | 41 | ||||
-rw-r--r-- | net/sched/sch_atm.c | 5 | ||||
-rw-r--r-- | net/sched/sch_cbq.c | 10 | ||||
-rw-r--r-- | net/sched/sch_dsmark.c | 9 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 10 | ||||
-rw-r--r-- | net/sched/sch_hfsc.c | 27 | ||||
-rw-r--r-- | net/sched/sch_htb.c | 36 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 10 | ||||
-rw-r--r-- | net/sched/sch_prio.c | 14 | ||||
-rw-r--r-- | net/sched/sch_red.c | 14 | ||||
-rw-r--r-- | net/sched/sch_sfq.c | 3 | ||||
-rw-r--r-- | net/sched/sch_tbf.c | 16 |
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 | ||
7 | config NET_SCHED | 7 | config 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 | ||
44 | config NET_SCH_FIFO | ||
45 | bool | ||
46 | |||
43 | if NET_SCHED | 47 | if NET_SCHED |
44 | 48 | ||
45 | choice | 49 | choice |
@@ -320,7 +324,7 @@ config CLS_U32_PERF | |||
320 | 324 | ||
321 | config CLS_U32_MARK | 325 | config 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 | ||
5 | obj-y := sch_generic.o | 5 | obj-y := sch_generic.o |
6 | 6 | ||
7 | obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o sch_blackhole.o | 7 | obj-$(CONFIG_NET_SCHED) += sch_api.o sch_blackhole.o |
8 | obj-$(CONFIG_NET_CLS) += cls_api.o | 8 | obj-$(CONFIG_NET_CLS) += cls_api.o |
9 | obj-$(CONFIG_NET_CLS_ACT) += act_api.o | 9 | obj-$(CONFIG_NET_CLS_ACT) += act_api.o |
10 | obj-$(CONFIG_NET_ACT_POLICE) += act_police.o | 10 | obj-$(CONFIG_NET_ACT_POLICE) += act_police.o |
@@ -14,6 +14,7 @@ obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o | |||
14 | obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o | 14 | obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o |
15 | obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o | 15 | obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o |
16 | obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o | 16 | obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o |
17 | obj-$(CONFIG_NET_SCH_FIFO) += sch_fifo.o | ||
17 | obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o | 18 | obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o |
18 | obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o | 19 | obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o |
19 | obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o | 20 | obj-$(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 |
49 | static int gact_net_rand(struct tcf_gact *gact) | 49 | static 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 | ||
56 | static int gact_determ(struct tcf_gact *gact) | 56 | static 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 */ | ||
50 | struct 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 | ||
72 | static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata) | 72 | static 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 | |||
77 | struct rsvp_session | 77 | struct 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 | |||
89 | struct rsvp_filter | 89 | struct 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 | ||
103 | static __inline__ unsigned hash_dst(u32 *dst, u8 protocol, u8 tunnelid) | 103 | static __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 | ||
111 | static __inline__ unsigned hash_src(u32 *src) | 111 | static __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 | ||
211 | META_COLLECTOR(int_nfmark) | 211 | META_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 | ||
194 | struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle) | 194 | static 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 | ||
205 | struct 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 | |||
209 | static struct Qdisc *qdisc_leaf(struct Qdisc *p, u32 classid) | 215 | static 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 | ||
357 | void 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 | } | ||
376 | EXPORT_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; |
1118 | reclassify: | 1144 | reclassify: |
@@ -1277,7 +1303,6 @@ static int __init pktsched_init(void) | |||
1277 | 1303 | ||
1278 | subsys_initcall(pktsched_init); | 1304 | subsys_initcall(pktsched_init); |
1279 | 1305 | ||
1280 | EXPORT_SYMBOL(qdisc_lookup); | ||
1281 | EXPORT_SYMBOL(qdisc_get_rtab); | 1306 | EXPORT_SYMBOL(qdisc_get_rtab); |
1282 | EXPORT_SYMBOL(qdisc_put_rtab); | 1307 | EXPORT_SYMBOL(qdisc_put_rtab); |
1283 | EXPORT_SYMBOL(register_qdisc); | 1308 | EXPORT_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 | ||
453 | struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) | 453 | struct 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 | ||
609 | EXPORT_SYMBOL(__netdev_watchdog_up); | ||
610 | EXPORT_SYMBOL(netif_carrier_on); | 612 | EXPORT_SYMBOL(netif_carrier_on); |
611 | EXPORT_SYMBOL(netif_carrier_off); | 613 | EXPORT_SYMBOL(netif_carrier_off); |
612 | EXPORT_SYMBOL(noop_qdisc); | 614 | EXPORT_SYMBOL(noop_qdisc); |
613 | EXPORT_SYMBOL(noop_qdisc_ops); | ||
614 | EXPORT_SYMBOL(qdisc_create_dflt); | 615 | EXPORT_SYMBOL(qdisc_create_dflt); |
615 | EXPORT_SYMBOL(qdisc_alloc); | ||
616 | EXPORT_SYMBOL(qdisc_destroy); | 616 | EXPORT_SYMBOL(qdisc_destroy); |
617 | EXPORT_SYMBOL(qdisc_reset); | 617 | EXPORT_SYMBOL(qdisc_reset); |
618 | EXPORT_SYMBOL(qdisc_lock_tree); | 618 | EXPORT_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 | ||
967 | static void | 964 | static 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 | ||
1295 | static void | ||
1296 | hfsc_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 | |||
1297 | static unsigned long | 1306 | static unsigned long |
1298 | hfsc_get_class(struct Qdisc *sch, u32 classid) | 1307 | hfsc_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 | ||
1248 | static 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 | |||
1251 | static unsigned long htb_get(struct Qdisc *sch, u32 classid) | 1256 | static 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) | |||
1269 | static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) | 1274 | static 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) | |||
1562 | static struct Qdisc_class_ops htb_class_ops = { | 1577 | static 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 | ||
178 | static struct Qdisc *red_create_dflt(struct net_device *dev, u32 limit) | 178 | static 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 | ||
276 | static struct Qdisc *tbf_create_dflt_qdisc(struct net_device *dev, u32 limit) | 276 | static 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; |