| From afcab636657421f7ebfa0783a91f90256bba0091 Mon Sep 17 00:00:00 2001 |
| From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> |
| Date: Tue, 4 Aug 2020 20:00:02 -0400 |
| Subject: [PATCH] tracing: Use trace_sched_process_free() instead of exit() for |
| pid tracing |
| |
| commit afcab636657421f7ebfa0783a91f90256bba0091 upstream. |
| |
| On exit, if a process is preempted after the trace_sched_process_exit() |
| tracepoint but before the process is done exiting, then when it gets |
| scheduled in, the function tracers will not filter it properly against the |
| function tracing pid filters. |
| |
| That is because the function tracing pid filters hooks to the |
| sched_process_exit() tracepoint to remove the exiting task's pid from the |
| filter list. Because the filtering happens at the sched_switch tracepoint, |
| when the exiting task schedules back in to finish up the exit, it will no |
| longer be in the function pid filtering tables. |
| |
| This was noticeable in the notrace self tests on a preemptable kernel, as |
| the tests would fail as it exits and preempted after being taken off the |
| notrace filter table and on scheduling back in it would not be in the |
| notrace list, and then the ending of the exit function would trace. The test |
| detected this and would fail. |
| |
| Cc: stable@vger.kernel.org |
| Cc: Namhyung Kim <namhyung@kernel.org> |
| Fixes: 1e10486ffee0a ("ftrace: Add 'function-fork' trace option") |
| Fixes: c37775d57830a ("tracing: Add infrastructure to allow set_event_pid to follow children" |
| Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> |
| |
| diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c |
| index 4e3a5d79c078..76f2dd6fd414 100644 |
| --- a/kernel/trace/ftrace.c |
| +++ b/kernel/trace/ftrace.c |
| @@ -6985,12 +6985,12 @@ void ftrace_pid_follow_fork(struct trace_array *tr, bool enable) |
| if (enable) { |
| register_trace_sched_process_fork(ftrace_pid_follow_sched_process_fork, |
| tr); |
| - register_trace_sched_process_exit(ftrace_pid_follow_sched_process_exit, |
| + register_trace_sched_process_free(ftrace_pid_follow_sched_process_exit, |
| tr); |
| } else { |
| unregister_trace_sched_process_fork(ftrace_pid_follow_sched_process_fork, |
| tr); |
| - unregister_trace_sched_process_exit(ftrace_pid_follow_sched_process_exit, |
| + unregister_trace_sched_process_free(ftrace_pid_follow_sched_process_exit, |
| tr); |
| } |
| } |
| diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c |
| index f6f55682d3e2..a85effb2373b 100644 |
| --- a/kernel/trace/trace_events.c |
| +++ b/kernel/trace/trace_events.c |
| @@ -538,12 +538,12 @@ void trace_event_follow_fork(struct trace_array *tr, bool enable) |
| if (enable) { |
| register_trace_prio_sched_process_fork(event_filter_pid_sched_process_fork, |
| tr, INT_MIN); |
| - register_trace_prio_sched_process_exit(event_filter_pid_sched_process_exit, |
| + register_trace_prio_sched_process_free(event_filter_pid_sched_process_exit, |
| tr, INT_MAX); |
| } else { |
| unregister_trace_sched_process_fork(event_filter_pid_sched_process_fork, |
| tr); |
| - unregister_trace_sched_process_exit(event_filter_pid_sched_process_exit, |
| + unregister_trace_sched_process_free(event_filter_pid_sched_process_exit, |
| tr); |
| } |
| } |
| -- |
| 2.27.0 |
| |