Commit d7728495 authored by Vlad Buslov's avatar Vlad Buslov Committed by David S. Miller

net: sched: act_sample: remove dependency on rtnl lock

Use tcf spinlock to protect private sample action data from concurrent
modification during dump and init.
Signed-off-by: default avatarVlad Buslov <vladbu@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 67b0c1a3
...@@ -80,11 +80,13 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, ...@@ -80,11 +80,13 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
} }
s = to_sample(*a); s = to_sample(*a);
spin_lock(&s->tcf_lock);
s->tcf_action = parm->action; s->tcf_action = parm->action;
s->rate = nla_get_u32(tb[TCA_SAMPLE_RATE]); s->rate = nla_get_u32(tb[TCA_SAMPLE_RATE]);
s->psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]); s->psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]);
psample_group = psample_group_get(net, s->psample_group_num); psample_group = psample_group_get(net, s->psample_group_num);
if (!psample_group) { if (!psample_group) {
spin_unlock(&s->tcf_lock);
tcf_idr_release(*a, bind); tcf_idr_release(*a, bind);
return -ENOMEM; return -ENOMEM;
} }
...@@ -94,6 +96,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, ...@@ -94,6 +96,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
s->truncate = true; s->truncate = true;
s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]); s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]);
} }
spin_unlock(&s->tcf_lock);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
tcf_idr_insert(tn, *a); tcf_idr_insert(tn, *a);
...@@ -105,7 +108,8 @@ static void tcf_sample_cleanup(struct tc_action *a) ...@@ -105,7 +108,8 @@ static void tcf_sample_cleanup(struct tc_action *a)
struct tcf_sample *s = to_sample(a); struct tcf_sample *s = to_sample(a);
struct psample_group *psample_group; struct psample_group *psample_group;
psample_group = rtnl_dereference(s->psample_group); /* last reference to action, no need to lock */
psample_group = rcu_dereference_protected(s->psample_group, 1);
RCU_INIT_POINTER(s->psample_group, NULL); RCU_INIT_POINTER(s->psample_group, NULL);
if (psample_group) if (psample_group)
psample_group_put(psample_group); psample_group_put(psample_group);
...@@ -174,12 +178,13 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -174,12 +178,13 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a,
struct tcf_sample *s = to_sample(a); struct tcf_sample *s = to_sample(a);
struct tc_sample opt = { struct tc_sample opt = {
.index = s->tcf_index, .index = s->tcf_index,
.action = s->tcf_action,
.refcnt = refcount_read(&s->tcf_refcnt) - ref, .refcnt = refcount_read(&s->tcf_refcnt) - ref,
.bindcnt = atomic_read(&s->tcf_bindcnt) - bind, .bindcnt = atomic_read(&s->tcf_bindcnt) - bind,
}; };
struct tcf_t t; struct tcf_t t;
spin_lock(&s->tcf_lock);
opt.action = s->tcf_action;
if (nla_put(skb, TCA_SAMPLE_PARMS, sizeof(opt), &opt)) if (nla_put(skb, TCA_SAMPLE_PARMS, sizeof(opt), &opt))
goto nla_put_failure; goto nla_put_failure;
...@@ -196,9 +201,12 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -196,9 +201,12 @@ static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a,
if (nla_put_u32(skb, TCA_SAMPLE_PSAMPLE_GROUP, s->psample_group_num)) if (nla_put_u32(skb, TCA_SAMPLE_PSAMPLE_GROUP, s->psample_group_num))
goto nla_put_failure; goto nla_put_failure;
spin_unlock(&s->tcf_lock);
return skb->len; return skb->len;
nla_put_failure: nla_put_failure:
spin_unlock(&s->tcf_lock);
nlmsg_trim(skb, b); nlmsg_trim(skb, b);
return -1; return -1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment