Skip to content

Commit cae422f

Browse files
w1ldptrdavem330
authored andcommitted
net: sched: use reference counting action init
Change action API to assume that action init function always takes reference to action, even when overwriting existing action. This is necessary because action API continues to use action pointer after init function is done. At this point action becomes accessible for concurrent modifications, so user must always hold reference to it. Implement helper put list function to atomically release list of actions after action API init code is done using them. 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>
1 parent 4e8ddd7 commit cae422f

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed

net/sched/act_api.c

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,18 @@ static int tcf_action_put(struct tc_action *p)
627627
return __tcf_action_put(p, false);
628628
}
629629

630+
static void tcf_action_put_lst(struct list_head *actions)
631+
{
632+
struct tc_action *a, *tmp;
633+
634+
list_for_each_entry_safe(a, tmp, actions, list) {
635+
const struct tc_action_ops *ops = a->ops;
636+
637+
if (tcf_action_put(a))
638+
module_put(ops->owner);
639+
}
640+
}
641+
630642
int
631643
tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
632644
{
@@ -835,17 +847,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
835847
return ERR_PTR(err);
836848
}
837849

838-
static void cleanup_a(struct list_head *actions, int ovr)
839-
{
840-
struct tc_action *a;
841-
842-
if (!ovr)
843-
return;
844-
845-
list_for_each_entry(a, actions, list)
846-
refcount_dec(&a->tcfa_refcnt);
847-
}
848-
849850
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
850851
struct nlattr *est, char *name, int ovr, int bind,
851852
struct list_head *actions, size_t *attr_size,
@@ -874,11 +875,6 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
874875
}
875876

876877
*attr_size = tcf_action_full_attrs_size(sz);
877-
878-
/* Remove the temp refcnt which was necessary to protect against
879-
* destroying an existing action which was being replaced
880-
*/
881-
cleanup_a(actions, ovr);
882878
return 0;
883879

884880
err:
@@ -1209,7 +1205,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
12091205
return ret;
12101206
}
12111207
err:
1212-
tcf_action_destroy(&actions, 0);
1208+
tcf_action_put_lst(&actions);
12131209
return ret;
12141210
}
12151211

@@ -1251,8 +1247,11 @@ static int tcf_action_add(struct net *net, struct nlattr *nla,
12511247
&attr_size, true, extack);
12521248
if (ret)
12531249
return ret;
1250+
ret = tcf_add_notify(net, n, &actions, portid, attr_size, extack);
1251+
if (ovr)
1252+
tcf_action_put_lst(&actions);
12541253

1255-
return tcf_add_notify(net, n, &actions, portid, attr_size, extack);
1254+
return ret;
12561255
}
12571256

12581257
static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON;

0 commit comments

Comments
 (0)