diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2014-05-30 10:49:46 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-05-30 13:03:40 -0400 |
commit | 4c27e756bc019ec1c11232893af036fdae720a97 (patch) | |
tree | 799c598208d828e343422d73cb70b74e22f64608 /kernel/trace | |
parent | 379cfdac37923653c9d4242d10052378b7563005 (diff) |
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) | |||
1484 | return 1; | 1484 | return 1; |
1485 | } | 1485 | } |
1486 | 1486 | ||
1487 | void trace_find_cmdline(int pid, char comm[]) | 1487 | static void __trace_find_cmdline(int pid, char comm[]) |
1488 | { | 1488 | { |
1489 | unsigned map; | 1489 | unsigned map; |
1490 | 1490 | ||
@@ -1503,13 +1503,19 @@ void trace_find_cmdline(int pid, char comm[]) | |||
1503 | return; | 1503 | return; |
1504 | } | 1504 | } |
1505 | 1505 | ||
1506 | preempt_disable(); | ||
1507 | arch_spin_lock(&trace_cmdline_lock); | ||
1508 | map = map_pid_to_cmdline[pid]; | 1506 | map = map_pid_to_cmdline[pid]; |
1509 | if (map != NO_CMDLINE_MAP) | 1507 | if (map != NO_CMDLINE_MAP) |
1510 | strcpy(comm, saved_cmdlines[map]); | 1508 | strcpy(comm, saved_cmdlines[map]); |
1511 | else | 1509 | else |
1512 | strcpy(comm, "<...>"); | 1510 | strcpy(comm, "<...>"); |
1511 | } | ||
1512 | |||
1513 | void trace_find_cmdline(int pid, char comm[]) | ||
1514 | { | ||
1515 | preempt_disable(); | ||
1516 | arch_spin_lock(&trace_cmdline_lock); | ||
1517 | |||
1518 | __trace_find_cmdline(pid, comm); | ||
1513 | 1519 | ||
1514 | arch_spin_unlock(&trace_cmdline_lock); | 1520 | arch_spin_unlock(&trace_cmdline_lock); |
1515 | preempt_enable(); | 1521 | preempt_enable(); |
@@ -3724,6 +3730,9 @@ static void *saved_cmdlines_start(struct seq_file *m, loff_t *pos) | |||
3724 | void *v; | 3730 | void *v; |
3725 | loff_t l = 0; | 3731 | loff_t l = 0; |
3726 | 3732 | ||
3733 | preempt_disable(); | ||
3734 | arch_spin_lock(&trace_cmdline_lock); | ||
3735 | |||
3727 | v = &map_cmdline_to_pid[0]; | 3736 | v = &map_cmdline_to_pid[0]; |
3728 | while (l <= *pos) { | 3737 | while (l <= *pos) { |
3729 | v = saved_cmdlines_next(m, v, &l); | 3738 | v = saved_cmdlines_next(m, v, &l); |
@@ -3736,6 +3745,8 @@ static void *saved_cmdlines_start(struct seq_file *m, loff_t *pos) | |||
3736 | 3745 | ||
3737 | static void saved_cmdlines_stop(struct seq_file *m, void *v) | 3746 | static void saved_cmdlines_stop(struct seq_file *m, void *v) |
3738 | { | 3747 | { |
3748 | arch_spin_unlock(&trace_cmdline_lock); | ||
3749 | preempt_enable(); | ||
3739 | } | 3750 | } |
3740 | 3751 | ||
3741 | static int saved_cmdlines_show(struct seq_file *m, void *v) | 3752 | 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) | |||
3743 | char buf[TASK_COMM_LEN]; | 3754 | char buf[TASK_COMM_LEN]; |
3744 | unsigned int *pid = v; | 3755 | unsigned int *pid = v; |
3745 | 3756 | ||
3746 | trace_find_cmdline(*pid, buf); | 3757 | __trace_find_cmdline(*pid, buf); |
3747 | seq_printf(m, "%d %s\n", *pid, buf); | 3758 | seq_printf(m, "%d %s\n", *pid, buf); |
3748 | return 0; | 3759 | return 0; |
3749 | } | 3760 | } |