Skip to content

Commit 764e9a2

Browse files
w1ldptrdavem330
authored andcommitted
net: sched: act_vlan: remove dependency on rtnl lock
Use tcf spinlock to protect vlan action private data from concurrent modification during dump and init. 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 assertion that is no longer necessary. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 729e012 commit 764e9a2

File tree

1 file changed

+15
-12
lines changed

1 file changed

+15
-12
lines changed

net/sched/act_vlan.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
109109
{
110110
struct tc_action_net *tn = net_generic(net, vlan_net_id);
111111
struct nlattr *tb[TCA_VLAN_MAX + 1];
112-
struct tcf_vlan_params *p, *p_old;
112+
struct tcf_vlan_params *p;
113113
struct tc_vlan *parm;
114114
struct tcf_vlan *v;
115115
int action;
@@ -202,26 +202,24 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
202202

203203
v = to_vlan(*a);
204204

205-
ASSERT_RTNL();
206205
p = kzalloc(sizeof(*p), GFP_KERNEL);
207206
if (!p) {
208207
tcf_idr_release(*a, bind);
209208
return -ENOMEM;
210209
}
211210

212-
v->tcf_action = parm->action;
213-
214-
p_old = rtnl_dereference(v->vlan_p);
215-
216211
p->tcfv_action = action;
217212
p->tcfv_push_vid = push_vid;
218213
p->tcfv_push_prio = push_prio;
219214
p->tcfv_push_proto = push_proto;
220215

221-
rcu_assign_pointer(v->vlan_p, p);
216+
spin_lock(&v->tcf_lock);
217+
v->tcf_action = parm->action;
218+
rcu_swap_protected(v->vlan_p, p, lockdep_is_held(&v->tcf_lock));
219+
spin_unlock(&v->tcf_lock);
222220

223-
if (p_old)
224-
kfree_rcu(p_old, rcu);
221+
if (p)
222+
kfree_rcu(p, rcu);
225223

226224
if (ret == ACT_P_CREATED)
227225
tcf_idr_insert(tn, *a);
@@ -243,16 +241,18 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
243241
{
244242
unsigned char *b = skb_tail_pointer(skb);
245243
struct tcf_vlan *v = to_vlan(a);
246-
struct tcf_vlan_params *p = rtnl_dereference(v->vlan_p);
244+
struct tcf_vlan_params *p;
247245
struct tc_vlan opt = {
248246
.index = v->tcf_index,
249247
.refcnt = refcount_read(&v->tcf_refcnt) - ref,
250248
.bindcnt = atomic_read(&v->tcf_bindcnt) - bind,
251-
.action = v->tcf_action,
252-
.v_action = p->tcfv_action,
253249
};
254250
struct tcf_t t;
255251

252+
spin_lock(&v->tcf_lock);
253+
opt.action = v->tcf_action;
254+
p = rcu_dereference_protected(v->vlan_p, lockdep_is_held(&v->tcf_lock));
255+
opt.v_action = p->tcfv_action;
256256
if (nla_put(skb, TCA_VLAN_PARMS, sizeof(opt), &opt))
257257
goto nla_put_failure;
258258

@@ -268,9 +268,12 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
268268
tcf_tm_dump(&t, &v->tcf_tm);
269269
if (nla_put_64bit(skb, TCA_VLAN_TM, sizeof(t), &t, TCA_VLAN_PAD))
270270
goto nla_put_failure;
271+
spin_unlock(&v->tcf_lock);
272+
271273
return skb->len;
272274

273275
nla_put_failure:
276+
spin_unlock(&v->tcf_lock);
274277
nlmsg_trim(skb, b);
275278
return -1;
276279
}

0 commit comments

Comments
 (0)