Skip to content

Commit

Permalink
net: sched: use reference counting action init
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Vlad Buslov <[email protected]>
Signed-off-by: Jiri Pirko <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
w1ldptr authored and davem330 committed Jul 8, 2018
1 parent 4e8ddd7 commit cae422f
Showing 1 changed file with 17 additions and 18 deletions.
35 changes: 17 additions & 18 deletions net/sched/act_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,18 @@ static int tcf_action_put(struct tc_action *p)
return __tcf_action_put(p, false);
}

static void tcf_action_put_lst(struct list_head *actions)
{
struct tc_action *a, *tmp;

list_for_each_entry_safe(a, tmp, actions, list) {
const struct tc_action_ops *ops = a->ops;

if (tcf_action_put(a))
module_put(ops->owner);
}
}

int
tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
Expand Down Expand Up @@ -835,17 +847,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
return ERR_PTR(err);
}

static void cleanup_a(struct list_head *actions, int ovr)
{
struct tc_action *a;

if (!ovr)
return;

list_for_each_entry(a, actions, list)
refcount_dec(&a->tcfa_refcnt);
}

int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind,
struct list_head *actions, size_t *attr_size,
Expand Down Expand Up @@ -874,11 +875,6 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
}

*attr_size = tcf_action_full_attrs_size(sz);

/* Remove the temp refcnt which was necessary to protect against
* destroying an existing action which was being replaced
*/
cleanup_a(actions, ovr);
return 0;

err:
Expand Down Expand Up @@ -1209,7 +1205,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
return ret;
}
err:
tcf_action_destroy(&actions, 0);
tcf_action_put_lst(&actions);
return ret;
}

Expand Down Expand Up @@ -1251,8 +1247,11 @@ static int tcf_action_add(struct net *net, struct nlattr *nla,
&attr_size, true, extack);
if (ret)
return ret;
ret = tcf_add_notify(net, n, &actions, portid, attr_size, extack);
if (ovr)
tcf_action_put_lst(&actions);

return tcf_add_notify(net, n, &actions, portid, attr_size, extack);
return ret;
}

static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON;
Expand Down

0 comments on commit cae422f

Please sign in to comment.