Message ID | 20230520094722.5393-1-zegao@tencent.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | | expand |
Thanks Steven, I think we've come to a consensus on this. The question here is whether bpf tracing fentry i.e., __bpf_prog_enter{_sleepable} needs to check rcu_is_watching as well before using rcu related calls. And Yonghong suggested making a change when there is indeed some bad case occurring since it's rare the tracee is in the idle path. Regards, Ze On Tue, May 23, 2023 at 10:10 PM Steven Rostedt <rostedt@goodmis.org> wrote: > > [ Added a subject, as I always want to delete these emails as spam! ] > > On Mon, 22 May 2023 10:07:42 +0800 > Ze Gao <zegao2021@gmail.com> wrote: > > > Oops, I missed that. Thanks for pointing that out, which I thought is > > conditional use of rcu_is_watching before. > > > > One last point, I think we should double check on this > > "fentry does not filter with !rcu_is_watching" > > as quoted from Yonghong and argue whether it needs > > the same check for fentry as well. > > > > Note that trace_test_and_set_recursion() (which is used by > ftrace_test_recursion_trylock()) checks for rcu_is_watching() and > returns false if it isn't (and the trylock will fail). > > -- Steve
On Mon, 22 May 2023 23:59:28 -0700 "Paul E. McKenney" <paulmck@kernel.org> wrote: > On Tue, May 23, 2023 at 01:30:19PM +0800, Masami Hiramatsu wrote: > > On Mon, 22 May 2023 10:07:42 +0800 > > Ze Gao <zegao2021@gmail.com> wrote: > > > > > Oops, I missed that. Thanks for pointing that out, which I thought is > > > conditional use of rcu_is_watching before. > > > > > > One last point, I think we should double check on this > > > "fentry does not filter with !rcu_is_watching" > > > as quoted from Yonghong and argue whether it needs > > > the same check for fentry as well. > > > > rcu_is_watching() comment says; > > > > * if the current CPU is not in its idle loop or is in an interrupt or > > * NMI handler, return true. > > > > Thus it returns *fault* if the current CPU is in the idle loop and not > > any interrupt(including NMI) context. This means if any tracable function > > is called from idle loop, it can be !rcu_is_watching(). I meant, this is > > 'context' based check, thus fentry can not filter out that some commonly > > used functions is called from that context but it can be detected. > > It really does return false (rather than faulting?) if the current CPU > is deep within the idle loop. > > In addition, the recent x86/entry rework (thank you Peter and > Thomas!) mean that the "idle loop" is quite restricted, as can be > seen by the invocations of ct_cpuidle_enter() and ct_cpuidle_exit(). > For example, in default_idle_call(), these are immediately before and > after the call to arch_cpu_idle(). Thanks! I also found that the default_idle_call() is enough small and it seems not happening on fentry because there are no commonly used functions on that path. > > Would the following help? Or am I missing your point? Yes, thank you for the update! > > Thanx, Paul > > ------------------------------------------------------------------------ > > diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c > index 1449cb69a0e0..fae9b4e29c93 100644 > --- a/kernel/rcu/tree.c > +++ b/kernel/rcu/tree.c > @@ -679,10 +679,14 @@ static void rcu_disable_urgency_upon_qs(struct rcu_data *rdp) > /** > * rcu_is_watching - see if RCU thinks that the current CPU is not idle > * > - * Return true if RCU is watching the running CPU, which means that this > - * CPU can safely enter RCU read-side critical sections. In other words, > - * if the current CPU is not in its idle loop or is in an interrupt or > - * NMI handler, return true. > + * Return @true if RCU is watching the running CPU and @false otherwise. > + * An @true return means that this CPU can safely enter RCU read-side > + * critical sections. > + * > + * More specifically, if the current CPU is not deep within its idle > + * loop, return @true. Note that rcu_is_watching() will return @true if > + * invoked from an interrupt or NMI handler, even if that interrupt or > + * NMI interrupted the CPU while it was deep within its idle loop. > * > * Make notrace because it can be called by the internal functions of > * ftrace, and making this notrace removes unnecessary recursion calls.
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 9a050e36dc6c..3e6ea7274765 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2622,7 +2622,7 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link, struct bpf_run_ctx *old_run_ctx; int err; - if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1)) { + if (unlikely(__this_cpu_inc_return(bpf_prog_active) != 1 || !rcu_is_watching())) { err = 0; goto out; }