summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat)2014-05-30 16:49:46 +0200
committerSteven Rostedt2014-05-30 19:03:40 +0200
commit4c27e756bc019ec1c11232893af036fdae720a97 (patch)
tree799c598208d828e343422d73cb70b74e22f64608 /kernel
parenttracing: Try again for saved cmdline if failed due to locking (diff)
downloadkernel-qcow2-linux-4c27e756bc019ec1c11232893af036fdae720a97.tar.gz
kernel-qcow2-linux-4c27e756bc019ec1c11232893af036fdae720a97.tar.xz
kernel-qcow2-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')
-rw-r--r--kernel/trace/trace.c19
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;
}