diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2014-05-30 16:49:46 +0200 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-05-30 19:03:40 +0200 |
commit | 4c27e756bc019ec1c11232893af036fdae720a97 (patch) | |
tree | 799c598208d828e343422d73cb70b74e22f64608 /kernel/trace | |
parent | tracing: Try again for saved cmdline if failed due to locking (diff) | |
download | linux-4c27e756bc019ec1c11232893af036fdae720a97.tar.xz linux-4c27e756bc019ec1c11232893af036fdae720a97.zip |
tracing: Move locking of trace_cmdline_lock into start/stop seq calls
With the conversion of the saved_cmdlines output to use seq_read, there
is now a race between accessing the values of the saved_cmdlines and
the writing to them. The trace_cmdline_lock needs to be taken at
the start and stop of the seq calls.
A new __trace_find_cmdline() call is created to allow for the look up
to happen without taking the lock.
Fixes: 42584c81c5ad tracing: Have saved_cmdlines use the seq_read infrastructure
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 22a902e2ded9..626dbfde5d56 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1484,7 +1484,7 @@ static int trace_save_cmdline(struct task_struct *tsk) return 1; } -void trace_find_cmdline(int pid, char comm[]) +static void __trace_find_cmdline(int pid, char comm[]) { unsigned map; @@ -1503,13 +1503,19 @@ void trace_find_cmdline(int pid, char comm[]) return; } - preempt_disable(); - arch_spin_lock(&trace_cmdline_lock); map = map_pid_to_cmdline[pid]; if (map != NO_CMDLINE_MAP) strcpy(comm, saved_cmdlines[map]); else strcpy(comm, "<...>"); +} + +void trace_find_cmdline(int pid, char comm[]) +{ + preempt_disable(); + arch_spin_lock(&trace_cmdline_lock); + + __trace_find_cmdline(pid, comm); arch_spin_unlock(&trace_cmdline_lock); preempt_enable(); @@ -3724,6 +3730,9 @@ static void *saved_cmdlines_start(struct seq_file *m, loff_t *pos) void *v; loff_t l = 0; + preempt_disable(); + arch_spin_lock(&trace_cmdline_lock); + v = &map_cmdline_to_pid[0]; while (l <= *pos) { v = saved_cmdlines_next(m, v, &l); @@ -3736,6 +3745,8 @@ static void *saved_cmdlines_start(struct seq_file *m, loff_t *pos) static void saved_cmdlines_stop(struct seq_file *m, void *v) { + arch_spin_unlock(&trace_cmdline_lock); + preempt_enable(); } static int saved_cmdlines_show(struct seq_file *m, void *v) @@ -3743,7 +3754,7 @@ static int saved_cmdlines_show(struct seq_file *m, void *v) char buf[TASK_COMM_LEN]; unsigned int *pid = v; - trace_find_cmdline(*pid, buf); + __trace_find_cmdline(*pid, buf); seq_printf(m, "%d %s\n", *pid, buf); return 0; } |