diff options
author | David S. Miller <davem@davemloft.net> | 2015-08-01 02:52:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-01 02:52:20 -0400 |
commit | 5510b3c2a173921374ec847848fb20b98e1c698a (patch) | |
tree | c9e185281ef17280ce0dc30be7923124874736b0 /net/sched | |
parent | 17f901e8915cb922c2ca710835ef34f166f53ee9 (diff) | |
parent | 7c764cec3703583247c4ab837c652975a3d41f4b (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.c | 11 | ||||
-rw-r--r-- | net/sched/act_bpf.c | 53 | ||||
-rw-r--r-- | net/sched/act_pedit.c | 5 | ||||
-rw-r--r-- | net/sched/sch_choke.c | 13 | ||||
-rw-r--r-- | net/sched/sch_plug.c | 1 |
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 | } |
55 | EXPORT_SYMBOL(tcf_hash_destroy); | 55 | EXPORT_SYMBOL(tcf_hash_destroy); |
56 | 56 | ||
57 | int tcf_hash_release(struct tc_action *a, int bind) | 57 | int __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 | } |
78 | EXPORT_SYMBOL(tcf_hash_release); | 79 | EXPORT_SYMBOL(__tcf_hash_release); |
79 | 80 | ||
80 | static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, | 81 | static 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 @@ | |||
27 | struct tcf_bpf_cfg { | 27 | struct 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 | ||
35 | static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, | 36 | static 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 | ||
251 | static 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 | |||
262 | static 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 | |||
248 | static int tcf_bpf_init(struct net *net, struct nlattr *nla, | 272 | static 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 | ||
322 | destroy_fp: | 351 | destroy_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 | ||
334 | static void tcf_bpf_cleanup(struct tc_action *act, int bind) | 356 | static 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 | ||
347 | static struct tc_action_ops act_bpf_ops __read_mostly = { | 364 | static 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 | ||