aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/act_api.c11
-rw-r--r--net/sched/act_mirred.c12
-rw-r--r--net/sched/act_nat.c31
-rw-r--r--net/sched/act_pedit.c3
-rw-r--r--net/sched/act_police.c12
-rw-r--r--net/sched/act_simple.c4
-rw-r--r--net/sched/sch_atm.c98
-rw-r--r--net/sched/sch_generic.c25
-rw-r--r--net/sched/sch_htb.c2
9 files changed, 102 insertions, 96 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 972378f47f3c..23b25f89e7e0 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -26,6 +26,11 @@
26#include <net/act_api.h> 26#include <net/act_api.h>
27#include <net/netlink.h> 27#include <net/netlink.h>
28 28
29static void tcf_common_free_rcu(struct rcu_head *head)
30{
31 kfree(container_of(head, struct tcf_common, tcfc_rcu));
32}
33
29void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) 34void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
30{ 35{
31 unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); 36 unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask);
@@ -38,7 +43,11 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
38 write_unlock_bh(hinfo->lock); 43 write_unlock_bh(hinfo->lock);
39 gen_kill_estimator(&p->tcfc_bstats, 44 gen_kill_estimator(&p->tcfc_bstats,
40 &p->tcfc_rate_est); 45 &p->tcfc_rate_est);
41 kfree(p); 46 /*
47 * gen_estimator est_timer() might access p->tcfc_lock
48 * or bstats, wait a RCU grace period before freeing p
49 */
50 call_rcu(&p->tcfc_rcu, tcf_common_free_rcu);
42 return; 51 return;
43 } 52 }
44 } 53 }
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 1980b71c283f..11f195af2da0 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -165,6 +165,8 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
165 165
166 spin_lock(&m->tcf_lock); 166 spin_lock(&m->tcf_lock);
167 m->tcf_tm.lastuse = jiffies; 167 m->tcf_tm.lastuse = jiffies;
168 m->tcf_bstats.bytes += qdisc_pkt_len(skb);
169 m->tcf_bstats.packets++;
168 170
169 dev = m->tcfm_dev; 171 dev = m->tcfm_dev;
170 if (!dev) { 172 if (!dev) {
@@ -179,13 +181,11 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
179 goto out; 181 goto out;
180 } 182 }
181 183
182 skb2 = skb_act_clone(skb, GFP_ATOMIC); 184 at = G_TC_AT(skb->tc_verd);
185 skb2 = skb_act_clone(skb, GFP_ATOMIC, m->tcf_action);
183 if (skb2 == NULL) 186 if (skb2 == NULL)
184 goto out; 187 goto out;
185 188
186 m->tcf_bstats.bytes += qdisc_pkt_len(skb2);
187 m->tcf_bstats.packets++;
188 at = G_TC_AT(skb->tc_verd);
189 if (!(at & AT_EGRESS)) { 189 if (!(at & AT_EGRESS)) {
190 if (m->tcfm_ok_push) 190 if (m->tcfm_ok_push)
191 skb_push(skb2, skb2->dev->hard_header_len); 191 skb_push(skb2, skb2->dev->hard_header_len);
@@ -195,16 +195,14 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
195 if (m->tcfm_eaction != TCA_EGRESS_MIRROR) 195 if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
196 skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at); 196 skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at);
197 197
198 skb2->dev = dev;
199 skb2->skb_iif = skb->dev->ifindex; 198 skb2->skb_iif = skb->dev->ifindex;
199 skb2->dev = dev;
200 dev_queue_xmit(skb2); 200 dev_queue_xmit(skb2);
201 err = 0; 201 err = 0;
202 202
203out: 203out:
204 if (err) { 204 if (err) {
205 m->tcf_qstats.overlimits++; 205 m->tcf_qstats.overlimits++;
206 m->tcf_bstats.bytes += qdisc_pkt_len(skb);
207 m->tcf_bstats.packets++;
208 /* should we be asking for packet to be dropped? 206 /* should we be asking for packet to be dropped?
209 * may make sense for redirect case only 207 * may make sense for redirect case only
210 */ 208 */
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 724553e8ed7b..24e614c495f2 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -268,40 +268,29 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
268{ 268{
269 unsigned char *b = skb_tail_pointer(skb); 269 unsigned char *b = skb_tail_pointer(skb);
270 struct tcf_nat *p = a->priv; 270 struct tcf_nat *p = a->priv;
271 struct tc_nat *opt; 271 struct tc_nat opt;
272 struct tcf_t t; 272 struct tcf_t t;
273 int s;
274 273
275 s = sizeof(*opt); 274 opt.old_addr = p->old_addr;
275 opt.new_addr = p->new_addr;
276 opt.mask = p->mask;
277 opt.flags = p->flags;
276 278
277 /* netlink spinlocks held above us - must use ATOMIC */ 279 opt.index = p->tcf_index;
278 opt = kzalloc(s, GFP_ATOMIC); 280 opt.action = p->tcf_action;
279 if (unlikely(!opt)) 281 opt.refcnt = p->tcf_refcnt - ref;
280 return -ENOBUFS; 282 opt.bindcnt = p->tcf_bindcnt - bind;
281 283
282 opt->old_addr = p->old_addr; 284 NLA_PUT(skb, TCA_NAT_PARMS, sizeof(opt), &opt);
283 opt->new_addr = p->new_addr;
284 opt->mask = p->mask;
285 opt->flags = p->flags;
286
287 opt->index = p->tcf_index;
288 opt->action = p->tcf_action;
289 opt->refcnt = p->tcf_refcnt - ref;
290 opt->bindcnt = p->tcf_bindcnt - bind;
291
292 NLA_PUT(skb, TCA_NAT_PARMS, s, opt);
293 t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); 285 t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install);
294 t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); 286 t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse);
295 t.expires = jiffies_to_clock_t(p->tcf_tm.expires); 287 t.expires = jiffies_to_clock_t(p->tcf_tm.expires);
296 NLA_PUT(skb, TCA_NAT_TM, sizeof(t), &t); 288 NLA_PUT(skb, TCA_NAT_TM, sizeof(t), &t);
297 289
298 kfree(opt);
299
300 return skb->len; 290 return skb->len;
301 291
302nla_put_failure: 292nla_put_failure:
303 nlmsg_trim(skb, b); 293 nlmsg_trim(skb, b);
304 kfree(opt);
305 return -1; 294 return -1;
306} 295}
307 296
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 50e3d945e1f4..a0593c9640db 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -127,8 +127,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
127 int i, munged = 0; 127 int i, munged = 0;
128 unsigned int off; 128 unsigned int off;
129 129
130 if (!(skb->tc_verd & TC_OK2MUNGE)) { 130 if (skb_cloned(skb)) {
131 /* should we set skb->cloned? */
132 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { 131 if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
133 return p->tcf_action; 132 return p->tcf_action;
134 } 133 }
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 654f73dff7c1..537a48732e9e 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -97,6 +97,11 @@ nla_put_failure:
97 goto done; 97 goto done;
98} 98}
99 99
100static void tcf_police_free_rcu(struct rcu_head *head)
101{
102 kfree(container_of(head, struct tcf_police, tcf_rcu));
103}
104
100static void tcf_police_destroy(struct tcf_police *p) 105static void tcf_police_destroy(struct tcf_police *p)
101{ 106{
102 unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); 107 unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
@@ -113,7 +118,11 @@ static void tcf_police_destroy(struct tcf_police *p)
113 qdisc_put_rtab(p->tcfp_R_tab); 118 qdisc_put_rtab(p->tcfp_R_tab);
114 if (p->tcfp_P_tab) 119 if (p->tcfp_P_tab)
115 qdisc_put_rtab(p->tcfp_P_tab); 120 qdisc_put_rtab(p->tcfp_P_tab);
116 kfree(p); 121 /*
122 * gen_estimator est_timer() might access p->tcf_lock
123 * or bstats, wait a RCU grace period before freeing p
124 */
125 call_rcu(&p->tcf_rcu, tcf_police_free_rcu);
117 return; 126 return;
118 } 127 }
119 } 128 }
@@ -397,6 +406,7 @@ static void __exit
397police_cleanup_module(void) 406police_cleanup_module(void)
398{ 407{
399 tcf_unregister_action(&act_police_ops); 408 tcf_unregister_action(&act_police_ops);
409 rcu_barrier(); /* Wait for completion of call_rcu()'s (tcf_police_free_rcu) */
400} 410}
401 411
402module_init(police_init_module); 412module_init(police_init_module);
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 1b4bc691d7d1..4a1d640b0cf1 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -73,10 +73,10 @@ static int tcf_simp_release(struct tcf_defact *d, int bind)
73 73
74static int alloc_defdata(struct tcf_defact *d, char *defdata) 74static int alloc_defdata(struct tcf_defact *d, char *defdata)
75{ 75{
76 d->tcfd_defdata = kstrndup(defdata, SIMP_MAX_DATA, GFP_KERNEL); 76 d->tcfd_defdata = kzalloc(SIMP_MAX_DATA, GFP_KERNEL);
77 if (unlikely(!d->tcfd_defdata)) 77 if (unlikely(!d->tcfd_defdata))
78 return -ENOMEM; 78 return -ENOMEM;
79 79 strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
80 return 0; 80 return 0;
81} 81}
82 82
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index fcbb86a486a2..e114f23d5eae 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -52,7 +52,7 @@ struct atm_flow_data {
52 int ref; /* reference count */ 52 int ref; /* reference count */
53 struct gnet_stats_basic_packed bstats; 53 struct gnet_stats_basic_packed bstats;
54 struct gnet_stats_queue qstats; 54 struct gnet_stats_queue qstats;
55 struct atm_flow_data *next; 55 struct list_head list;
56 struct atm_flow_data *excess; /* flow for excess traffic; 56 struct atm_flow_data *excess; /* flow for excess traffic;
57 NULL to set CLP instead */ 57 NULL to set CLP instead */
58 int hdr_len; 58 int hdr_len;
@@ -61,34 +61,23 @@ struct atm_flow_data {
61 61
62struct atm_qdisc_data { 62struct atm_qdisc_data {
63 struct atm_flow_data link; /* unclassified skbs go here */ 63 struct atm_flow_data link; /* unclassified skbs go here */
64 struct atm_flow_data *flows; /* NB: "link" is also on this 64 struct list_head flows; /* NB: "link" is also on this
65 list */ 65 list */
66 struct tasklet_struct task; /* dequeue tasklet */ 66 struct tasklet_struct task; /* dequeue tasklet */
67}; 67};
68 68
69/* ------------------------- Class/flow operations ------------------------- */ 69/* ------------------------- Class/flow operations ------------------------- */
70 70
71static int find_flow(struct atm_qdisc_data *qdisc, struct atm_flow_data *flow)
72{
73 struct atm_flow_data *walk;
74
75 pr_debug("find_flow(qdisc %p,flow %p)\n", qdisc, flow);
76 for (walk = qdisc->flows; walk; walk = walk->next)
77 if (walk == flow)
78 return 1;
79 pr_debug("find_flow: not found\n");
80 return 0;
81}
82
83static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid) 71static inline struct atm_flow_data *lookup_flow(struct Qdisc *sch, u32 classid)
84{ 72{
85 struct atm_qdisc_data *p = qdisc_priv(sch); 73 struct atm_qdisc_data *p = qdisc_priv(sch);
86 struct atm_flow_data *flow; 74 struct atm_flow_data *flow;
87 75
88 for (flow = p->flows; flow; flow = flow->next) 76 list_for_each_entry(flow, &p->flows, list) {
89 if (flow->classid == classid) 77 if (flow->classid == classid)
90 break; 78 return flow;
91 return flow; 79 }
80 return NULL;
92} 81}
93 82
94static int atm_tc_graft(struct Qdisc *sch, unsigned long arg, 83static int atm_tc_graft(struct Qdisc *sch, unsigned long arg,
@@ -99,7 +88,7 @@ static int atm_tc_graft(struct Qdisc *sch, unsigned long arg,
99 88
100 pr_debug("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n", 89 pr_debug("atm_tc_graft(sch %p,[qdisc %p],flow %p,new %p,old %p)\n",
101 sch, p, flow, new, old); 90 sch, p, flow, new, old);
102 if (!find_flow(p, flow)) 91 if (list_empty(&flow->list))
103 return -EINVAL; 92 return -EINVAL;
104 if (!new) 93 if (!new)
105 new = &noop_qdisc; 94 new = &noop_qdisc;
@@ -146,20 +135,12 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl)
146{ 135{
147 struct atm_qdisc_data *p = qdisc_priv(sch); 136 struct atm_qdisc_data *p = qdisc_priv(sch);
148 struct atm_flow_data *flow = (struct atm_flow_data *)cl; 137 struct atm_flow_data *flow = (struct atm_flow_data *)cl;
149 struct atm_flow_data **prev;
150 138
151 pr_debug("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow); 139 pr_debug("atm_tc_put(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
152 if (--flow->ref) 140 if (--flow->ref)
153 return; 141 return;
154 pr_debug("atm_tc_put: destroying\n"); 142 pr_debug("atm_tc_put: destroying\n");
155 for (prev = &p->flows; *prev; prev = &(*prev)->next) 143 list_del_init(&flow->list);
156 if (*prev == flow)
157 break;
158 if (!*prev) {
159 printk(KERN_CRIT "atm_tc_put: class %p not found\n", flow);
160 return;
161 }
162 *prev = flow->next;
163 pr_debug("atm_tc_put: qdisc %p\n", flow->q); 144 pr_debug("atm_tc_put: qdisc %p\n", flow->q);
164 qdisc_destroy(flow->q); 145 qdisc_destroy(flow->q);
165 tcf_destroy_chain(&flow->filter_list); 146 tcf_destroy_chain(&flow->filter_list);
@@ -274,7 +255,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
274 error = -EINVAL; 255 error = -EINVAL;
275 goto err_out; 256 goto err_out;
276 } 257 }
277 if (find_flow(p, flow)) { 258 if (!list_empty(&flow->list)) {
278 error = -EEXIST; 259 error = -EEXIST;
279 goto err_out; 260 goto err_out;
280 } 261 }
@@ -313,8 +294,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
313 flow->classid = classid; 294 flow->classid = classid;
314 flow->ref = 1; 295 flow->ref = 1;
315 flow->excess = excess; 296 flow->excess = excess;
316 flow->next = p->link.next; 297 list_add(&flow->list, &p->link.list);
317 p->link.next = flow;
318 flow->hdr_len = hdr_len; 298 flow->hdr_len = hdr_len;
319 if (hdr) 299 if (hdr)
320 memcpy(flow->hdr, hdr, hdr_len); 300 memcpy(flow->hdr, hdr, hdr_len);
@@ -335,7 +315,7 @@ static int atm_tc_delete(struct Qdisc *sch, unsigned long arg)
335 struct atm_flow_data *flow = (struct atm_flow_data *)arg; 315 struct atm_flow_data *flow = (struct atm_flow_data *)arg;
336 316
337 pr_debug("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow); 317 pr_debug("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n", sch, p, flow);
338 if (!find_flow(qdisc_priv(sch), flow)) 318 if (list_empty(&flow->list))
339 return -EINVAL; 319 return -EINVAL;
340 if (flow->filter_list || flow == &p->link) 320 if (flow->filter_list || flow == &p->link)
341 return -EBUSY; 321 return -EBUSY;
@@ -361,12 +341,12 @@ static void atm_tc_walk(struct Qdisc *sch, struct qdisc_walker *walker)
361 pr_debug("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker); 341 pr_debug("atm_tc_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
362 if (walker->stop) 342 if (walker->stop)
363 return; 343 return;
364 for (flow = p->flows; flow; flow = flow->next) { 344 list_for_each_entry(flow, &p->flows, list) {
365 if (walker->count >= walker->skip) 345 if (walker->count >= walker->skip &&
366 if (walker->fn(sch, (unsigned long)flow, walker) < 0) { 346 walker->fn(sch, (unsigned long)flow, walker) < 0) {
367 walker->stop = 1; 347 walker->stop = 1;
368 break; 348 break;
369 } 349 }
370 walker->count++; 350 walker->count++;
371 } 351 }
372} 352}
@@ -385,16 +365,17 @@ static struct tcf_proto **atm_tc_find_tcf(struct Qdisc *sch, unsigned long cl)
385static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch) 365static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
386{ 366{
387 struct atm_qdisc_data *p = qdisc_priv(sch); 367 struct atm_qdisc_data *p = qdisc_priv(sch);
388 struct atm_flow_data *flow = NULL; /* @@@ */ 368 struct atm_flow_data *flow;
389 struct tcf_result res; 369 struct tcf_result res;
390 int result; 370 int result;
391 int ret = NET_XMIT_POLICED; 371 int ret = NET_XMIT_POLICED;
392 372
393 pr_debug("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p); 373 pr_debug("atm_tc_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
394 result = TC_POLICE_OK; /* be nice to gcc */ 374 result = TC_POLICE_OK; /* be nice to gcc */
375 flow = NULL;
395 if (TC_H_MAJ(skb->priority) != sch->handle || 376 if (TC_H_MAJ(skb->priority) != sch->handle ||
396 !(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority))) 377 !(flow = (struct atm_flow_data *)atm_tc_get(sch, skb->priority))) {
397 for (flow = p->flows; flow; flow = flow->next) 378 list_for_each_entry(flow, &p->flows, list) {
398 if (flow->filter_list) { 379 if (flow->filter_list) {
399 result = tc_classify_compat(skb, 380 result = tc_classify_compat(skb,
400 flow->filter_list, 381 flow->filter_list,
@@ -404,8 +385,13 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
404 flow = (struct atm_flow_data *)res.class; 385 flow = (struct atm_flow_data *)res.class;
405 if (!flow) 386 if (!flow)
406 flow = lookup_flow(sch, res.classid); 387 flow = lookup_flow(sch, res.classid);
407 break; 388 goto done;
408 } 389 }
390 }
391 flow = NULL;
392 done:
393 ;
394 }
409 if (!flow) 395 if (!flow)
410 flow = &p->link; 396 flow = &p->link;
411 else { 397 else {
@@ -477,7 +463,9 @@ static void sch_atm_dequeue(unsigned long data)
477 struct sk_buff *skb; 463 struct sk_buff *skb;
478 464
479 pr_debug("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p); 465 pr_debug("sch_atm_dequeue(sch %p,[qdisc %p])\n", sch, p);
480 for (flow = p->link.next; flow; flow = flow->next) 466 list_for_each_entry(flow, &p->flows, list) {
467 if (flow == &p->link)
468 continue;
481 /* 469 /*
482 * If traffic is properly shaped, this won't generate nasty 470 * If traffic is properly shaped, this won't generate nasty
483 * little bursts. Otherwise, it may ... (but that's okay) 471 * little bursts. Otherwise, it may ... (but that's okay)
@@ -512,6 +500,7 @@ static void sch_atm_dequeue(unsigned long data)
512 /* atm.atm_options are already set by atm_tc_enqueue */ 500 /* atm.atm_options are already set by atm_tc_enqueue */
513 flow->vcc->send(flow->vcc, skb); 501 flow->vcc->send(flow->vcc, skb);
514 } 502 }
503 }
515} 504}
516 505
517static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) 506static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch)
@@ -543,9 +532,10 @@ static unsigned int atm_tc_drop(struct Qdisc *sch)
543 unsigned int len; 532 unsigned int len;
544 533
545 pr_debug("atm_tc_drop(sch %p,[qdisc %p])\n", sch, p); 534 pr_debug("atm_tc_drop(sch %p,[qdisc %p])\n", sch, p);
546 for (flow = p->flows; flow; flow = flow->next) 535 list_for_each_entry(flow, &p->flows, list) {
547 if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q))) 536 if (flow->q->ops->drop && (len = flow->q->ops->drop(flow->q)))
548 return len; 537 return len;
538 }
549 return 0; 539 return 0;
550} 540}
551 541
@@ -554,7 +544,9 @@ static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt)
554 struct atm_qdisc_data *p = qdisc_priv(sch); 544 struct atm_qdisc_data *p = qdisc_priv(sch);
555 545
556 pr_debug("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt); 546 pr_debug("atm_tc_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
557 p->flows = &p->link; 547 INIT_LIST_HEAD(&p->flows);
548 INIT_LIST_HEAD(&p->link.list);
549 list_add(&p->link.list, &p->flows);
558 p->link.q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue, 550 p->link.q = qdisc_create_dflt(qdisc_dev(sch), sch->dev_queue,
559 &pfifo_qdisc_ops, sch->handle); 551 &pfifo_qdisc_ops, sch->handle);
560 if (!p->link.q) 552 if (!p->link.q)
@@ -565,7 +557,6 @@ static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt)
565 p->link.sock = NULL; 557 p->link.sock = NULL;
566 p->link.classid = sch->handle; 558 p->link.classid = sch->handle;
567 p->link.ref = 1; 559 p->link.ref = 1;
568 p->link.next = NULL;
569 tasklet_init(&p->task, sch_atm_dequeue, (unsigned long)sch); 560 tasklet_init(&p->task, sch_atm_dequeue, (unsigned long)sch);
570 return 0; 561 return 0;
571} 562}
@@ -576,7 +567,7 @@ static void atm_tc_reset(struct Qdisc *sch)
576 struct atm_flow_data *flow; 567 struct atm_flow_data *flow;
577 568
578 pr_debug("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p); 569 pr_debug("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p);
579 for (flow = p->flows; flow; flow = flow->next) 570 list_for_each_entry(flow, &p->flows, list)
580 qdisc_reset(flow->q); 571 qdisc_reset(flow->q);
581 sch->q.qlen = 0; 572 sch->q.qlen = 0;
582} 573}
@@ -584,24 +575,17 @@ static void atm_tc_reset(struct Qdisc *sch)
584static void atm_tc_destroy(struct Qdisc *sch) 575static void atm_tc_destroy(struct Qdisc *sch)
585{ 576{
586 struct atm_qdisc_data *p = qdisc_priv(sch); 577 struct atm_qdisc_data *p = qdisc_priv(sch);
587 struct atm_flow_data *flow; 578 struct atm_flow_data *flow, *tmp;
588 579
589 pr_debug("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p); 580 pr_debug("atm_tc_destroy(sch %p,[qdisc %p])\n", sch, p);
590 for (flow = p->flows; flow; flow = flow->next) 581 list_for_each_entry(flow, &p->flows, list)
591 tcf_destroy_chain(&flow->filter_list); 582 tcf_destroy_chain(&flow->filter_list);
592 583
593 /* races ? */ 584 list_for_each_entry_safe(flow, tmp, &p->flows, list) {
594 while ((flow = p->flows)) {
595 if (flow->ref > 1) 585 if (flow->ref > 1)
596 printk(KERN_ERR "atm_destroy: %p->ref = %d\n", flow, 586 printk(KERN_ERR "atm_destroy: %p->ref = %d\n", flow,
597 flow->ref); 587 flow->ref);
598 atm_tc_put(sch, (unsigned long)flow); 588 atm_tc_put(sch, (unsigned long)flow);
599 if (p->flows == flow) {
600 printk(KERN_ERR "atm_destroy: putting flow %p didn't "
601 "kill it\n", flow);
602 p->flows = flow->next; /* brute force */
603 break;
604 }
605 } 589 }
606 tasklet_kill(&p->task); 590 tasklet_kill(&p->task);
607} 591}
@@ -615,7 +599,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
615 599
616 pr_debug("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n", 600 pr_debug("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",
617 sch, p, flow, skb, tcm); 601 sch, p, flow, skb, tcm);
618 if (!find_flow(p, flow)) 602 if (list_empty(&flow->list))
619 return -EINVAL; 603 return -EINVAL;
620 tcm->tcm_handle = flow->classid; 604 tcm->tcm_handle = flow->classid;
621 tcm->tcm_info = flow->q->handle; 605 tcm->tcm_info = flow->q->handle;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index a63029ef3edd..2aeb3a4386a1 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -96,7 +96,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
96 * Another cpu is holding lock, requeue & delay xmits for 96 * Another cpu is holding lock, requeue & delay xmits for
97 * some time. 97 * some time.
98 */ 98 */
99 __get_cpu_var(softnet_data).cpu_collision++; 99 __this_cpu_inc(softnet_data.cpu_collision);
100 ret = dev_requeue_skb(skb, q); 100 ret = dev_requeue_skb(skb, q);
101 } 101 }
102 102
@@ -205,7 +205,7 @@ void __qdisc_run(struct Qdisc *q)
205 } 205 }
206 } 206 }
207 207
208 clear_bit(__QDISC_STATE_RUNNING, &q->state); 208 qdisc_run_end(q);
209} 209}
210 210
211unsigned long dev_trans_start(struct net_device *dev) 211unsigned long dev_trans_start(struct net_device *dev)
@@ -327,6 +327,24 @@ void netif_carrier_off(struct net_device *dev)
327} 327}
328EXPORT_SYMBOL(netif_carrier_off); 328EXPORT_SYMBOL(netif_carrier_off);
329 329
330/**
331 * netif_notify_peers - notify network peers about existence of @dev
332 * @dev: network device
333 *
334 * Generate traffic such that interested network peers are aware of
335 * @dev, such as by generating a gratuitous ARP. This may be used when
336 * a device wants to inform the rest of the network about some sort of
337 * reconfiguration such as a failover event or virtual machine
338 * migration.
339 */
340void netif_notify_peers(struct net_device *dev)
341{
342 rtnl_lock();
343 call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev);
344 rtnl_unlock();
345}
346EXPORT_SYMBOL(netif_notify_peers);
347
330/* "NOOP" scheduler: the best scheduler, recommended for all interfaces 348/* "NOOP" scheduler: the best scheduler, recommended for all interfaces
331 under all circumstances. It is difficult to invent anything faster or 349 under all circumstances. It is difficult to invent anything faster or
332 cheaper. 350 cheaper.
@@ -543,6 +561,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
543 561
544 INIT_LIST_HEAD(&sch->list); 562 INIT_LIST_HEAD(&sch->list);
545 skb_queue_head_init(&sch->q); 563 skb_queue_head_init(&sch->q);
564 spin_lock_init(&sch->busylock);
546 sch->ops = ops; 565 sch->ops = ops;
547 sch->enqueue = ops->enqueue; 566 sch->enqueue = ops->enqueue;
548 sch->dequeue = ops->dequeue; 567 sch->dequeue = ops->dequeue;
@@ -779,7 +798,7 @@ static bool some_qdisc_is_busy(struct net_device *dev)
779 798
780 spin_lock_bh(root_lock); 799 spin_lock_bh(root_lock);
781 800
782 val = (test_bit(__QDISC_STATE_RUNNING, &q->state) || 801 val = (qdisc_is_running(q) ||
783 test_bit(__QDISC_STATE_SCHED, &q->state)); 802 test_bit(__QDISC_STATE_SCHED, &q->state));
784 803
785 spin_unlock_bh(root_lock); 804 spin_unlock_bh(root_lock);
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 0b52b8de562c..4be8d04b262d 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1550,7 +1550,6 @@ static const struct Qdisc_class_ops htb_class_ops = {
1550}; 1550};
1551 1551
1552static struct Qdisc_ops htb_qdisc_ops __read_mostly = { 1552static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
1553 .next = NULL,
1554 .cl_ops = &htb_class_ops, 1553 .cl_ops = &htb_class_ops,
1555 .id = "htb", 1554 .id = "htb",
1556 .priv_size = sizeof(struct htb_sched), 1555 .priv_size = sizeof(struct htb_sched),
@@ -1561,7 +1560,6 @@ static struct Qdisc_ops htb_qdisc_ops __read_mostly = {
1561 .init = htb_init, 1560 .init = htb_init,
1562 .reset = htb_reset, 1561 .reset = htb_reset,
1563 .destroy = htb_destroy, 1562 .destroy = htb_destroy,
1564 .change = NULL /* htb_change */,
1565 .dump = htb_dump, 1563 .dump = htb_dump,
1566 .owner = THIS_MODULE, 1564 .owner = THIS_MODULE,
1567}; 1565};