diff options
author | Alexei Starovoitov <ast@plumgrid.com> | 2015-08-26 06:06:35 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-26 21:01:45 +0300 |
commit | cff82457c5584f6a96d2b85d1a88b81ba304a330 (patch) | |
tree | ee2e2eb473e84ba5c052dddd05ef09db5b7faeb3 /include/net/tc_act | |
parent | 9e528d89154b602209fda2fb92e89927bbffc976 (diff) | |
download | linux-cff82457c5584f6a96d2b85d1a88b81ba304a330.tar.xz |
net_sched: act_bpf: remove spinlock in fast path
Similar to act_gact/act_mirred, act_bpf can be lockless in packet processing
with extra care taken to free bpf programs after rcu grace period.
Replacement of existing act_bpf (very rare) is done with synchronize_rcu()
and final destruction is done from tc_action_ops->cleanup() callback that is
called from tcf_exts_destroy()->tcf_action_destroy()->__tcf_hash_release() when
bind and refcnt reach zero which is only possible when classifier is destroyed.
Previous two patches fixed the last two classifiers (tcindex and rsvp) to
call tcf_exts_destroy() from rcu callback.
Similar to gact/mirred there is a race between prog->filter and
prog->tcf_action. Meaning that the program being replaced may use
previous default action if it happened to return TC_ACT_UNSPEC.
act_mirred race betwen tcf_action and tcfm_dev is similar.
In all cases the race is harmless.
Long term we may want to improve the situation by replacing the whole
tc_action->priv as single pointer instead of updating inner fields one by one.
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/tc_act')
-rw-r--r-- | include/net/tc_act/tc_bpf.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/include/net/tc_act/tc_bpf.h b/include/net/tc_act/tc_bpf.h index a152e9858b2c..958d69cfb19c 100644 --- a/include/net/tc_act/tc_bpf.h +++ b/include/net/tc_act/tc_bpf.h @@ -15,7 +15,7 @@ struct tcf_bpf { struct tcf_common common; - struct bpf_prog *filter; + struct bpf_prog __rcu *filter; union { u32 bpf_fd; u16 bpf_num_ops; |