Skip to content

Commit eec94fd

Browse files
w1ldptrdavem330
authored andcommitted
net: sched: use rcu for action cookie update
Implement functions to atomically update and free action cookie using rcu mechanism. 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 b233504 commit eec94fd

File tree

3 files changed

+32
-15
lines changed

3 files changed

+32
-15
lines changed

include/net/act_api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct tc_action {
3737
spinlock_t tcfa_lock;
3838
struct gnet_stats_basic_cpu __percpu *cpu_bstats;
3939
struct gnet_stats_queue __percpu *cpu_qstats;
40-
struct tc_cookie *act_cookie;
40+
struct tc_cookie __rcu *act_cookie;
4141
struct tcf_chain *goto_chain;
4242
};
4343
#define tcf_index common.tcfa_index

include/net/pkt_cls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,7 @@ struct tc_mqprio_qopt_offload {
781781
struct tc_cookie {
782782
u8 *data;
783783
u32 len;
784+
struct rcu_head rcu;
784785
};
785786

786787
struct tc_qopt_offload_stats {

net/sched/act_api.c

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,24 @@ static void tcf_action_goto_chain_exec(const struct tc_action *a,
5555
res->goto_tp = rcu_dereference_bh(chain->filter_chain);
5656
}
5757

58+
static void tcf_free_cookie_rcu(struct rcu_head *p)
59+
{
60+
struct tc_cookie *cookie = container_of(p, struct tc_cookie, rcu);
61+
62+
kfree(cookie->data);
63+
kfree(cookie);
64+
}
65+
66+
static void tcf_set_action_cookie(struct tc_cookie __rcu **old_cookie,
67+
struct tc_cookie *new_cookie)
68+
{
69+
struct tc_cookie *old;
70+
71+
old = xchg(old_cookie, new_cookie);
72+
if (old)
73+
call_rcu(&old->rcu, tcf_free_cookie_rcu);
74+
}
75+
5876
/* XXX: For standalone actions, we don't need a RCU grace period either, because
5977
* actions are always connected to filters and filters are already destroyed in
6078
* RCU callbacks, so after a RCU grace period actions are already disconnected
@@ -65,10 +83,7 @@ static void free_tcf(struct tc_action *p)
6583
free_percpu(p->cpu_bstats);
6684
free_percpu(p->cpu_qstats);
6785

68-
if (p->act_cookie) {
69-
kfree(p->act_cookie->data);
70-
kfree(p->act_cookie);
71-
}
86+
tcf_set_action_cookie(&p->act_cookie, NULL);
7287
if (p->goto_chain)
7388
tcf_action_goto_chain_fini(p);
7489

@@ -567,16 +582,22 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
567582
int err = -EINVAL;
568583
unsigned char *b = skb_tail_pointer(skb);
569584
struct nlattr *nest;
585+
struct tc_cookie *cookie;
570586

571587
if (nla_put_string(skb, TCA_KIND, a->ops->kind))
572588
goto nla_put_failure;
573589
if (tcf_action_copy_stats(skb, a, 0))
574590
goto nla_put_failure;
575-
if (a->act_cookie) {
576-
if (nla_put(skb, TCA_ACT_COOKIE, a->act_cookie->len,
577-
a->act_cookie->data))
591+
592+
rcu_read_lock();
593+
cookie = rcu_dereference(a->act_cookie);
594+
if (cookie) {
595+
if (nla_put(skb, TCA_ACT_COOKIE, cookie->len, cookie->data)) {
596+
rcu_read_unlock();
578597
goto nla_put_failure;
598+
}
579599
}
600+
rcu_read_unlock();
580601

581602
nest = nla_nest_start(skb, TCA_OPTIONS);
582603
if (nest == NULL)
@@ -719,13 +740,8 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
719740
if (err < 0)
720741
goto err_mod;
721742

722-
if (name == NULL && tb[TCA_ACT_COOKIE]) {
723-
if (a->act_cookie) {
724-
kfree(a->act_cookie->data);
725-
kfree(a->act_cookie);
726-
}
727-
a->act_cookie = cookie;
728-
}
743+
if (!name && tb[TCA_ACT_COOKIE])
744+
tcf_set_action_cookie(&a->act_cookie, cookie);
729745

730746
/* module count goes up only when brand new policy is created
731747
* if it exists and is only bound to in a_o->init() then

0 commit comments

Comments
 (0)