Re: [PATCH] tracing: Add an 'overwrite' trace_option.

From: David Sharp
Date: Tue Mar 08 2011 - 19:46:17 EST


On Wed, Dec 8, 2010 at 1:46 PM, David Sharp <dhsharp@xxxxxxxxxx> wrote:
> Add an "overwrite" trace_option for ftrace to control whether the buffer should
> be overwritten on overflow or not. The default remains to overwrite old events
> when the buffer is full. This patch adds the option to instead discard newest
> events when the buffer is full. This is useful to get a snapshot of traces just
> after enabling traces. Dropping the current event is also a simpler code path.

Signed-off-by: David Sharp <dhsharp@xxxxxxxxxx>

> ---
> ÂDocumentation/trace/ftrace.txt | Â Â5 +++++
> Âinclude/linux/ring_buffer.h  Â|  Â2 ++
> Âkernel/trace/ring_buffer.c   |  11 +++++++++++
> Âkernel/trace/trace.c      |  17 +++++++++++------
> Âkernel/trace/trace.h      |  Â1 +
> Â5 files changed, 30 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
> index 557c1ed..2842ea7 100644
> --- a/Documentation/trace/ftrace.txt
> +++ b/Documentation/trace/ftrace.txt
> @@ -491,6 +491,11 @@ x494] <- /root/a.out[+0x4a8] <- /lib/libc-2.7.so[+0x1e1a6]
> Â Â Â Â Â Â Â Â Â Âlatencies, as described in "Latency
> Â Â Â Â Â Â Â Â Â Âtrace format".
>
> + Âoverwrite - This controls what happens when the trace buffer is
> + Â Â Â Â Â Â Âfull. If "1" (default), the oldest events are
> + Â Â Â Â Â Â Âdiscarded and overwritten. If "0", then the newest
> + Â Â Â Â Â Â Âevents are discarded.
> +
> Âsched_switch
> Â------------
>
> diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
> index 8d3a248..ab38ac8 100644
> --- a/include/linux/ring_buffer.h
> +++ b/include/linux/ring_buffer.h
> @@ -100,6 +100,8 @@ void ring_buffer_free(struct ring_buffer *buffer);
>
> Âint ring_buffer_resize(struct ring_buffer *buffer, unsigned long size);
>
> +void ring_buffer_change_overwrite(struct ring_buffer *buffer, int val);
> +
> Âstruct ring_buffer_event *ring_buffer_lock_reserve(struct ring_buffer *buffer,
> Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â unsigned long length);
> Âint ring_buffer_unlock_commit(struct ring_buffer *buffer,
> diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> index 9ed509a..3207147 100644
> --- a/kernel/trace/ring_buffer.c
> +++ b/kernel/trace/ring_buffer.c
> @@ -1429,6 +1429,17 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
> Â}
> ÂEXPORT_SYMBOL_GPL(ring_buffer_resize);
>
> +void ring_buffer_change_overwrite(struct ring_buffer *buffer, int val)
> +{
> + Â Â Â mutex_lock(&buffer->mutex);
> + Â Â Â if (val)
> + Â Â Â Â Â Â Â buffer->flags |= RB_FL_OVERWRITE;
> + Â Â Â else
> + Â Â Â Â Â Â Â buffer->flags &= ~RB_FL_OVERWRITE;
> + Â Â Â mutex_unlock(&buffer->mutex);
> +}
> +EXPORT_SYMBOL_GPL(ring_buffer_change_overwrite);
> +
> Âstatic inline void *
> Â__rb_data_page_index(struct buffer_data_page *bpage, unsigned index)
> Â{
> diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
> index c380612..6f7494c 100644
> --- a/kernel/trace/trace.c
> +++ b/kernel/trace/trace.c
> @@ -41,8 +41,6 @@
> Â#include "trace.h"
> Â#include "trace_output.h"
>
> -#define TRACE_BUFFER_FLAGS Â Â (RB_FL_OVERWRITE)
> -
> Â/*
> Â* On boot up, the ring buffer is set to the minimum size, so that
> Â* we do not waste memory on systems that are not using tracing.
> @@ -340,7 +338,7 @@ static DECLARE_WAIT_QUEUE_HEAD(trace_wait);
> Â/* trace_flags holds trace_options default values */
> Âunsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
> Â Â Â ÂTRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME |
> - Â Â Â TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD;
> + Â Â Â TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE;
>
> Âstatic int trace_stop_count;
> Âstatic DEFINE_SPINLOCK(tracing_start_lock);
> @@ -425,6 +423,7 @@ static const char *trace_options[] = {
> Â Â Â Â"sleep-time",
> Â Â Â Â"graph-time",
> Â Â Â Â"record-cmd",
> + Â Â Â "overwrite",
> Â Â Â ÂNULL
> Â};
>
> @@ -2523,6 +2522,9 @@ static void set_tracer_flags(unsigned int mask, int enabled)
>
> Â Â Â Âif (mask == TRACE_ITER_RECORD_CMD)
> Â Â Â Â Â Â Â Âtrace_event_enable_cmd_record(enabled);
> +
> + Â Â Â if (mask == TRACE_ITER_OVERWRITE)
> + Â Â Â Â Â Â Â ring_buffer_change_overwrite(global_trace.buffer, enabled);
> Â}
>
> Âstatic ssize_t
> @@ -4545,9 +4547,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
> Â__init static int tracer_alloc_buffers(void)
> Â{
> Â Â Â Âint ring_buf_size;
> + Â Â Â enum ring_buffer_flags rb_flags;
> Â Â Â Âint i;
> Â Â Â Âint ret = -ENOMEM;
>
> +
> Â Â Â Âif (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL))
> Â Â Â Â Â Â Â Âgoto out;
>
> @@ -4560,12 +4564,13 @@ __init static int tracer_alloc_buffers(void)
> Â Â Â Âelse
> Â Â Â Â Â Â Â Âring_buf_size = 1;
>
> + Â Â Â rb_flags = trace_flags & TRACE_ITER_OVERWRITE ? RB_FL_OVERWRITE : 0;
> +
> Â Â Â Âcpumask_copy(tracing_buffer_mask, cpu_possible_mask);
> Â Â Â Âcpumask_copy(tracing_cpumask, cpu_all_mask);
>
> Â Â Â Â/* TODO: make the number of buffers hot pluggable with CPUS */
> - Â Â Â global_trace.buffer = ring_buffer_alloc(ring_buf_size,
> - Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ÂTRACE_BUFFER_FLAGS);
> + Â Â Â global_trace.buffer = ring_buffer_alloc(ring_buf_size, rb_flags);
> Â Â Â Âif (!global_trace.buffer) {
> Â Â Â Â Â Â Â Âprintk(KERN_ERR "tracer: failed to allocate ring buffer!\n");
> Â Â Â Â Â Â Â ÂWARN_ON(1);
> @@ -4575,7 +4580,7 @@ __init static int tracer_alloc_buffers(void)
>
>
> Â#ifdef CONFIG_TRACER_MAX_TRACE
> - Â Â Â max_tr.buffer = ring_buffer_alloc(1, TRACE_BUFFER_FLAGS);
> + Â Â Â max_tr.buffer = ring_buffer_alloc(1, rb_flags);
> Â Â Â Âif (!max_tr.buffer) {
> Â Â Â Â Â Â Â Âprintk(KERN_ERR "tracer: failed to allocate max ring buffer!\n");
> Â Â Â Â Â Â Â ÂWARN_ON(1);
> diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
> index 9021f8c..9cd025a 100644
> --- a/kernel/trace/trace.h
> +++ b/kernel/trace/trace.h
> @@ -606,6 +606,7 @@ enum trace_iterator_flags {
> Â Â Â ÂTRACE_ITER_SLEEP_TIME Â Â Â Â Â = 0x40000,
> Â Â Â ÂTRACE_ITER_GRAPH_TIME Â Â Â Â Â = 0x80000,
> Â Â Â ÂTRACE_ITER_RECORD_CMD Â Â Â Â Â = 0x100000,
> + Â Â Â TRACE_ITER_OVERWRITE Â Â Â Â Â Â= 0x200000,
> Â};
>
> Â/*
> --
> 1.7.3.1
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/