aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/act_connmark.c
diff options
context:
space:
mode:
authorVlad Buslov <vladbu@mellanox.com>2018-07-05 17:24:32 +0300
committerDavid S. Miller <davem@davemloft.net>2018-07-08 12:42:29 +0900
commit0190c1d452a91c38a3462abdd81752be1b9006a8 (patch)
tree861605e9fbe0db5ba1ef8a518cc0bca96d04f4fb /net/sched/act_connmark.c
parentnet: sched: use reference counting action init (diff)
downloadlinux-dev-0190c1d452a91c38a3462abdd81752be1b9006a8.tar.xz
linux-dev-0190c1d452a91c38a3462abdd81752be1b9006a8.zip
net: sched: atomically check-allocate action
Implement function that atomically checks if action exists and either takes reference to it, or allocates idr slot for action index to prevent concurrent allocations of actions with same index. Use EBUSY error pointer to indicate that idr slot is reserved. Implement cleanup helper function that removes temporary error pointer from idr. (in case of error between idr allocation and insertion of newly created action to specified index) Refactor all action init functions to insert new action to idr using this API. Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/act_connmark.c')
-rw-r--r--net/sched/act_connmark.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 701e90244eff..1e31f0e448e2 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -118,11 +118,14 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_CONNMARK_PARMS]);
- if (!tcf_idr_check(tn, parm->index, a, bind)) {
+ ret = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ if (!ret) {
ret = tcf_idr_create(tn, parm->index, est, a,
&act_connmark_ops, bind, false);
- if (ret)
+ if (ret) {
+ tcf_idr_cleanup(tn, parm->index);
return ret;
+ }
ci = to_connmark(*a);
ci->tcf_action = parm->action;
@@ -131,7 +134,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
tcf_idr_insert(tn, *a);
ret = ACT_P_CREATED;
- } else {
+ } else if (ret > 0) {
ci = to_connmark(*a);
if (bind)
return 0;
@@ -142,6 +145,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
/* replacing action and zone */
ci->tcf_action = parm->action;
ci->zone = parm->zone;
+ ret = 0;
}
return ret;