aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-08-01 02:52:20 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-01 02:52:20 -0400
commit5510b3c2a173921374ec847848fb20b98e1c698a (patch)
treec9e185281ef17280ce0dc30be7923124874736b0 /net/sched
parent17f901e8915cb922c2ca710835ef34f166f53ee9 (diff)
parent7c764cec3703583247c4ab837c652975a3d41f4b (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: arch/s390/net/bpf_jit_comp.c drivers/net/ethernet/ti/netcp_ethss.c net/bridge/br_multicast.c net/ipv4/ip_fragment.c All four conflicts were cases of simple overlapping changes. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/act_api.c11
-rw-r--r--net/sched/act_bpf.c53
-rw-r--r--net/sched/act_pedit.c5
-rw-r--r--net/sched/sch_choke.c13
-rw-r--r--net/sched/sch_plug.c1
5 files changed, 57 insertions, 26 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 074a32f466f8..b087087ccfa9 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -54,7 +54,7 @@ void tcf_hash_destroy(struct tc_action *a)
54} 54}
55EXPORT_SYMBOL(tcf_hash_destroy); 55EXPORT_SYMBOL(tcf_hash_destroy);
56 56
57int tcf_hash_release(struct tc_action *a, int bind) 57int __tcf_hash_release(struct tc_action *a, bool bind, bool strict)
58{ 58{
59 struct tcf_common *p = a->priv; 59 struct tcf_common *p = a->priv;
60 int ret = 0; 60 int ret = 0;
@@ -62,7 +62,7 @@ int tcf_hash_release(struct tc_action *a, int bind)
62 if (p) { 62 if (p) {
63 if (bind) 63 if (bind)
64 p->tcfc_bindcnt--; 64 p->tcfc_bindcnt--;
65 else if (p->tcfc_bindcnt > 0) 65 else if (strict && p->tcfc_bindcnt > 0)
66 return -EPERM; 66 return -EPERM;
67 67
68 p->tcfc_refcnt--; 68 p->tcfc_refcnt--;
@@ -73,9 +73,10 @@ int tcf_hash_release(struct tc_action *a, int bind)
73 ret = 1; 73 ret = 1;
74 } 74 }
75 } 75 }
76
76 return ret; 77 return ret;
77} 78}
78EXPORT_SYMBOL(tcf_hash_release); 79EXPORT_SYMBOL(__tcf_hash_release);
79 80
80static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, 81static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
81 struct tc_action *a) 82 struct tc_action *a)
@@ -145,7 +146,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a)
145 head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; 146 head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
146 hlist_for_each_entry_safe(p, n, head, tcfc_head) { 147 hlist_for_each_entry_safe(p, n, head, tcfc_head) {
147 a->priv = p; 148 a->priv = p;
148 ret = tcf_hash_release(a, 0); 149 ret = __tcf_hash_release(a, false, true);
149 if (ret == ACT_P_DELETED) { 150 if (ret == ACT_P_DELETED) {
150 module_put(a->ops->owner); 151 module_put(a->ops->owner);
151 n_i++; 152 n_i++;
@@ -432,7 +433,7 @@ int tcf_action_destroy(struct list_head *actions, int bind)
432 int ret = 0; 433 int ret = 0;
433 434
434 list_for_each_entry_safe(a, tmp, actions, list) { 435 list_for_each_entry_safe(a, tmp, actions, list) {
435 ret = tcf_hash_release(a, bind); 436 ret = __tcf_hash_release(a, bind, true);
436 if (ret == ACT_P_DELETED) 437 if (ret == ACT_P_DELETED)
437 module_put(a->ops->owner); 438 module_put(a->ops->owner);
438 else if (ret < 0) 439 else if (ret < 0)
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index e9e923a8c747..aaae8e83bf18 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -27,9 +27,10 @@
27struct tcf_bpf_cfg { 27struct tcf_bpf_cfg {
28 struct bpf_prog *filter; 28 struct bpf_prog *filter;
29 struct sock_filter *bpf_ops; 29 struct sock_filter *bpf_ops;
30 char *bpf_name; 30 const char *bpf_name;
31 u32 bpf_fd; 31 u32 bpf_fd;
32 u16 bpf_num_ops; 32 u16 bpf_num_ops;
33 bool is_ebpf;
33}; 34};
34 35
35static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, 36static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act,
@@ -207,6 +208,7 @@ static int tcf_bpf_init_from_ops(struct nlattr **tb, struct tcf_bpf_cfg *cfg)
207 cfg->bpf_ops = bpf_ops; 208 cfg->bpf_ops = bpf_ops;
208 cfg->bpf_num_ops = bpf_num_ops; 209 cfg->bpf_num_ops = bpf_num_ops;
209 cfg->filter = fp; 210 cfg->filter = fp;
211 cfg->is_ebpf = false;
210 212
211 return 0; 213 return 0;
212} 214}
@@ -241,18 +243,40 @@ static int tcf_bpf_init_from_efd(struct nlattr **tb, struct tcf_bpf_cfg *cfg)
241 cfg->bpf_fd = bpf_fd; 243 cfg->bpf_fd = bpf_fd;
242 cfg->bpf_name = name; 244 cfg->bpf_name = name;
243 cfg->filter = fp; 245 cfg->filter = fp;
246 cfg->is_ebpf = true;
244 247
245 return 0; 248 return 0;
246} 249}
247 250
251static void tcf_bpf_cfg_cleanup(const struct tcf_bpf_cfg *cfg)
252{
253 if (cfg->is_ebpf)
254 bpf_prog_put(cfg->filter);
255 else
256 bpf_prog_destroy(cfg->filter);
257
258 kfree(cfg->bpf_ops);
259 kfree(cfg->bpf_name);
260}
261
262static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
263 struct tcf_bpf_cfg *cfg)
264{
265 cfg->is_ebpf = tcf_bpf_is_ebpf(prog);
266 cfg->filter = prog->filter;
267
268 cfg->bpf_ops = prog->bpf_ops;
269 cfg->bpf_name = prog->bpf_name;
270}
271
248static int tcf_bpf_init(struct net *net, struct nlattr *nla, 272static int tcf_bpf_init(struct net *net, struct nlattr *nla,
249 struct nlattr *est, struct tc_action *act, 273 struct nlattr *est, struct tc_action *act,
250 int replace, int bind) 274 int replace, int bind)
251{ 275{
252 struct nlattr *tb[TCA_ACT_BPF_MAX + 1]; 276 struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
277 struct tcf_bpf_cfg cfg, old;
253 struct tc_act_bpf *parm; 278 struct tc_act_bpf *parm;
254 struct tcf_bpf *prog; 279 struct tcf_bpf *prog;
255 struct tcf_bpf_cfg cfg;
256 bool is_bpf, is_ebpf; 280 bool is_bpf, is_ebpf;
257 int ret; 281 int ret;
258 282
@@ -301,6 +325,9 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
301 prog = to_bpf(act); 325 prog = to_bpf(act);
302 spin_lock_bh(&prog->tcf_lock); 326 spin_lock_bh(&prog->tcf_lock);
303 327
328 if (ret != ACT_P_CREATED)
329 tcf_bpf_prog_fill_cfg(prog, &old);
330
304 prog->bpf_ops = cfg.bpf_ops; 331 prog->bpf_ops = cfg.bpf_ops;
305 prog->bpf_name = cfg.bpf_name; 332 prog->bpf_name = cfg.bpf_name;
306 333
@@ -316,32 +343,22 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
316 343
317 if (ret == ACT_P_CREATED) 344 if (ret == ACT_P_CREATED)
318 tcf_hash_insert(act); 345 tcf_hash_insert(act);
346 else
347 tcf_bpf_cfg_cleanup(&old);
319 348
320 return ret; 349 return ret;
321 350
322destroy_fp: 351destroy_fp:
323 if (is_ebpf) 352 tcf_bpf_cfg_cleanup(&cfg);
324 bpf_prog_put(cfg.filter);
325 else
326 bpf_prog_destroy(cfg.filter);
327
328 kfree(cfg.bpf_ops);
329 kfree(cfg.bpf_name);
330
331 return ret; 353 return ret;
332} 354}
333 355
334static void tcf_bpf_cleanup(struct tc_action *act, int bind) 356static void tcf_bpf_cleanup(struct tc_action *act, int bind)
335{ 357{
336 const struct tcf_bpf *prog = act->priv; 358 struct tcf_bpf_cfg tmp;
337
338 if (tcf_bpf_is_ebpf(prog))
339 bpf_prog_put(prog->filter);
340 else
341 bpf_prog_destroy(prog->filter);
342 359
343 kfree(prog->bpf_ops); 360 tcf_bpf_prog_fill_cfg(act->priv, &tmp);
344 kfree(prog->bpf_name); 361 tcf_bpf_cfg_cleanup(&tmp);
345} 362}
346 363
347static struct tc_action_ops act_bpf_ops __read_mostly = { 364static struct tc_action_ops act_bpf_ops __read_mostly = {
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index ce8676ad892f..e38a7701f154 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -69,13 +69,12 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
69 } 69 }
70 ret = ACT_P_CREATED; 70 ret = ACT_P_CREATED;
71 } else { 71 } else {
72 p = to_pedit(a);
73 tcf_hash_release(a, bind);
74 if (bind) 72 if (bind)
75 return 0; 73 return 0;
74 tcf_hash_release(a, bind);
76 if (!ovr) 75 if (!ovr)
77 return -EEXIST; 76 return -EEXIST;
78 77 p = to_pedit(a);
79 if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { 78 if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
80 keys = kmalloc(ksize, GFP_KERNEL); 79 keys = kmalloc(ksize, GFP_KERNEL);
81 if (keys == NULL) 80 if (keys == NULL)
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 93d5742dc7e0..6a783afe4960 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -385,6 +385,19 @@ static void choke_reset(struct Qdisc *sch)
385{ 385{
386 struct choke_sched_data *q = qdisc_priv(sch); 386 struct choke_sched_data *q = qdisc_priv(sch);
387 387
388 while (q->head != q->tail) {
389 struct sk_buff *skb = q->tab[q->head];
390
391 q->head = (q->head + 1) & q->tab_mask;
392 if (!skb)
393 continue;
394 qdisc_qstats_backlog_dec(sch, skb);
395 --sch->q.qlen;
396 qdisc_drop(skb, sch);
397 }
398
399 memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *));
400 q->head = q->tail = 0;
388 red_restart(&q->vars); 401 red_restart(&q->vars);
389} 402}
390 403
diff --git a/net/sched/sch_plug.c b/net/sched/sch_plug.c
index 89f8fcf73f18..ade9445a55ab 100644
--- a/net/sched/sch_plug.c
+++ b/net/sched/sch_plug.c
@@ -216,6 +216,7 @@ static struct Qdisc_ops plug_qdisc_ops __read_mostly = {
216 .peek = qdisc_peek_head, 216 .peek = qdisc_peek_head,
217 .init = plug_init, 217 .init = plug_init,
218 .change = plug_change, 218 .change = plug_change,
219 .reset = qdisc_reset_queue,
219 .owner = THIS_MODULE, 220 .owner = THIS_MODULE,
220}; 221};
221 222