| From 379cfdac37923653c9d4242d10052378b7563005 Mon Sep 17 00:00:00 2001 |
| From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org> |
| Date: Fri, 30 May 2014 09:42:39 -0400 |
| Subject: tracing: Try again for saved cmdline if failed due to locking |
| |
| From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org> |
| |
| commit 379cfdac37923653c9d4242d10052378b7563005 upstream. |
| |
| In order to prevent the saved cmdline cache from being filled when |
| tracing is not active, the comms are only recorded after a trace event |
| is recorded. |
| |
| The problem is, a comm can fail to be recorded if the trace_cmdline_lock |
| is held. That lock is taken via a trylock to allow it to happen from |
| any context (including NMI). If the lock fails to be taken, the comm |
| is skipped. No big deal, as we will try again later. |
| |
| But! Because of the code that was added to only record after an event, |
| we may not try again later as the recording is made as a oneshot per |
| event per CPU. |
| |
| Only disable the recording of the comm if the comm is actually recorded. |
| |
| Fixes: 7ffbd48d5cab "tracing: Cache comms only after an event occurred" |
| Signed-off-by: Steven Rostedt <rostedt@goodmis.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| kernel/trace/trace.c | 13 +++++++------ |
| 1 file changed, 7 insertions(+), 6 deletions(-) |
| |
| --- a/kernel/trace/trace.c |
| +++ b/kernel/trace/trace.c |
| @@ -1449,12 +1449,12 @@ static void tracing_stop_tr(struct trace |
| |
| void trace_stop_cmdline_recording(void); |
| |
| -static void trace_save_cmdline(struct task_struct *tsk) |
| +static int trace_save_cmdline(struct task_struct *tsk) |
| { |
| unsigned pid, idx; |
| |
| if (!tsk->pid || unlikely(tsk->pid > PID_MAX_DEFAULT)) |
| - return; |
| + return 0; |
| |
| /* |
| * It's not the end of the world if we don't get |
| @@ -1463,7 +1463,7 @@ static void trace_save_cmdline(struct ta |
| * so if we miss here, then better luck next time. |
| */ |
| if (!arch_spin_trylock(&trace_cmdline_lock)) |
| - return; |
| + return 0; |
| |
| idx = map_pid_to_cmdline[tsk->pid]; |
| if (idx == NO_CMDLINE_MAP) { |
| @@ -1488,6 +1488,8 @@ static void trace_save_cmdline(struct ta |
| memcpy(&saved_cmdlines[idx], tsk->comm, TASK_COMM_LEN); |
| |
| arch_spin_unlock(&trace_cmdline_lock); |
| + |
| + return 1; |
| } |
| |
| void trace_find_cmdline(int pid, char comm[]) |
| @@ -1529,9 +1531,8 @@ void tracing_record_cmdline(struct task_ |
| if (!__this_cpu_read(trace_cmdline_save)) |
| return; |
| |
| - __this_cpu_write(trace_cmdline_save, false); |
| - |
| - trace_save_cmdline(tsk); |
| + if (trace_save_cmdline(tsk)) |
| + __this_cpu_write(trace_cmdline_save, false); |
| } |
| |
| void |