mirror of https://gitee.com/openkylin/linux.git
net: sched: act_pedit: remove dependency on rtnl lock
Rearrange pedit init code to only access pedit action data while holding tcf spinlock. Change keys allocation type to atomic to allow it to execute while holding tcf spinlock. Take tcf spinlock in dump function when accessing pedit action data. Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ff25276de9
commit
67b0c1a3c9
|
@ -187,44 +187,38 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
|
||||||
tcf_idr_cleanup(tn, parm->index);
|
tcf_idr_cleanup(tn, parm->index);
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
p = to_pedit(*a);
|
|
||||||
keys = kmalloc(ksize, GFP_KERNEL);
|
|
||||||
if (!keys) {
|
|
||||||
tcf_idr_release(*a, bind);
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
ret = ACT_P_CREATED;
|
ret = ACT_P_CREATED;
|
||||||
} else if (err > 0) {
|
} else if (err > 0) {
|
||||||
if (bind)
|
if (bind)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
if (!ovr) {
|
if (!ovr) {
|
||||||
tcf_idr_release(*a, bind);
|
|
||||||
ret = -EEXIST;
|
ret = -EEXIST;
|
||||||
goto out_free;
|
goto out_release;
|
||||||
}
|
|
||||||
p = to_pedit(*a);
|
|
||||||
if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
|
|
||||||
keys = kmalloc(ksize, GFP_KERNEL);
|
|
||||||
if (!keys) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p = to_pedit(*a);
|
||||||
spin_lock_bh(&p->tcf_lock);
|
spin_lock_bh(&p->tcf_lock);
|
||||||
p->tcfp_flags = parm->flags;
|
|
||||||
p->tcf_action = parm->action;
|
if (ret == ACT_P_CREATED ||
|
||||||
if (keys) {
|
(p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys)) {
|
||||||
|
keys = kmalloc(ksize, GFP_ATOMIC);
|
||||||
|
if (!keys) {
|
||||||
|
spin_unlock_bh(&p->tcf_lock);
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto out_release;
|
||||||
|
}
|
||||||
kfree(p->tcfp_keys);
|
kfree(p->tcfp_keys);
|
||||||
p->tcfp_keys = keys;
|
p->tcfp_keys = keys;
|
||||||
p->tcfp_nkeys = parm->nkeys;
|
p->tcfp_nkeys = parm->nkeys;
|
||||||
}
|
}
|
||||||
memcpy(p->tcfp_keys, parm->keys, ksize);
|
memcpy(p->tcfp_keys, parm->keys, ksize);
|
||||||
|
|
||||||
|
p->tcfp_flags = parm->flags;
|
||||||
|
p->tcf_action = parm->action;
|
||||||
|
|
||||||
kfree(p->tcfp_keys_ex);
|
kfree(p->tcfp_keys_ex);
|
||||||
p->tcfp_keys_ex = keys_ex;
|
p->tcfp_keys_ex = keys_ex;
|
||||||
|
|
||||||
|
@ -232,6 +226,9 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
|
||||||
if (ret == ACT_P_CREATED)
|
if (ret == ACT_P_CREATED)
|
||||||
tcf_idr_insert(tn, *a);
|
tcf_idr_insert(tn, *a);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
out_release:
|
||||||
|
tcf_idr_release(*a, bind);
|
||||||
out_free:
|
out_free:
|
||||||
kfree(keys_ex);
|
kfree(keys_ex);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -410,6 +407,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
|
||||||
if (unlikely(!opt))
|
if (unlikely(!opt))
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
|
|
||||||
|
spin_lock_bh(&p->tcf_lock);
|
||||||
memcpy(opt->keys, p->tcfp_keys,
|
memcpy(opt->keys, p->tcfp_keys,
|
||||||
p->tcfp_nkeys * sizeof(struct tc_pedit_key));
|
p->tcfp_nkeys * sizeof(struct tc_pedit_key));
|
||||||
opt->index = p->tcf_index;
|
opt->index = p->tcf_index;
|
||||||
|
@ -432,11 +430,13 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
|
||||||
tcf_tm_dump(&t, &p->tcf_tm);
|
tcf_tm_dump(&t, &p->tcf_tm);
|
||||||
if (nla_put_64bit(skb, TCA_PEDIT_TM, sizeof(t), &t, TCA_PEDIT_PAD))
|
if (nla_put_64bit(skb, TCA_PEDIT_TM, sizeof(t), &t, TCA_PEDIT_PAD))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
spin_unlock_bh(&p->tcf_lock);
|
||||||
|
|
||||||
kfree(opt);
|
kfree(opt);
|
||||||
return skb->len;
|
return skb->len;
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
|
spin_unlock_bh(&p->tcf_lock);
|
||||||
nlmsg_trim(skb, b);
|
nlmsg_trim(skb, b);
|
||||||
kfree(opt);
|
kfree(opt);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue