aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVlad Buslov <vladbu@mellanox.com>2018-08-10 13:51:50 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-11 15:37:10 -0400
commit729e01260989cc06c8a78491b46545793aef323a (patch)
tree7edb289b936935c0bb7c8a7ec27c1902a27e040a /net
parentc8814552fe51358f5fc46bc1c4aa4bb68454f4eb (diff)
net: sched: act_tunnel_key: remove dependency on rtnl lock
Use tcf lock to protect tunnel key action struct private data from concurrent modification in init and dump. Use rcu swap operation to reassign params pointer under protection of tcf lock. (old params value is not used by init, so there is no need of standalone rcu dereference step) Remove rtnl lock assertion that is no longer required. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/sched/act_tunnel_key.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index d42d9e112789..ba2ae9f75ef5 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -204,7 +204,6 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
204{ 204{
205 struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); 205 struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
206 struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1]; 206 struct nlattr *tb[TCA_TUNNEL_KEY_MAX + 1];
207 struct tcf_tunnel_key_params *params_old;
208 struct tcf_tunnel_key_params *params_new; 207 struct tcf_tunnel_key_params *params_new;
209 struct metadata_dst *metadata = NULL; 208 struct metadata_dst *metadata = NULL;
210 struct tc_tunnel_key *parm; 209 struct tc_tunnel_key *parm;
@@ -346,24 +345,22 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
346 345
347 t = to_tunnel_key(*a); 346 t = to_tunnel_key(*a);
348 347
349 ASSERT_RTNL();
350 params_new = kzalloc(sizeof(*params_new), GFP_KERNEL); 348 params_new = kzalloc(sizeof(*params_new), GFP_KERNEL);
351 if (unlikely(!params_new)) { 349 if (unlikely(!params_new)) {
352 tcf_idr_release(*a, bind); 350 tcf_idr_release(*a, bind);
353 NL_SET_ERR_MSG(extack, "Cannot allocate tunnel key parameters"); 351 NL_SET_ERR_MSG(extack, "Cannot allocate tunnel key parameters");
354 return -ENOMEM; 352 return -ENOMEM;
355 } 353 }
356
357 params_old = rtnl_dereference(t->params);
358
359 t->tcf_action = parm->action;
360 params_new->tcft_action = parm->t_action; 354 params_new->tcft_action = parm->t_action;
361 params_new->tcft_enc_metadata = metadata; 355 params_new->tcft_enc_metadata = metadata;
362 356
363 rcu_assign_pointer(t->params, params_new); 357 spin_lock(&t->tcf_lock);
364 358 t->tcf_action = parm->action;
365 if (params_old) 359 rcu_swap_protected(t->params, params_new,
366 kfree_rcu(params_old, rcu); 360 lockdep_is_held(&t->tcf_lock));
361 spin_unlock(&t->tcf_lock);
362 if (params_new)
363 kfree_rcu(params_new, rcu);
367 364
368 if (ret == ACT_P_CREATED) 365 if (ret == ACT_P_CREATED)
369 tcf_idr_insert(tn, *a); 366 tcf_idr_insert(tn, *a);
@@ -485,12 +482,13 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
485 .index = t->tcf_index, 482 .index = t->tcf_index,
486 .refcnt = refcount_read(&t->tcf_refcnt) - ref, 483 .refcnt = refcount_read(&t->tcf_refcnt) - ref,
487 .bindcnt = atomic_read(&t->tcf_bindcnt) - bind, 484 .bindcnt = atomic_read(&t->tcf_bindcnt) - bind,
488 .action = t->tcf_action,
489 }; 485 };
490 struct tcf_t tm; 486 struct tcf_t tm;
491 487
492 params = rtnl_dereference(t->params); 488 spin_lock(&t->tcf_lock);
493 489 params = rcu_dereference_protected(t->params,
490 lockdep_is_held(&t->tcf_lock));
491 opt.action = t->tcf_action;
494 opt.t_action = params->tcft_action; 492 opt.t_action = params->tcft_action;
495 493
496 if (nla_put(skb, TCA_TUNNEL_KEY_PARMS, sizeof(opt), &opt)) 494 if (nla_put(skb, TCA_TUNNEL_KEY_PARMS, sizeof(opt), &opt))
@@ -522,10 +520,12 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,
522 if (nla_put_64bit(skb, TCA_TUNNEL_KEY_TM, sizeof(tm), 520 if (nla_put_64bit(skb, TCA_TUNNEL_KEY_TM, sizeof(tm),
523 &tm, TCA_TUNNEL_KEY_PAD)) 521 &tm, TCA_TUNNEL_KEY_PAD))
524 goto nla_put_failure; 522 goto nla_put_failure;
523 spin_unlock(&t->tcf_lock);
525 524
526 return skb->len; 525 return skb->len;
527 526
528nla_put_failure: 527nla_put_failure:
528 spin_unlock(&t->tcf_lock);
529 nlmsg_trim(skb, b); 529 nlmsg_trim(skb, b);
530 return -1; 530 return -1;
531} 531}