All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] [GIT PULL] tracing: fixes
@ 2013-07-26 13:03 Steven Rostedt
  2013-07-26 13:03 ` [PATCH 1/9] tracing: Introduce trace_create_cpu_file() and tracing_get_cpu() Steven Rostedt
                   ` (8 more replies)
  0 siblings, 9 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: Linus Torvalds, Ingo Molnar, Andrew Morton


Linus,

Oleg is working on fixing a very tight race between opening an event file
and deleting that event at the same time (both must be done as root).

I also found a bug while testing Oleg's patches which has to do with
a race with kprobes using the function tracer.

There's also a deadlock fix that was introduced with the previous fixes.

Please pull the latest trace-fixes-3.11-rc2 tree, which can be found at:

  git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
trace-fixes-3.11-rc2

Tag SHA1: 7feda6d587604a2ab6fbb609ade28b42cd064fbd
Head SHA1: 09d8091c024ec88d1541d93eb8ddb2bd5cf10c39


Oleg Nesterov (7):
      tracing: Introduce trace_create_cpu_file() and tracing_get_cpu()
      tracing: Change tracing_pipe_fops() to rely on tracing_get_cpu()
      tracing: Change tracing_buffers_fops to rely on tracing_get_cpu()
      tracing: Change tracing_stats_fops to rely on tracing_get_cpu()
      tracing: Change tracing_entries_fops to rely on tracing_get_cpu()
      tracing: Change tracing_fops/snapshot_fops to rely on tracing_get_cpu()
      tracing: Kill trace_cpu struct/members

Steven Rostedt (Red Hat) (2):
      ftrace: Add check for NULL regs if ops has SAVE_REGS set
      tracing: Remove locking trace_types_lock from tracing_reset_all_online_cpus()

----
 kernel/trace/ftrace.c |   18 ++++-
 kernel/trace/trace.c  |  197 ++++++++++++++++++++-----------------------------
 kernel/trace/trace.h  |    8 --
 3 files changed, 95 insertions(+), 128 deletions(-)

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/9] tracing: Introduce trace_create_cpu_file() and tracing_get_cpu()
  2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
@ 2013-07-26 13:03 ` Steven Rostedt
  2013-07-26 13:03 ` [PATCH 2/9] tracing: Change tracing_pipe_fops() to rely on tracing_get_cpu() Steven Rostedt
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Ingo Molnar, Andrew Morton, Al Viro, Oleg Nesterov

[-- Attachment #1: 0001-tracing-Introduce-trace_create_cpu_file-and-tracing_.patch --]
[-- Type: text/plain, Size: 4743 bytes --]

From: Oleg Nesterov <oleg@redhat.com>

Every "file_operations" used by tracing_init_debugfs_percpu is buggy.
f_op->open/etc does:

	1. struct trace_cpu *tc = inode->i_private;
	   struct trace_array *tr = tc->tr;

	2. trace_array_get(tr) or fail;

	3. do_something(tc);

But tc (and tr) can be already freed before trace_array_get() is called.
And it doesn't matter whether this file is per-cpu or it was created by
init_tracer_debugfs(), free_percpu() or kfree() are equally bad.

Note that even 1. is not safe, the freed memory can be unmapped. But even
if it was safe trace_array_get() can wrongly succeed if we also race with
the next new_instance_create() which can re-allocate the same tr, or tc
was overwritten and ->tr points to the valid tr. In this case 3. uses the
freed/reused memory.

Add the new trivial helper, trace_create_cpu_file() which simply calls
trace_create_file() and encodes "cpu" in "struct inode". Another helper,
tracing_get_cpu() will be used to read cpu_nr-or-RING_BUFFER_ALL_CPUS.

The patch abuses ->i_cdev to encode the number, it is never used unless
the file is S_ISCHR(). But we could use something else, say, i_bytes or
even ->d_fsdata. In any case this hack is hidden inside these 2 helpers,
it would be trivial to change them if needed.

This patch only changes tracing_init_debugfs_percpu() to use the new
trace_create_cpu_file(), the next patches will change file_operations.

Note: tracing_get_cpu(inode) is always safe but you can't trust the
result unless trace_array_get() was called, without trace_types_lock
which acts as a barrier it can wrongly return RING_BUFFER_ALL_CPUS.

Link: http://lkml.kernel.org/r/20130723152554.GA23710@redhat.com

Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c |   50 ++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 14 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 3f24777..cfff63c 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2843,6 +2843,17 @@ static int s_show(struct seq_file *m, void *v)
 	return 0;
 }
 
+/*
+ * Should be used after trace_array_get(), trace_types_lock
+ * ensures that i_cdev was already initialized.
+ */
+static inline int tracing_get_cpu(struct inode *inode)
+{
+	if (inode->i_cdev) /* See trace_create_cpu_file() */
+		return (long)inode->i_cdev - 1;
+	return RING_BUFFER_ALL_CPUS;
+}
+
 static const struct seq_operations tracer_seq_ops = {
 	.start		= s_start,
 	.next		= s_next,
@@ -5529,6 +5540,17 @@ static struct dentry *tracing_dentry_percpu(struct trace_array *tr, int cpu)
 	return tr->percpu_dir;
 }
 
+static struct dentry *
+trace_create_cpu_file(const char *name, umode_t mode, struct dentry *parent,
+		      void *data, long cpu, const struct file_operations *fops)
+{
+	struct dentry *ret = trace_create_file(name, mode, parent, data, fops);
+
+	if (ret) /* See tracing_get_cpu() */
+		ret->d_inode->i_cdev = (void *)(cpu + 1);
+	return ret;
+}
+
 static void
 tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 {
@@ -5548,28 +5570,28 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 	}
 
 	/* per cpu trace_pipe */
-	trace_create_file("trace_pipe", 0444, d_cpu,
-			(void *)&data->trace_cpu, &tracing_pipe_fops);
+	trace_create_cpu_file("trace_pipe", 0444, d_cpu,
+				&data->trace_cpu, cpu, &tracing_pipe_fops);
 
 	/* per cpu trace */
-	trace_create_file("trace", 0644, d_cpu,
-			(void *)&data->trace_cpu, &tracing_fops);
+	trace_create_cpu_file("trace", 0644, d_cpu,
+				&data->trace_cpu, cpu, &tracing_fops);
 
-	trace_create_file("trace_pipe_raw", 0444, d_cpu,
-			(void *)&data->trace_cpu, &tracing_buffers_fops);
+	trace_create_cpu_file("trace_pipe_raw", 0444, d_cpu,
+				&data->trace_cpu, cpu, &tracing_buffers_fops);
 
-	trace_create_file("stats", 0444, d_cpu,
-			(void *)&data->trace_cpu, &tracing_stats_fops);
+	trace_create_cpu_file("stats", 0444, d_cpu,
+				&data->trace_cpu, cpu, &tracing_stats_fops);
 
-	trace_create_file("buffer_size_kb", 0444, d_cpu,
-			(void *)&data->trace_cpu, &tracing_entries_fops);
+	trace_create_cpu_file("buffer_size_kb", 0444, d_cpu,
+				&data->trace_cpu, cpu, &tracing_entries_fops);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
-	trace_create_file("snapshot", 0644, d_cpu,
-			  (void *)&data->trace_cpu, &snapshot_fops);
+	trace_create_cpu_file("snapshot", 0644, d_cpu,
+				&data->trace_cpu, cpu, &snapshot_fops);
 
-	trace_create_file("snapshot_raw", 0444, d_cpu,
-			(void *)&data->trace_cpu, &snapshot_raw_fops);
+	trace_create_cpu_file("snapshot_raw", 0444, d_cpu,
+				&data->trace_cpu, cpu, &snapshot_raw_fops);
 #endif
 }
 
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/9] tracing: Change tracing_pipe_fops() to rely on tracing_get_cpu()
  2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
  2013-07-26 13:03 ` [PATCH 1/9] tracing: Introduce trace_create_cpu_file() and tracing_get_cpu() Steven Rostedt
@ 2013-07-26 13:03 ` Steven Rostedt
  2013-07-26 13:03 ` [PATCH 3/9] tracing: Change tracing_buffers_fops " Steven Rostedt
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: Linus Torvalds, Ingo Molnar, Andrew Morton, Oleg Nesterov

[-- Attachment #1: 0002-tracing-Change-tracing_pipe_fops-to-rely-on-tracing_.patch --]
[-- Type: text/plain, Size: 2455 bytes --]

From: Oleg Nesterov <oleg@redhat.com>

tracing_open_pipe() is racy, the memory inode->i_private points to
can be already freed.

Change debugfs_create_file("trace_pipe", data) callers to to pass
"data = tr", tracing_open_pipe() can use tracing_get_cpu().

Link: http://lkml.kernel.org/r/20130723152557.GA23717@redhat.com

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c |   16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index cfff63c..51a99ef 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3959,8 +3959,7 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf,
 
 static int tracing_open_pipe(struct inode *inode, struct file *filp)
 {
-	struct trace_cpu *tc = inode->i_private;
-	struct trace_array *tr = tc->tr;
+	struct trace_array *tr = inode->i_private;
 	struct trace_iterator *iter;
 	int ret = 0;
 
@@ -4006,9 +4005,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
 	if (trace_clocks[tr->clock_id].in_ns)
 		iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
 
-	iter->cpu_file = tc->cpu;
-	iter->tr = tc->tr;
-	iter->trace_buffer = &tc->tr->trace_buffer;
+	iter->tr = tr;
+	iter->trace_buffer = &tr->trace_buffer;
+	iter->cpu_file = tracing_get_cpu(inode);
 	mutex_init(&iter->mutex);
 	filp->private_data = iter;
 
@@ -4031,8 +4030,7 @@ fail:
 static int tracing_release_pipe(struct inode *inode, struct file *file)
 {
 	struct trace_iterator *iter = file->private_data;
-	struct trace_cpu *tc = inode->i_private;
-	struct trace_array *tr = tc->tr;
+	struct trace_array *tr = inode->i_private;
 
 	mutex_lock(&trace_types_lock);
 
@@ -5571,7 +5569,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 
 	/* per cpu trace_pipe */
 	trace_create_cpu_file("trace_pipe", 0444, d_cpu,
-				&data->trace_cpu, cpu, &tracing_pipe_fops);
+				tr, cpu, &tracing_pipe_fops);
 
 	/* per cpu trace */
 	trace_create_cpu_file("trace", 0644, d_cpu,
@@ -6157,7 +6155,7 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
 			(void *)&tr->trace_cpu, &tracing_fops);
 
 	trace_create_file("trace_pipe", 0444, d_tracer,
-			(void *)&tr->trace_cpu, &tracing_pipe_fops);
+			  tr, &tracing_pipe_fops);
 
 	trace_create_file("buffer_size_kb", 0644, d_tracer,
 			(void *)&tr->trace_cpu, &tracing_entries_fops);
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/9] tracing: Change tracing_buffers_fops to rely on tracing_get_cpu()
  2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
  2013-07-26 13:03 ` [PATCH 1/9] tracing: Introduce trace_create_cpu_file() and tracing_get_cpu() Steven Rostedt
  2013-07-26 13:03 ` [PATCH 2/9] tracing: Change tracing_pipe_fops() to rely on tracing_get_cpu() Steven Rostedt
@ 2013-07-26 13:03 ` Steven Rostedt
  2013-07-26 13:03 ` [PATCH 4/9] tracing: Change tracing_stats_fops " Steven Rostedt
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: Linus Torvalds, Ingo Molnar, Andrew Morton, Oleg Nesterov

[-- Attachment #1: 0003-tracing-Change-tracing_buffers_fops-to-rely-on-traci.patch --]
[-- Type: text/plain, Size: 2114 bytes --]

From: Oleg Nesterov <oleg@redhat.com>

tracing_buffers_open() is racy, the memory inode->i_private points
to can be already freed.

Change debugfs_create_file("trace_pipe_raw", data) caller to pass
"data = tr", tracing_buffers_open() can use tracing_get_cpu().

Change debugfs_create_file("snapshot_raw_fops", data) caller too,
this file uses tracing_buffers_open/release.

Link: http://lkml.kernel.org/r/20130723152600.GA23720@redhat.com

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 51a99ef..30c058a 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4949,8 +4949,7 @@ static const struct file_operations snapshot_raw_fops = {
 
 static int tracing_buffers_open(struct inode *inode, struct file *filp)
 {
-	struct trace_cpu *tc = inode->i_private;
-	struct trace_array *tr = tc->tr;
+	struct trace_array *tr = inode->i_private;
 	struct ftrace_buffer_info *info;
 	int ret;
 
@@ -4969,7 +4968,7 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
 	mutex_lock(&trace_types_lock);
 
 	info->iter.tr		= tr;
-	info->iter.cpu_file	= tc->cpu;
+	info->iter.cpu_file	= tracing_get_cpu(inode);
 	info->iter.trace	= tr->current_trace;
 	info->iter.trace_buffer = &tr->trace_buffer;
 	info->spare		= NULL;
@@ -5576,7 +5575,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 				&data->trace_cpu, cpu, &tracing_fops);
 
 	trace_create_cpu_file("trace_pipe_raw", 0444, d_cpu,
-				&data->trace_cpu, cpu, &tracing_buffers_fops);
+				tr, cpu, &tracing_buffers_fops);
 
 	trace_create_cpu_file("stats", 0444, d_cpu,
 				&data->trace_cpu, cpu, &tracing_stats_fops);
@@ -5589,7 +5588,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 				&data->trace_cpu, cpu, &snapshot_fops);
 
 	trace_create_cpu_file("snapshot_raw", 0444, d_cpu,
-				&data->trace_cpu, cpu, &snapshot_raw_fops);
+				tr, cpu, &snapshot_raw_fops);
 #endif
 }
 
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/9] tracing: Change tracing_stats_fops to rely on tracing_get_cpu()
  2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
                   ` (2 preceding siblings ...)
  2013-07-26 13:03 ` [PATCH 3/9] tracing: Change tracing_buffers_fops " Steven Rostedt
@ 2013-07-26 13:03 ` Steven Rostedt
  2013-07-26 13:03 ` [PATCH 5/9] tracing: Change tracing_entries_fops " Steven Rostedt
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: Linus Torvalds, Ingo Molnar, Andrew Morton, Oleg Nesterov

[-- Attachment #1: 0004-tracing-Change-tracing_stats_fops-to-rely-on-tracing.patch --]
[-- Type: text/plain, Size: 2330 bytes --]

From: Oleg Nesterov <oleg@redhat.com>

tracing_open_generic_tc() is racy, the memory inode->i_private
points to can be already freed.

1. Change one of its users, tracing_stats_fops, to use
   tracing_*_generic_tr() instead.

2. Change trace_create_cpu_file("stats", data) to pass "data = tr".

3. Change tracing_stats_read() to use tracing_get_cpu().

Link: http://lkml.kernel.org/r/20130723152603.GA23727@redhat.com

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c |   13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 30c058a..e29dc8f 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2982,7 +2982,6 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp)
 	filp->private_data = inode->i_private;
 
 	return 0;
-	
 }
 
 static int tracing_open_generic_tc(struct inode *inode, struct file *filp)
@@ -5285,14 +5284,14 @@ static ssize_t
 tracing_stats_read(struct file *filp, char __user *ubuf,
 		   size_t count, loff_t *ppos)
 {
-	struct trace_cpu *tc = filp->private_data;
-	struct trace_array *tr = tc->tr;
+	struct inode *inode = file_inode(filp);
+	struct trace_array *tr = inode->i_private;
 	struct trace_buffer *trace_buf = &tr->trace_buffer;
+	int cpu = tracing_get_cpu(inode);
 	struct trace_seq *s;
 	unsigned long cnt;
 	unsigned long long t;
 	unsigned long usec_rem;
-	int cpu = tc->cpu;
 
 	s = kmalloc(sizeof(*s), GFP_KERNEL);
 	if (!s)
@@ -5345,10 +5344,10 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
 }
 
 static const struct file_operations tracing_stats_fops = {
-	.open		= tracing_open_generic_tc,
+	.open		= tracing_open_generic_tr,
 	.read		= tracing_stats_read,
 	.llseek		= generic_file_llseek,
-	.release	= tracing_release_generic_tc,
+	.release	= tracing_release_generic_tr,
 };
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -5578,7 +5577,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 				tr, cpu, &tracing_buffers_fops);
 
 	trace_create_cpu_file("stats", 0444, d_cpu,
-				&data->trace_cpu, cpu, &tracing_stats_fops);
+				tr, cpu, &tracing_stats_fops);
 
 	trace_create_cpu_file("buffer_size_kb", 0444, d_cpu,
 				&data->trace_cpu, cpu, &tracing_entries_fops);
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/9] tracing: Change tracing_entries_fops to rely on tracing_get_cpu()
  2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
                   ` (3 preceding siblings ...)
  2013-07-26 13:03 ` [PATCH 4/9] tracing: Change tracing_stats_fops " Steven Rostedt
@ 2013-07-26 13:03 ` Steven Rostedt
  2013-07-26 13:03 ` [PATCH 6/9] tracing: Change tracing_fops/snapshot_fops " Steven Rostedt
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: Linus Torvalds, Ingo Molnar, Andrew Morton, Oleg Nesterov

[-- Attachment #1: 0005-tracing-Change-tracing_entries_fops-to-rely-on-traci.patch --]
[-- Type: text/plain, Size: 4629 bytes --]

From: Oleg Nesterov <oleg@redhat.com>

tracing_open_generic_tc() is racy, the memory inode->i_private
points to can be already freed.

1. Change its last user, tracing_entries_fops, to use
   tracing_*_generic_tr() instead.

2. Change debugfs_create_file("buffer_size_kb", data) callers
   to pass "data = tr".

3. Change tracing_entries_read() and tracing_entries_write() to
   use tracing_get_cpu().

4. Kill the no longer used tracing_open_generic_tc() and
   tracing_release_generic_tc().

Link: http://lkml.kernel.org/r/20130723152606.GA23730@redhat.com

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c |   49 ++++++++++++-------------------------------------
 1 file changed, 12 insertions(+), 37 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index e29dc8f..68b4685 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2984,23 +2984,6 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp)
 	return 0;
 }
 
-static int tracing_open_generic_tc(struct inode *inode, struct file *filp)
-{
-	struct trace_cpu *tc = inode->i_private;
-	struct trace_array *tr = tc->tr;
-
-	if (tracing_disabled)
-		return -ENODEV;
-
-	if (trace_array_get(tr) < 0)
-		return -ENODEV;
-
-	filp->private_data = inode->i_private;
-
-	return 0;
-	
-}
-
 static int tracing_release(struct inode *inode, struct file *file)
 {
 	struct seq_file *m = file->private_data;
@@ -3054,15 +3037,6 @@ static int tracing_release_generic_tr(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static int tracing_release_generic_tc(struct inode *inode, struct file *file)
-{
-	struct trace_cpu *tc = inode->i_private;
-	struct trace_array *tr = tc->tr;
-
-	trace_array_put(tr);
-	return 0;
-}
-
 static int tracing_single_release_tr(struct inode *inode, struct file *file)
 {
 	struct trace_array *tr = inode->i_private;
@@ -4382,15 +4356,16 @@ static ssize_t
 tracing_entries_read(struct file *filp, char __user *ubuf,
 		     size_t cnt, loff_t *ppos)
 {
-	struct trace_cpu *tc = filp->private_data;
-	struct trace_array *tr = tc->tr;
+	struct inode *inode = file_inode(filp);
+	struct trace_array *tr = inode->i_private;
+	int cpu = tracing_get_cpu(inode);
 	char buf[64];
 	int r = 0;
 	ssize_t ret;
 
 	mutex_lock(&trace_types_lock);
 
-	if (tc->cpu == RING_BUFFER_ALL_CPUS) {
+	if (cpu == RING_BUFFER_ALL_CPUS) {
 		int cpu, buf_size_same;
 		unsigned long size;
 
@@ -4417,7 +4392,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf,
 		} else
 			r = sprintf(buf, "X\n");
 	} else
-		r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, tc->cpu)->entries >> 10);
+		r = sprintf(buf, "%lu\n", per_cpu_ptr(tr->trace_buffer.data, cpu)->entries >> 10);
 
 	mutex_unlock(&trace_types_lock);
 
@@ -4429,7 +4404,8 @@ static ssize_t
 tracing_entries_write(struct file *filp, const char __user *ubuf,
 		      size_t cnt, loff_t *ppos)
 {
-	struct trace_cpu *tc = filp->private_data;
+	struct inode *inode = file_inode(filp);
+	struct trace_array *tr = inode->i_private;
 	unsigned long val;
 	int ret;
 
@@ -4443,8 +4419,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
 
 	/* value is in KB */
 	val <<= 10;
-
-	ret = tracing_resize_ring_buffer(tc->tr, val, tc->cpu);
+	ret = tracing_resize_ring_buffer(tr, val, tracing_get_cpu(inode));
 	if (ret < 0)
 		return ret;
 
@@ -4892,11 +4867,11 @@ static const struct file_operations tracing_pipe_fops = {
 };
 
 static const struct file_operations tracing_entries_fops = {
-	.open		= tracing_open_generic_tc,
+	.open		= tracing_open_generic_tr,
 	.read		= tracing_entries_read,
 	.write		= tracing_entries_write,
 	.llseek		= generic_file_llseek,
-	.release	= tracing_release_generic_tc,
+	.release	= tracing_release_generic_tr,
 };
 
 static const struct file_operations tracing_total_entries_fops = {
@@ -5580,7 +5555,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 				tr, cpu, &tracing_stats_fops);
 
 	trace_create_cpu_file("buffer_size_kb", 0444, d_cpu,
-				&data->trace_cpu, cpu, &tracing_entries_fops);
+				tr, cpu, &tracing_entries_fops);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
 	trace_create_cpu_file("snapshot", 0644, d_cpu,
@@ -6156,7 +6131,7 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
 			  tr, &tracing_pipe_fops);
 
 	trace_create_file("buffer_size_kb", 0644, d_tracer,
-			(void *)&tr->trace_cpu, &tracing_entries_fops);
+			  tr, &tracing_entries_fops);
 
 	trace_create_file("buffer_total_size_kb", 0444, d_tracer,
 			  tr, &tracing_total_entries_fops);
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 6/9] tracing: Change tracing_fops/snapshot_fops to rely on tracing_get_cpu()
  2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
                   ` (4 preceding siblings ...)
  2013-07-26 13:03 ` [PATCH 5/9] tracing: Change tracing_entries_fops " Steven Rostedt
@ 2013-07-26 13:03 ` Steven Rostedt
  2013-07-26 13:03 ` [PATCH 7/9] tracing: Kill trace_cpu struct/members Steven Rostedt
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: Linus Torvalds, Ingo Molnar, Andrew Morton, Oleg Nesterov

[-- Attachment #1: 0006-tracing-Change-tracing_fops-snapshot_fops-to-rely-on.patch --]
[-- Type: text/plain, Size: 6308 bytes --]

From: Oleg Nesterov <oleg@redhat.com>

tracing_open() and tracing_snapshot_open() are racy, the memory
inode->i_private points to can be already freed.

Convert these last users of "inode->i_private == trace_cpu" to
use "i_private = trace_array" and rely on tracing_get_cpu().

v2: incorporate the fix from Steven, tracing_release() must not
    blindly dereference file->private_data unless we know that
    the file was opened for reading.

Link: http://lkml.kernel.org/r/20130723152610.GA23737@redhat.com

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c |   50 ++++++++++++++++++++++----------------------------
 1 file changed, 22 insertions(+), 28 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 68b4685..dd7780d 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2862,9 +2862,9 @@ static const struct seq_operations tracer_seq_ops = {
 };
 
 static struct trace_iterator *
-__tracing_open(struct trace_array *tr, struct trace_cpu *tc,
-	       struct inode *inode, struct file *file, bool snapshot)
+__tracing_open(struct inode *inode, struct file *file, bool snapshot)
 {
+	struct trace_array *tr = inode->i_private;
 	struct trace_iterator *iter;
 	int cpu;
 
@@ -2905,8 +2905,8 @@ __tracing_open(struct trace_array *tr, struct trace_cpu *tc,
 		iter->trace_buffer = &tr->trace_buffer;
 	iter->snapshot = snapshot;
 	iter->pos = -1;
+	iter->cpu_file = tracing_get_cpu(inode);
 	mutex_init(&iter->mutex);
-	iter->cpu_file = tc->cpu;
 
 	/* Notify the tracer early; before we stop tracing. */
 	if (iter->trace && iter->trace->open)
@@ -2986,22 +2986,18 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp)
 
 static int tracing_release(struct inode *inode, struct file *file)
 {
+	struct trace_array *tr = inode->i_private;
 	struct seq_file *m = file->private_data;
 	struct trace_iterator *iter;
-	struct trace_array *tr;
 	int cpu;
 
-	/* Writes do not use seq_file, need to grab tr from inode */
 	if (!(file->f_mode & FMODE_READ)) {
-		struct trace_cpu *tc = inode->i_private;
-
-		trace_array_put(tc->tr);
+		trace_array_put(tr);
 		return 0;
 	}
 
+	/* Writes do not use seq_file */
 	iter = m->private;
-	tr = iter->tr;
-
 	mutex_lock(&trace_types_lock);
 
 	for_each_tracing_cpu(cpu) {
@@ -3048,8 +3044,7 @@ static int tracing_single_release_tr(struct inode *inode, struct file *file)
 
 static int tracing_open(struct inode *inode, struct file *file)
 {
-	struct trace_cpu *tc = inode->i_private;
-	struct trace_array *tr = tc->tr;
+	struct trace_array *tr = inode->i_private;
 	struct trace_iterator *iter;
 	int ret = 0;
 
@@ -3057,16 +3052,17 @@ static int tracing_open(struct inode *inode, struct file *file)
 		return -ENODEV;
 
 	/* If this file was open for write, then erase contents */
-	if ((file->f_mode & FMODE_WRITE) &&
-	    (file->f_flags & O_TRUNC)) {
-		if (tc->cpu == RING_BUFFER_ALL_CPUS)
+	if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
+		int cpu = tracing_get_cpu(inode);
+
+		if (cpu == RING_BUFFER_ALL_CPUS)
 			tracing_reset_online_cpus(&tr->trace_buffer);
 		else
-			tracing_reset(&tr->trace_buffer, tc->cpu);
+			tracing_reset(&tr->trace_buffer, cpu);
 	}
 
 	if (file->f_mode & FMODE_READ) {
-		iter = __tracing_open(tr, tc, inode, file, false);
+		iter = __tracing_open(inode, file, false);
 		if (IS_ERR(iter))
 			ret = PTR_ERR(iter);
 		else if (trace_flags & TRACE_ITER_LATENCY_FMT)
@@ -4680,8 +4676,7 @@ struct ftrace_buffer_info {
 #ifdef CONFIG_TRACER_SNAPSHOT
 static int tracing_snapshot_open(struct inode *inode, struct file *file)
 {
-	struct trace_cpu *tc = inode->i_private;
-	struct trace_array *tr = tc->tr;
+	struct trace_array *tr = inode->i_private;
 	struct trace_iterator *iter;
 	struct seq_file *m;
 	int ret = 0;
@@ -4690,7 +4685,7 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file)
 		return -ENODEV;
 
 	if (file->f_mode & FMODE_READ) {
-		iter = __tracing_open(tr, tc, inode, file, true);
+		iter = __tracing_open(inode, file, true);
 		if (IS_ERR(iter))
 			ret = PTR_ERR(iter);
 	} else {
@@ -4707,8 +4702,8 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file)
 		ret = 0;
 
 		iter->tr = tr;
-		iter->trace_buffer = &tc->tr->max_buffer;
-		iter->cpu_file = tc->cpu;
+		iter->trace_buffer = &tr->max_buffer;
+		iter->cpu_file = tracing_get_cpu(inode);
 		m->private = iter;
 		file->private_data = m;
 	}
@@ -5525,7 +5520,6 @@ trace_create_cpu_file(const char *name, umode_t mode, struct dentry *parent,
 static void
 tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 {
-	struct trace_array_cpu *data = per_cpu_ptr(tr->trace_buffer.data, cpu);
 	struct dentry *d_percpu = tracing_dentry_percpu(tr, cpu);
 	struct dentry *d_cpu;
 	char cpu_dir[30]; /* 30 characters should be more than enough */
@@ -5546,7 +5540,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 
 	/* per cpu trace */
 	trace_create_cpu_file("trace", 0644, d_cpu,
-				&data->trace_cpu, cpu, &tracing_fops);
+				tr, cpu, &tracing_fops);
 
 	trace_create_cpu_file("trace_pipe_raw", 0444, d_cpu,
 				tr, cpu, &tracing_buffers_fops);
@@ -5559,7 +5553,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
 
 #ifdef CONFIG_TRACER_SNAPSHOT
 	trace_create_cpu_file("snapshot", 0644, d_cpu,
-				&data->trace_cpu, cpu, &snapshot_fops);
+				tr, cpu, &snapshot_fops);
 
 	trace_create_cpu_file("snapshot_raw", 0444, d_cpu,
 				tr, cpu, &snapshot_raw_fops);
@@ -6125,7 +6119,7 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
 			  tr, &tracing_iter_fops);
 
 	trace_create_file("trace", 0644, d_tracer,
-			(void *)&tr->trace_cpu, &tracing_fops);
+			  tr, &tracing_fops);
 
 	trace_create_file("trace_pipe", 0444, d_tracer,
 			  tr, &tracing_pipe_fops);
@@ -6146,11 +6140,11 @@ init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer)
 			  &trace_clock_fops);
 
 	trace_create_file("tracing_on", 0644, d_tracer,
-			    tr, &rb_simple_fops);
+			  tr, &rb_simple_fops);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
 	trace_create_file("snapshot", 0644, d_tracer,
-			  (void *)&tr->trace_cpu, &snapshot_fops);
+			  tr, &snapshot_fops);
 #endif
 
 	for_each_tracing_cpu(cpu)
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 7/9] tracing: Kill trace_cpu struct/members
  2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
                   ` (5 preceding siblings ...)
  2013-07-26 13:03 ` [PATCH 6/9] tracing: Change tracing_fops/snapshot_fops " Steven Rostedt
@ 2013-07-26 13:03 ` Steven Rostedt
  2013-07-26 13:03 ` [PATCH 8/9] ftrace: Add check for NULL regs if ops has SAVE_REGS set Steven Rostedt
  2013-07-26 13:03 ` [PATCH 9/9] tracing: Remove locking trace_types_lock from tracing_reset_all_online_cpus() Steven Rostedt
  8 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: Linus Torvalds, Ingo Molnar, Andrew Morton, Oleg Nesterov

[-- Attachment #1: 0007-tracing-Kill-trace_cpu-struct-members.patch --]
[-- Type: text/plain, Size: 3201 bytes --]

From: Oleg Nesterov <oleg@redhat.com>

After the previous changes trace_array_cpu->trace_cpu and
trace_array->trace_cpu becomes write-only. Remove these members
and kill "struct trace_cpu" as well.

As a side effect this also removes memset(per_cpu_memory, 0).
It was not needed, alloc_percpu() returns zero-filled memory.

Link: http://lkml.kernel.org/r/20130723152613.GA23741@redhat.com

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c |   21 ---------------------
 kernel/trace/trace.h |    8 --------
 2 files changed, 29 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index dd7780d..69cba47 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -5865,17 +5865,6 @@ struct dentry *trace_instance_dir;
 static void
 init_tracer_debugfs(struct trace_array *tr, struct dentry *d_tracer);
 
-static void init_trace_buffers(struct trace_array *tr, struct trace_buffer *buf)
-{
-	int cpu;
-
-	for_each_tracing_cpu(cpu) {
-		memset(per_cpu_ptr(buf->data, cpu), 0, sizeof(struct trace_array_cpu));
-		per_cpu_ptr(buf->data, cpu)->trace_cpu.cpu = cpu;
-		per_cpu_ptr(buf->data, cpu)->trace_cpu.tr = tr;
-	}
-}
-
 static int
 allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size)
 {
@@ -5893,8 +5882,6 @@ allocate_trace_buffer(struct trace_array *tr, struct trace_buffer *buf, int size
 		return -ENOMEM;
 	}
 
-	init_trace_buffers(tr, buf);
-
 	/* Allocate the first page for all buffers */
 	set_buffer_entries(&tr->trace_buffer,
 			   ring_buffer_size(tr->trace_buffer.buffer, 0));
@@ -5961,10 +5948,6 @@ static int new_instance_create(const char *name)
 	if (allocate_trace_buffers(tr, trace_buf_size) < 0)
 		goto out_free_tr;
 
-	/* Holder for file callbacks */
-	tr->trace_cpu.cpu = RING_BUFFER_ALL_CPUS;
-	tr->trace_cpu.tr = tr;
-
 	tr->dir = debugfs_create_dir(name, trace_instance_dir);
 	if (!tr->dir)
 		goto out_free_tr;
@@ -6438,10 +6421,6 @@ __init static int tracer_alloc_buffers(void)
 
 	global_trace.flags = TRACE_ARRAY_FL_GLOBAL;
 
-	/* Holder for file callbacks */
-	global_trace.trace_cpu.cpu = RING_BUFFER_ALL_CPUS;
-	global_trace.trace_cpu.tr = &global_trace;
-
 	INIT_LIST_HEAD(&global_trace.systems);
 	INIT_LIST_HEAD(&global_trace.events);
 	list_add(&global_trace.list, &ftrace_trace_arrays);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index e7d643b..afaae41 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -130,19 +130,12 @@ enum trace_flag_type {
 
 struct trace_array;
 
-struct trace_cpu {
-	struct trace_array	*tr;
-	struct dentry		*dir;
-	int			cpu;
-};
-
 /*
  * The CPU trace array - it consists of thousands of trace entries
  * plus some other descriptor data: (for example which task started
  * the trace, etc.)
  */
 struct trace_array_cpu {
-	struct trace_cpu	trace_cpu;
 	atomic_t		disabled;
 	void			*buffer_page;	/* ring buffer spare */
 
@@ -196,7 +189,6 @@ struct trace_array {
 	bool			allocated_snapshot;
 #endif
 	int			buffer_disabled;
-	struct trace_cpu	trace_cpu;	/* place holder */
 #ifdef CONFIG_FTRACE_SYSCALLS
 	int			sys_refcount_enter;
 	int			sys_refcount_exit;
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 8/9] ftrace: Add check for NULL regs if ops has SAVE_REGS set
  2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
                   ` (6 preceding siblings ...)
  2013-07-26 13:03 ` [PATCH 7/9] tracing: Kill trace_cpu struct/members Steven Rostedt
@ 2013-07-26 13:03 ` Steven Rostedt
  2013-07-26 13:03 ` [PATCH 9/9] tracing: Remove locking trace_types_lock from tracing_reset_all_online_cpus() Steven Rostedt
  8 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel; +Cc: Linus Torvalds, Ingo Molnar, Andrew Morton

[-- Attachment #1: 0008-ftrace-Add-check-for-NULL-regs-if-ops-has-SAVE_REGS-.patch --]
[-- Type: text/plain, Size: 2985 bytes --]

From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>

If a ftrace ops is registered with the SAVE_REGS flag set, and there's
already a ops registered to one of its functions but without the
SAVE_REGS flag, there's a small race window where the SAVE_REGS ops gets
added to the list of callbacks to call for that function before the
callback trampoline gets set to save the regs.

The problem is, the function is not currently saving regs, which opens
a small race window where the ops that is expecting regs to be passed
to it, wont. This can cause a crash if the callback were to reference
the regs, as the SAVE_REGS guarantees that regs will be set.

To fix this, we add a check in the loop case where it checks if the ops
has the SAVE_REGS flag set, and if so, it will ignore it if regs is
not set.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/ftrace.c |   18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 67708f4..8ce9eef 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1441,12 +1441,22 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
  * the hashes are freed with call_rcu_sched().
  */
 static int
-ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
 {
 	struct ftrace_hash *filter_hash;
 	struct ftrace_hash *notrace_hash;
 	int ret;
 
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+	/*
+	 * There's a small race when adding ops that the ftrace handler
+	 * that wants regs, may be called without them. We can not
+	 * allow that handler to be called if regs is NULL.
+	 */
+	if (regs == NULL && (ops->flags & FTRACE_OPS_FL_SAVE_REGS))
+		return 0;
+#endif
+
 	filter_hash = rcu_dereference_raw_notrace(ops->filter_hash);
 	notrace_hash = rcu_dereference_raw_notrace(ops->notrace_hash);
 
@@ -4218,7 +4228,7 @@ static inline void ftrace_startup_enable(int command) { }
 # define ftrace_shutdown_sysctl()	do { } while (0)
 
 static inline int
-ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip)
+ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs)
 {
 	return 1;
 }
@@ -4241,7 +4251,7 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,
 	do_for_each_ftrace_op(op, ftrace_control_list) {
 		if (!(op->flags & FTRACE_OPS_FL_STUB) &&
 		    !ftrace_function_local_disabled(op) &&
-		    ftrace_ops_test(op, ip))
+		    ftrace_ops_test(op, ip, regs))
 			op->func(ip, parent_ip, op, regs);
 	} while_for_each_ftrace_op(op);
 	trace_recursion_clear(TRACE_CONTROL_BIT);
@@ -4274,7 +4284,7 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
 	 */
 	preempt_disable_notrace();
 	do_for_each_ftrace_op(op, ftrace_ops_list) {
-		if (ftrace_ops_test(op, ip))
+		if (ftrace_ops_test(op, ip, regs))
 			op->func(ip, parent_ip, op, regs);
 	} while_for_each_ftrace_op(op);
 	preempt_enable_notrace();
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 9/9] tracing: Remove locking trace_types_lock from tracing_reset_all_online_cpus()
  2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
                   ` (7 preceding siblings ...)
  2013-07-26 13:03 ` [PATCH 8/9] ftrace: Add check for NULL regs if ops has SAVE_REGS set Steven Rostedt
@ 2013-07-26 13:03 ` Steven Rostedt
  2013-07-26 16:15   ` Arend van Spriel
  8 siblings, 1 reply; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 13:03 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Ingo Molnar, Andrew Morton, Arend van Spril,
	Alexander Z Lam, Vaibhav Nagarnaik, David Sharp, stable

[-- Attachment #1: 0009-tracing-Remove-locking-trace_types_lock-from-tracing.patch --]
[-- Type: text/plain, Size: 1943 bytes --]

From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>

Commit a82274151af "tracing: Protect ftrace_trace_arrays list in trace_events.c"
added taking the trace_types_lock mutex in trace_events.c as there were
several locations that needed it for protection. Unfortunately, it also
encapsulated a call to tracing_reset_all_online_cpus() which also takes
the trace_types_lock, causing a deadlock.

This happens when a module has tracepoints and has been traced. When the
module is removed, the trace events module notifier will grab the
trace_types_lock, do a bunch of clean ups, and also clears the buffer
by calling tracing_reset_all_online_cpus. This doesn't happen often
which explains why it wasn't caught right away.

Commit a82274151af was marked for stable, which means this must be
sent to stable too.

Link: http://lkml.kernel.org/r/51EEC646.7070306@broadcom.com

Reported-by: Arend van Spril <arend@broadcom.com>
Tested-by: Arend van Spriel <arend@broadcom.com>
Cc: Alexander Z Lam <azl@google.com>
Cc: Vaibhav Nagarnaik <vnagarnaik@google.com>
Cc: David Sharp <dhsharp@google.com>
Cc: stable@vger.kernel.org # 3.10
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 69cba47..882ec1d 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1224,18 +1224,17 @@ void tracing_reset_current(int cpu)
 	tracing_reset(&global_trace.trace_buffer, cpu);
 }
 
+/* Must have trace_types_lock held */
 void tracing_reset_all_online_cpus(void)
 {
 	struct trace_array *tr;
 
-	mutex_lock(&trace_types_lock);
 	list_for_each_entry(tr, &ftrace_trace_arrays, list) {
 		tracing_reset_online_cpus(&tr->trace_buffer);
 #ifdef CONFIG_TRACER_MAX_TRACE
 		tracing_reset_online_cpus(&tr->max_buffer);
 #endif
 	}
-	mutex_unlock(&trace_types_lock);
 }
 
 #define SAVED_CMDLINES 128
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 9/9] tracing: Remove locking trace_types_lock from tracing_reset_all_online_cpus()
  2013-07-26 13:03 ` [PATCH 9/9] tracing: Remove locking trace_types_lock from tracing_reset_all_online_cpus() Steven Rostedt
@ 2013-07-26 16:15   ` Arend van Spriel
  2013-07-26 16:41     ` Steven Rostedt
  0 siblings, 1 reply; 12+ messages in thread
From: Arend van Spriel @ 2013-07-26 16:15 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Andrew Morton,
	Alexander Z Lam, Vaibhav Nagarnaik, David Sharp, stable

On 07/26/2013 03:03 PM, Steven Rostedt wrote:
> From: "Steven Rostedt (Red Hat)"<rostedt@goodmis.org>
>
> Commit a82274151af "tracing: Protect ftrace_trace_arrays list in trace_events.c"
> added taking the trace_types_lock mutex in trace_events.c as there were
> several locations that needed it for protection. Unfortunately, it also
> encapsulated a call to tracing_reset_all_online_cpus() which also takes
> the trace_types_lock, causing a deadlock.
>
> This happens when a module has tracepoints and has been traced. When the
> module is removed, the trace events module notifier will grab the
> trace_types_lock, do a bunch of clean ups, and also clears the buffer
> by calling tracing_reset_all_online_cpus. This doesn't happen often
> which explains why it wasn't caught right away.
>
> Commit a82274151af was marked for stable, which means this must be
> sent to stable too.
>
> Link:http://lkml.kernel.org/r/51EEC646.7070306@broadcom.com
>
> Reported-by: Arend van *Spril*<arend@broadcom.com>

Nasty dutch names, huh. If we ever meet on a summit you may try to 
pronounce it :-) Way easier than Finnish.

Regards,
Arend

> Tested-by: Arend van *Spriel*<arend@broadcom.com>
> Cc: Alexander Z Lam<azl@google.com>
> Cc: Vaibhav Nagarnaik<vnagarnaik@google.com>
> Cc: David Sharp<dhsharp@google.com>
> Cc:stable@vger.kernel.org  # 3.10
> Signed-off-by: Steven Rostedt<rostedt@goodmis.org>
> ---
>   kernel/trace/trace.c |    3 +--
>   1 file changed, 1 insertion(+), 2 deletions(-)



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 9/9] tracing: Remove locking trace_types_lock from tracing_reset_all_online_cpus()
  2013-07-26 16:15   ` Arend van Spriel
@ 2013-07-26 16:41     ` Steven Rostedt
  0 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2013-07-26 16:41 UTC (permalink / raw)
  To: Arend van Spriel
  Cc: linux-kernel, Linus Torvalds, Ingo Molnar, Andrew Morton,
	Alexander Z Lam, Vaibhav Nagarnaik, David Sharp, stable

On Fri, 2013-07-26 at 18:15 +0200, Arend van Spriel wrote:

> > Link:http://lkml.kernel.org/r/51EEC646.7070306@broadcom.com
> >
> > Reported-by: Arend van *Spril*<arend@broadcom.com>
> 
> Nasty dutch names, huh. If we ever meet on a summit you may try to 
> pronounce it :-) Way easier than Finnish.

Eek! How did that happen?? You would think cut and paste would work. I
did cut off the quotes that I had from the place that I cut it from. I
must have cropped off the 'e' there somehow too?

Sorry about that.

> 
> Regards,
> Arend
> 
> > Tested-by: Arend van *Spriel*<arend@broadcom.com>

Well, at least I got this part right.

-- Steve


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2013-07-26 16:41 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-26 13:03 [PATCH 0/9] [GIT PULL] tracing: fixes Steven Rostedt
2013-07-26 13:03 ` [PATCH 1/9] tracing: Introduce trace_create_cpu_file() and tracing_get_cpu() Steven Rostedt
2013-07-26 13:03 ` [PATCH 2/9] tracing: Change tracing_pipe_fops() to rely on tracing_get_cpu() Steven Rostedt
2013-07-26 13:03 ` [PATCH 3/9] tracing: Change tracing_buffers_fops " Steven Rostedt
2013-07-26 13:03 ` [PATCH 4/9] tracing: Change tracing_stats_fops " Steven Rostedt
2013-07-26 13:03 ` [PATCH 5/9] tracing: Change tracing_entries_fops " Steven Rostedt
2013-07-26 13:03 ` [PATCH 6/9] tracing: Change tracing_fops/snapshot_fops " Steven Rostedt
2013-07-26 13:03 ` [PATCH 7/9] tracing: Kill trace_cpu struct/members Steven Rostedt
2013-07-26 13:03 ` [PATCH 8/9] ftrace: Add check for NULL regs if ops has SAVE_REGS set Steven Rostedt
2013-07-26 13:03 ` [PATCH 9/9] tracing: Remove locking trace_types_lock from tracing_reset_all_online_cpus() Steven Rostedt
2013-07-26 16:15   ` Arend van Spriel
2013-07-26 16:41     ` Steven Rostedt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.