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: Vlad Buslov <vladbu@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
67b0c1a3c9
commit
d772849566
@ -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,
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user