public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [for-next][PATCH 0/4] tracing: Cleanups and fixes for 3.16
@ 2014-06-11  1:59 Steven Rostedt
  2014-06-11  1:59 ` [for-next][PATCH 1/4] ring-buffer: Check if buffer exists before polling Steven Rostedt
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Steven Rostedt @ 2014-06-11  1:59 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton

Thanks to Namhyung Kim who pointed out some slight things with the code
that went to Linus already, I have some early cleanups.

There's also a bug that needs to be fixed in the ring buffer waiter
logic.

  git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
for-next

Head SHA1: da9c3413a27be5ba6f996e90495c836dd30b8841


Namhyung Kim (1)
      tracing: Cleanup saved_cmdlines_size changes

Steven Rostedt (Red Hat) (3)
      ring-buffer: Check if buffer exists before polling
      tracing: Fix leak of per cpu max data in instances
      tracing: Fix check of ftrace_trace_arrays list_empty() check

----
 include/linux/ring_buffer.h |    2 -
 kernel/trace/ring_buffer.c  |    5 +++-
 kernel/trace/trace.c        |   49 +++++++++++++++++++++++++++-----------------
 kernel/trace/trace.h        |    2 -
 4 files changed, 37 insertions(+), 21 deletions(-)

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

* [for-next][PATCH 1/4] ring-buffer: Check if buffer exists before polling
  2014-06-11  1:59 [for-next][PATCH 0/4] tracing: Cleanups and fixes for 3.16 Steven Rostedt
@ 2014-06-11  1:59 ` Steven Rostedt
  2014-06-11  1:59 ` [for-next][PATCH 2/4] tracing: Cleanup saved_cmdlines_size changes Steven Rostedt
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Steven Rostedt @ 2014-06-11  1:59 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton, Sasha Levin

[-- Attachment #1: 0000-ring-buffer-Check-if-buffer-exists-before-polling.patch --]
[-- Type: text/plain, Size: 4528 bytes --]

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

The per_cpu buffers are created one per possible CPU. But these do
not mean that those CPUs are online, nor do they even exist.

With the addition of the ring buffer polling, it assumes that the
caller polls on an existing buffer. But this is not the case if
the user reads trace_pipe from a CPU that does not exist, and this
causes the kernel to crash.

Simple fix is to check the cpu against buffer bitmask against to see
if the buffer was allocated or not and return -ENODEV if it is
not.

More updates were done to pass the -ENODEV back up to userspace.

Link: http://lkml.kernel.org/r/5393DB61.6060707@oracle.com

Reported-by: Sasha Levin <sasha.levin@oracle.com>
Cc: stable@vger.kernel.org # 3.10+
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 include/linux/ring_buffer.h |  2 +-
 kernel/trace/ring_buffer.c  |  5 ++++-
 kernel/trace/trace.c        | 22 ++++++++++++++++------
 3 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index d69cf637a15a..49a4d6f59108 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -97,7 +97,7 @@ __ring_buffer_alloc(unsigned long size, unsigned flags, struct lock_class_key *k
 	__ring_buffer_alloc((size), (flags), &__key);	\
 })
 
-void ring_buffer_wait(struct ring_buffer *buffer, int cpu);
+int ring_buffer_wait(struct ring_buffer *buffer, int cpu);
 int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu,
 			  struct file *filp, poll_table *poll_table);
 
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index c634868c2921..7c56c3d06943 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -543,7 +543,7 @@ static void rb_wake_up_waiters(struct irq_work *work)
  * as data is added to any of the @buffer's cpu buffers. Otherwise
  * it will wait for data to be added to a specific cpu buffer.
  */
-void ring_buffer_wait(struct ring_buffer *buffer, int cpu)
+int ring_buffer_wait(struct ring_buffer *buffer, int cpu)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
 	DEFINE_WAIT(wait);
@@ -557,6 +557,8 @@ void ring_buffer_wait(struct ring_buffer *buffer, int cpu)
 	if (cpu == RING_BUFFER_ALL_CPUS)
 		work = &buffer->irq_work;
 	else {
+		if (!cpumask_test_cpu(cpu, buffer->cpumask))
+			return -ENODEV;
 		cpu_buffer = buffer->buffers[cpu];
 		work = &cpu_buffer->irq_work;
 	}
@@ -591,6 +593,7 @@ void ring_buffer_wait(struct ring_buffer *buffer, int cpu)
 		schedule();
 
 	finish_wait(&work->waiters, &wait);
+	return 0;
 }
 
 /**
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 16f7038d1f4d..56422f1decba 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1085,13 +1085,13 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 }
 #endif /* CONFIG_TRACER_MAX_TRACE */
 
-static void wait_on_pipe(struct trace_iterator *iter)
+static int wait_on_pipe(struct trace_iterator *iter)
 {
 	/* Iterators are static, they should be filled or empty */
 	if (trace_buffer_iter(iter, iter->cpu_file))
-		return;
+		return 0;
 
-	ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
+	return ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
 }
 
 #ifdef CONFIG_FTRACE_STARTUP_TEST
@@ -4378,6 +4378,7 @@ tracing_poll_pipe(struct file *filp, poll_table *poll_table)
 static int tracing_wait_pipe(struct file *filp)
 {
 	struct trace_iterator *iter = filp->private_data;
+	int ret;
 
 	while (trace_empty(iter)) {
 
@@ -4399,10 +4400,13 @@ static int tracing_wait_pipe(struct file *filp)
 
 		mutex_unlock(&iter->mutex);
 
-		wait_on_pipe(iter);
+		ret = wait_on_pipe(iter);
 
 		mutex_lock(&iter->mutex);
 
+		if (ret)
+			return ret;
+
 		if (signal_pending(current))
 			return -EINTR;
 	}
@@ -5327,8 +5331,12 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
 				goto out_unlock;
 			}
 			mutex_unlock(&trace_types_lock);
-			wait_on_pipe(iter);
+			ret = wait_on_pipe(iter);
 			mutex_lock(&trace_types_lock);
+			if (ret) {
+				size = ret;
+				goto out_unlock;
+			}
 			if (signal_pending(current)) {
 				size = -EINTR;
 				goto out_unlock;
@@ -5538,8 +5546,10 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 			goto out;
 		}
 		mutex_unlock(&trace_types_lock);
-		wait_on_pipe(iter);
+		ret = wait_on_pipe(iter);
 		mutex_lock(&trace_types_lock);
+		if (ret)
+			goto out;
 		if (signal_pending(current)) {
 			ret = -EINTR;
 			goto out;
-- 
2.0.0.rc2



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

* [for-next][PATCH 2/4] tracing: Cleanup saved_cmdlines_size changes
  2014-06-11  1:59 [for-next][PATCH 0/4] tracing: Cleanups and fixes for 3.16 Steven Rostedt
  2014-06-11  1:59 ` [for-next][PATCH 1/4] ring-buffer: Check if buffer exists before polling Steven Rostedt
@ 2014-06-11  1:59 ` Steven Rostedt
  2014-06-11  1:59 ` [for-next][PATCH 3/4] tracing: Fix leak of per cpu max data in instances Steven Rostedt
  2014-06-11  1:59 ` [for-next][PATCH 4/4] tracing: Fix check of ftrace_trace_arrays list_empty() check Steven Rostedt
  3 siblings, 0 replies; 5+ messages in thread
From: Steven Rostedt @ 2014-06-11  1:59 UTC (permalink / raw)
  To: linux-kernel
  Cc: Ingo Molnar, Andrew Morton, Namhyung Kim, Yoshihiro YUNOMAE,
	Namhyung Kim

[-- Attachment #1: 0001-tracing-Cleanup-saved_cmdlines_size-changes.patch --]
[-- Type: text/plain, Size: 1665 bytes --]

From: Namhyung Kim <namhyung@kernel.org>

The recent addition of saved_cmdlines_size file had some remaining
(minor - mostly coding style) issues.  Fix them by passing pointer
name to sizeof() and using scnprintf().

Link: http://lkml.kernel.org/p/1402384295-23680-1-git-send-email-namhyung@kernel.org

Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 56422f1decba..2b458c60e0da 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1338,7 +1338,7 @@ static int trace_create_savedcmd(void)
 {
 	int ret;
 
-	savedcmd = kmalloc(sizeof(struct saved_cmdlines_buffer), GFP_KERNEL);
+	savedcmd = kmalloc(sizeof(*savedcmd), GFP_KERNEL);
 	if (!savedcmd)
 		return -ENOMEM;
 
@@ -3840,7 +3840,7 @@ tracing_saved_cmdlines_size_read(struct file *filp, char __user *ubuf,
 	int r;
 
 	arch_spin_lock(&trace_cmdline_lock);
-	r = sprintf(buf, "%u\n", savedcmd->cmdline_num);
+	r = scnprintf(buf, sizeof(buf), "%u\n", savedcmd->cmdline_num);
 	arch_spin_unlock(&trace_cmdline_lock);
 
 	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
@@ -3857,7 +3857,7 @@ static int tracing_resize_saved_cmdlines(unsigned int val)
 {
 	struct saved_cmdlines_buffer *s, *savedcmd_temp;
 
-	s = kmalloc(sizeof(struct saved_cmdlines_buffer), GFP_KERNEL);
+	s = kmalloc(sizeof(*s), GFP_KERNEL);
 	if (!s)
 		return -ENOMEM;
 
-- 
2.0.0.rc2



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

* [for-next][PATCH 3/4] tracing: Fix leak of per cpu max data in instances
  2014-06-11  1:59 [for-next][PATCH 0/4] tracing: Cleanups and fixes for 3.16 Steven Rostedt
  2014-06-11  1:59 ` [for-next][PATCH 1/4] ring-buffer: Check if buffer exists before polling Steven Rostedt
  2014-06-11  1:59 ` [for-next][PATCH 2/4] tracing: Cleanup saved_cmdlines_size changes Steven Rostedt
@ 2014-06-11  1:59 ` Steven Rostedt
  2014-06-11  1:59 ` [for-next][PATCH 4/4] tracing: Fix check of ftrace_trace_arrays list_empty() check Steven Rostedt
  3 siblings, 0 replies; 5+ messages in thread
From: Steven Rostedt @ 2014-06-11  1:59 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton, Namhyung Kim

[-- Attachment #1: 0002-tracing-Fix-leak-of-per-cpu-max-data-in-instances.patch --]
[-- Type: text/plain, Size: 1665 bytes --]

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

The freeing of an instance, if max data is configured, there will be
per cpu data structures created. But these are not freed when the instance
is deleted, which causes a memory leak.

A new helper function is added that frees the individual buffers within a
trace array, instead of duplicating the code. This way changes made for one
are applied to the other (normal buffer vs max buffer).

Link: http://lkml.kernel.org/r/87k38pbake.fsf@sejong.aot.lge.com

Reported-by: Namhyung Kim <namhyung@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 2b458c60e0da..384ede311717 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6242,22 +6242,25 @@ static int allocate_trace_buffers(struct trace_array *tr, int size)
 	return 0;
 }
 
+static void free_trace_buffer(struct trace_buffer *buf)
+{
+	if (buf->buffer) {
+		ring_buffer_free(buf->buffer);
+		buf->buffer = NULL;
+		free_percpu(buf->data);
+		buf->data = NULL;
+	}
+}
+
 static void free_trace_buffers(struct trace_array *tr)
 {
 	if (!tr)
 		return;
 
-	if (tr->trace_buffer.buffer) {
-		ring_buffer_free(tr->trace_buffer.buffer);
-		tr->trace_buffer.buffer = NULL;
-		free_percpu(tr->trace_buffer.data);
-	}
+	free_trace_buffer(&tr->trace_buffer);
 
 #ifdef CONFIG_TRACER_MAX_TRACE
-	if (tr->max_buffer.buffer) {
-		ring_buffer_free(tr->max_buffer.buffer);
-		tr->max_buffer.buffer = NULL;
-	}
+	free_trace_buffer(&tr->max_buffer);
 #endif
 }
 
-- 
2.0.0.rc2



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

* [for-next][PATCH 4/4] tracing: Fix check of ftrace_trace_arrays list_empty() check
  2014-06-11  1:59 [for-next][PATCH 0/4] tracing: Cleanups and fixes for 3.16 Steven Rostedt
                   ` (2 preceding siblings ...)
  2014-06-11  1:59 ` [for-next][PATCH 3/4] tracing: Fix leak of per cpu max data in instances Steven Rostedt
@ 2014-06-11  1:59 ` Steven Rostedt
  3 siblings, 0 replies; 5+ messages in thread
From: Steven Rostedt @ 2014-06-11  1:59 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton, Namhyung Kim

[-- Attachment #1: 0003-tracing-Fix-check-of-ftrace_trace_arrays-list_empty-.patch --]
[-- Type: text/plain, Size: 1038 bytes --]

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

The check that tests if ftrace_trace_arrays is empty in
top_trace_array(), uses the .prev pointer:

  if (list_empty(ftrace_trace_arrays.prev))

instead of testing the variable itself:

  if (list_empty(&ftrace_trace_arrays))

Although it is technically correct, it is awkward and confusing.
Use the proper method.

Link: http://lkml.kernel.org/r/87oay1bas8.fsf@sejong.aot.lge.com

Reported-by: Namhyung Kim <namhyung@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 9e82551dd566..9258f5a815db 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -252,7 +252,7 @@ static inline struct trace_array *top_trace_array(void)
 {
 	struct trace_array *tr;
 
-	if (list_empty(ftrace_trace_arrays.prev))
+	if (list_empty(&ftrace_trace_arrays))
 		return NULL;
 
 	tr = list_entry(ftrace_trace_arrays.prev,
-- 
2.0.0.rc2



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

end of thread, other threads:[~2014-06-11  2:02 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-11  1:59 [for-next][PATCH 0/4] tracing: Cleanups and fixes for 3.16 Steven Rostedt
2014-06-11  1:59 ` [for-next][PATCH 1/4] ring-buffer: Check if buffer exists before polling Steven Rostedt
2014-06-11  1:59 ` [for-next][PATCH 2/4] tracing: Cleanup saved_cmdlines_size changes Steven Rostedt
2014-06-11  1:59 ` [for-next][PATCH 3/4] tracing: Fix leak of per cpu max data in instances Steven Rostedt
2014-06-11  1:59 ` [for-next][PATCH 4/4] tracing: Fix check of ftrace_trace_arrays list_empty() check Steven Rostedt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox