From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Ingo Molnar <mingo@elte.hu>, Thomas Gleixner <tglx@linutronix.de>,
Peter Zijlstra <peterz@infradead.org>,
Andrew Morton <akpm@linux-foundation.org>,
prasad@linux.vnet.ibm.com,
Linus Torvalds <torvalds@linux-foundation.org>,
Mathieu Desnoyers <compudj@krystal.dyndns.org>,
"Frank Ch. Eigler" <fche@redhat.com>,
David Wilder <dwilder@us.ibm.com>,
hch@lst.de, Martin Bligh <mbligh@google.com>,
Tom Zanussi <zanussi@comcast.net>,
Steven Rostedt <srostedt@redhat.com>
Subject: [RFC PATCH 3/3] ftrace: hack in the ring buffer
Date: Wed, 24 Sep 2008 01:10:59 -0400 [thread overview]
Message-ID: <20080924051400.552924670@goodmis.org> (raw)
In-Reply-To: 20080924051056.650388887@goodmis.org
[-- Attachment #1: ftrace-use-ring-buffer.patch --]
[-- Type: text/plain, Size: 78498 bytes --]
As a test case for the unified ring buffer, I wanted to try it out with
ftrace. This is a big patch that hacks up ftrace to get it to work.
Actually, I see areas that can be greatly improved with this new approach.
A lot of clean ups can follow this.
But before I go ahead and do all this work, I want to "release early
release often". This way I can get the feedback (whew, it's hot in here)
that will let me know what is expected.
Note, selftest is busted with this patch. I didn't have time to fixe it.
All these patches are busted, this is RFC remember!
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
---
arch/x86/kernel/Makefile | 1
include/linux/ftrace.h | 6
include/linux/mmiotrace.h | 3
kernel/trace/trace.c | 1326 ++++++++++----------------------------
kernel/trace/trace.h | 87 --
kernel/trace/trace_functions.c | 2
kernel/trace/trace_irqsoff.c | 38 -
kernel/trace/trace_mmiotrace.c | 73 --
kernel/trace/trace_sched_switch.c | 2
kernel/trace/trace_sched_wakeup.c | 3
10 files changed, 464 insertions(+), 1077 deletions(-)
Index: linux-compile.git/kernel/trace/trace.c
===================================================================
--- linux-compile.git.orig/kernel/trace/trace.c 2008-09-23 23:33:47.000000000 -0400
+++ linux-compile.git/kernel/trace/trace.c 2008-09-24 00:16:24.000000000 -0400
@@ -31,25 +31,24 @@
#include <linux/writeback.h>
#include <linux/stacktrace.h>
+#include <linux/ring_buffer.h>
#include "trace.h"
+#define FTRACE_BUF_NAME "ftrace"
+
+#define TRACE_BUFFER_FLAGS (RB_FL_OVERWRITE | RB_FL_SNAPSHOT)
+
unsigned long __read_mostly tracing_max_latency = (cycle_t)ULONG_MAX;
unsigned long __read_mostly tracing_thresh;
-static unsigned long __read_mostly tracing_nr_buffers;
static cpumask_t __read_mostly tracing_buffer_mask;
#define for_each_tracing_cpu(cpu) \
for_each_cpu_mask(cpu, tracing_buffer_mask)
-static int trace_alloc_page(void);
-static int trace_free_page(void);
-
static int tracing_disabled = 1;
-static unsigned long tracing_pages_allocated;
-
long
ns2usecs(cycle_t nsec)
{
@@ -79,20 +78,6 @@ static struct trace_array global_trace;
static DEFINE_PER_CPU(struct trace_array_cpu, global_trace_cpu);
-/*
- * The max_tr is used to snapshot the global_trace when a maximum
- * latency is reached. Some tracers will use this to store a maximum
- * trace while it continues examining live traces.
- *
- * The buffers for the max_tr are set up the same as the global_trace.
- * When a snapshot is taken, the link list of the max_tr is swapped
- * with the link list of the global_trace and the buffers are reset for
- * the global_trace so the tracing can continue.
- */
-static struct trace_array max_tr;
-
-static DEFINE_PER_CPU(struct trace_array_cpu, max_data);
-
/* tracer_enabled is used to toggle activation of a tracer */
static int tracer_enabled = 1;
@@ -100,11 +85,11 @@ static int tracer_enabled = 1;
int ftrace_function_enabled;
/*
- * trace_nr_entries is the number of entries that is allocated
- * for a buffer. Note, the number of entries is always rounded
- * to ENTRIES_PER_PAGE.
+ * trace_buf_size is the size in bytes that is allocated
+ * for a buffer. Note, the number of bytes is always rounded
+ * to page size.
*/
-static unsigned long trace_nr_entries = 65536UL;
+static unsigned long trace_buf_size = 65536UL;
/* trace_types holds a link list of available tracers. */
static struct tracer *trace_types __read_mostly;
@@ -140,7 +125,7 @@ static notrace void no_trace_init(struct
ftrace_function_enabled = 0;
if(tr->ctrl)
for_each_online_cpu(cpu)
- tracing_reset(tr->data[cpu]);
+ tracing_reset(tr, cpu);
tracer_enabled = 0;
}
@@ -167,23 +152,21 @@ void trace_wake_up(void)
wake_up(&trace_wait);
}
-#define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct trace_entry))
-
-static int __init set_nr_entries(char *str)
+static int __init set_buf_size(char *str)
{
- unsigned long nr_entries;
+ unsigned long buf_size;
int ret;
if (!str)
return 0;
- ret = strict_strtoul(str, 0, &nr_entries);
+ ret = strict_strtoul(str, 0, &buf_size);
/* nr_entries can not be zero */
- if (ret < 0 || nr_entries == 0)
+ if (ret < 0 || buf_size == 0)
return 0;
- trace_nr_entries = nr_entries;
+ trace_buf_size = buf_size;
return 1;
}
-__setup("trace_entries=", set_nr_entries);
+__setup("trace_buf_size=", set_buf_size);
unsigned long nsecs_to_usecs(unsigned long nsecs)
{
@@ -249,245 +232,20 @@ __update_max_tr(struct trace_array *tr,
{
struct trace_array_cpu *data = tr->data[cpu];
- max_tr.cpu = cpu;
- max_tr.time_start = data->preempt_timestamp;
-
- data = max_tr.data[cpu];
- data->saved_latency = tracing_max_latency;
-
- memcpy(data->comm, tsk->comm, TASK_COMM_LEN);
- data->pid = tsk->pid;
- data->uid = tsk->uid;
- data->nice = tsk->static_prio - 20 - MAX_RT_PRIO;
- data->policy = tsk->policy;
- data->rt_priority = tsk->rt_priority;
+ tr->cpu = cpu;
+ tr->time_start = data->preempt_timestamp;
+ tr->saved_latency = tracing_max_latency;
+ tr->pid = tsk->pid;
+ tr->uid = tsk->uid;
+ tr->nice = tsk->static_prio - 20 - MAX_RT_PRIO;
+ tr->policy = tsk->policy;
+ tr->rt_priority = tsk->rt_priority;
+ memcpy(tr->comm, tsk->comm, TASK_COMM_LEN);
/* record this tasks comm */
tracing_record_cmdline(current);
}
-#define CHECK_COND(cond) \
- if (unlikely(cond)) { \
- tracing_disabled = 1; \
- WARN_ON(1); \
- return -1; \
- }
-
-/**
- * check_pages - integrity check of trace buffers
- *
- * As a safty measure we check to make sure the data pages have not
- * been corrupted.
- */
-int check_pages(struct trace_array_cpu *data)
-{
- struct page *page, *tmp;
-
- CHECK_COND(data->trace_pages.next->prev != &data->trace_pages);
- CHECK_COND(data->trace_pages.prev->next != &data->trace_pages);
-
- list_for_each_entry_safe(page, tmp, &data->trace_pages, lru) {
- CHECK_COND(page->lru.next->prev != &page->lru);
- CHECK_COND(page->lru.prev->next != &page->lru);
- }
-
- return 0;
-}
-
-/**
- * head_page - page address of the first page in per_cpu buffer.
- *
- * head_page returns the page address of the first page in
- * a per_cpu buffer. This also preforms various consistency
- * checks to make sure the buffer has not been corrupted.
- */
-void *head_page(struct trace_array_cpu *data)
-{
- struct page *page;
-
- if (list_empty(&data->trace_pages))
- return NULL;
-
- page = list_entry(data->trace_pages.next, struct page, lru);
- BUG_ON(&page->lru == &data->trace_pages);
-
- return page_address(page);
-}
-
-/**
- * trace_seq_printf - sequence printing of trace information
- * @s: trace sequence descriptor
- * @fmt: printf format string
- *
- * The tracer may use either sequence operations or its own
- * copy to user routines. To simplify formating of a trace
- * trace_seq_printf is used to store strings into a special
- * buffer (@s). Then the output may be either used by
- * the sequencer or pulled into another buffer.
- */
-int
-trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
-{
- int len = (PAGE_SIZE - 1) - s->len;
- va_list ap;
- int ret;
-
- if (!len)
- return 0;
-
- va_start(ap, fmt);
- ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
- va_end(ap);
-
- /* If we can't write it all, don't bother writing anything */
- if (ret >= len)
- return 0;
-
- s->len += ret;
-
- return len;
-}
-
-/**
- * trace_seq_puts - trace sequence printing of simple string
- * @s: trace sequence descriptor
- * @str: simple string to record
- *
- * The tracer may use either the sequence operations or its own
- * copy to user routines. This function records a simple string
- * into a special buffer (@s) for later retrieval by a sequencer
- * or other mechanism.
- */
-static int
-trace_seq_puts(struct trace_seq *s, const char *str)
-{
- int len = strlen(str);
-
- if (len > ((PAGE_SIZE - 1) - s->len))
- return 0;
-
- memcpy(s->buffer + s->len, str, len);
- s->len += len;
-
- return len;
-}
-
-static int
-trace_seq_putc(struct trace_seq *s, unsigned char c)
-{
- if (s->len >= (PAGE_SIZE - 1))
- return 0;
-
- s->buffer[s->len++] = c;
-
- return 1;
-}
-
-static int
-trace_seq_putmem(struct trace_seq *s, void *mem, size_t len)
-{
- if (len > ((PAGE_SIZE - 1) - s->len))
- return 0;
-
- memcpy(s->buffer + s->len, mem, len);
- s->len += len;
-
- return len;
-}
-
-#define HEX_CHARS 17
-static const char hex2asc[] = "0123456789abcdef";
-
-static int
-trace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len)
-{
- unsigned char hex[HEX_CHARS];
- unsigned char *data = mem;
- unsigned char byte;
- int i, j;
-
- BUG_ON(len >= HEX_CHARS);
-
-#ifdef __BIG_ENDIAN
- for (i = 0, j = 0; i < len; i++) {
-#else
- for (i = len-1, j = 0; i >= 0; i--) {
-#endif
- byte = data[i];
-
- hex[j++] = hex2asc[byte & 0x0f];
- hex[j++] = hex2asc[byte >> 4];
- }
- hex[j++] = ' ';
-
- return trace_seq_putmem(s, hex, j);
-}
-
-static void
-trace_seq_reset(struct trace_seq *s)
-{
- s->len = 0;
- s->readpos = 0;
-}
-
-ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt)
-{
- int len;
- int ret;
-
- if (s->len <= s->readpos)
- return -EBUSY;
-
- len = s->len - s->readpos;
- if (cnt > len)
- cnt = len;
- ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
- if (ret)
- return -EFAULT;
-
- s->readpos += len;
- return cnt;
-}
-
-static void
-trace_print_seq(struct seq_file *m, struct trace_seq *s)
-{
- int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;
-
- s->buffer[len] = 0;
- seq_puts(m, s->buffer);
-
- trace_seq_reset(s);
-}
-
-/*
- * flip the trace buffers between two trace descriptors.
- * This usually is the buffers between the global_trace and
- * the max_tr to record a snapshot of a current trace.
- *
- * The ftrace_max_lock must be held.
- */
-static void
-flip_trace(struct trace_array_cpu *tr1, struct trace_array_cpu *tr2)
-{
- struct list_head flip_pages;
-
- INIT_LIST_HEAD(&flip_pages);
-
- memcpy(&tr1->trace_head_idx, &tr2->trace_head_idx,
- sizeof(struct trace_array_cpu) -
- offsetof(struct trace_array_cpu, trace_head_idx));
-
- check_pages(tr1);
- check_pages(tr2);
- list_splice_init(&tr1->trace_pages, &flip_pages);
- list_splice_init(&tr2->trace_pages, &tr1->trace_pages);
- list_splice_init(&flip_pages, &tr2->trace_pages);
- BUG_ON(!list_empty(&flip_pages));
- check_pages(tr1);
- check_pages(tr2);
-}
-
/**
* update_max_tr - snapshot all trace buffers from global_trace to max_tr
* @tr: tracer
@@ -500,18 +258,9 @@ flip_trace(struct trace_array_cpu *tr1,
void
update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
{
- struct trace_array_cpu *data;
- int i;
-
WARN_ON_ONCE(!irqs_disabled());
__raw_spin_lock(&ftrace_max_lock);
- /* clear out all the previous traces */
- for_each_tracing_cpu(i) {
- data = tr->data[i];
- flip_trace(max_tr.data[i], data);
- tracing_reset(data);
- }
-
+ ring_buffer_snapshot(tr->buffer);
__update_max_tr(tr, tsk, cpu);
__raw_spin_unlock(&ftrace_max_lock);
}
@@ -527,21 +276,20 @@ update_max_tr(struct trace_array *tr, st
void
update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
{
- struct trace_array_cpu *data = tr->data[cpu];
- int i;
-
WARN_ON_ONCE(!irqs_disabled());
__raw_spin_lock(&ftrace_max_lock);
- for_each_tracing_cpu(i)
- tracing_reset(max_tr.data[i]);
-
- flip_trace(max_tr.data[cpu], data);
- tracing_reset(data);
-
+ ring_buffer_snapshot_one_cpu(tr->buffer, cpu);
__update_max_tr(tr, tsk, cpu);
__raw_spin_unlock(&ftrace_max_lock);
}
+#define CHECK_COND(cond) \
+ if (unlikely(cond)) { \
+ tracing_disabled = 1; \
+ WARN_ON(1); \
+ return -1; \
+ }
+
/**
* register_tracer - register a tracer with the ftrace system.
* @type - the plugin for the tracer
@@ -573,7 +321,6 @@ int register_tracer(struct tracer *type)
#ifdef CONFIG_FTRACE_STARTUP_TEST
if (type->selftest) {
struct tracer *saved_tracer = current_trace;
- struct trace_array_cpu *data;
struct trace_array *tr = &global_trace;
int saved_ctrl = tr->ctrl;
int i;
@@ -585,10 +332,7 @@ int register_tracer(struct tracer *type)
* If we fail, we do not register this tracer.
*/
for_each_tracing_cpu(i) {
- data = tr->data[i];
- if (!head_page(data))
- continue;
- tracing_reset(data);
+ tracing_reset(tr, i);
}
current_trace = type;
tr->ctrl = 0;
@@ -604,10 +348,7 @@ int register_tracer(struct tracer *type)
}
/* Only reset on passing, to avoid touching corrupted buffers */
for_each_tracing_cpu(i) {
- data = tr->data[i];
- if (!head_page(data))
- continue;
- tracing_reset(data);
+ tracing_reset(tr, i);
}
printk(KERN_CONT "PASSED\n");
}
@@ -653,13 +394,9 @@ void unregister_tracer(struct tracer *ty
mutex_unlock(&trace_types_lock);
}
-void tracing_reset(struct trace_array_cpu *data)
+void tracing_reset(struct trace_array *tr, int cpu)
{
- data->trace_idx = 0;
- data->overrun = 0;
- data->trace_head = data->trace_tail = head_page(data);
- data->trace_head_idx = 0;
- data->trace_tail_idx = 0;
+ ring_buffer_reset_cpu(tr->buffer, cpu);
}
#define SAVED_CMDLINES 128
@@ -745,70 +482,6 @@ void tracing_record_cmdline(struct task_
trace_save_cmdline(tsk);
}
-static inline struct list_head *
-trace_next_list(struct trace_array_cpu *data, struct list_head *next)
-{
- /*
- * Roundrobin - but skip the head (which is not a real page):
- */
- next = next->next;
- if (unlikely(next == &data->trace_pages))
- next = next->next;
- BUG_ON(next == &data->trace_pages);
-
- return next;
-}
-
-static inline void *
-trace_next_page(struct trace_array_cpu *data, void *addr)
-{
- struct list_head *next;
- struct page *page;
-
- page = virt_to_page(addr);
-
- next = trace_next_list(data, &page->lru);
- page = list_entry(next, struct page, lru);
-
- return page_address(page);
-}
-
-static inline struct trace_entry *
-tracing_get_trace_entry(struct trace_array *tr, struct trace_array_cpu *data)
-{
- unsigned long idx, idx_next;
- struct trace_entry *entry;
-
- data->trace_idx++;
- idx = data->trace_head_idx;
- idx_next = idx + 1;
-
- BUG_ON(idx * TRACE_ENTRY_SIZE >= PAGE_SIZE);
-
- entry = data->trace_head + idx * TRACE_ENTRY_SIZE;
-
- if (unlikely(idx_next >= ENTRIES_PER_PAGE)) {
- data->trace_head = trace_next_page(data, data->trace_head);
- idx_next = 0;
- }
-
- if (data->trace_head == data->trace_tail &&
- idx_next == data->trace_tail_idx) {
- /* overrun */
- data->overrun++;
- data->trace_tail_idx++;
- if (data->trace_tail_idx >= ENTRIES_PER_PAGE) {
- data->trace_tail =
- trace_next_page(data, data->trace_tail);
- data->trace_tail_idx = 0;
- }
- }
-
- data->trace_head_idx = idx_next;
-
- return entry;
-}
-
static inline void
tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags)
{
@@ -819,7 +492,6 @@ tracing_generic_entry_update(struct trac
entry->preempt_count = pc & 0xff;
entry->pid = (tsk) ? tsk->pid : 0;
- entry->t = ftrace_now(raw_smp_processor_id());
entry->flags = (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) |
((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
@@ -830,18 +502,17 @@ void
trace_function(struct trace_array *tr, struct trace_array_cpu *data,
unsigned long ip, unsigned long parent_ip, unsigned long flags)
{
- struct trace_entry *entry;
+ struct ftrace_entry *entry;
unsigned long irq_flags;
- raw_local_irq_save(irq_flags);
- __raw_spin_lock(&data->lock);
- entry = tracing_get_trace_entry(tr, data);
- tracing_generic_entry_update(entry, flags);
- entry->type = TRACE_FN;
- entry->fn.ip = ip;
- entry->fn.parent_ip = parent_ip;
- __raw_spin_unlock(&data->lock);
- raw_local_irq_restore(irq_flags);
+ entry = ring_buffer_lock_reserve(tr->buffer, TRACE_FN, sizeof(*entry),
+ &irq_flags);
+ if (!entry)
+ return;
+ tracing_generic_entry_update(&entry->ent, flags);
+ entry->ip = ip;
+ entry->parent_ip = parent_ip;
+ ring_buffer_unlock_commit(tr->buffer, entry, irq_flags);
}
void
@@ -856,19 +527,16 @@ ftrace(struct trace_array *tr, struct tr
void __trace_mmiotrace_rw(struct trace_array *tr, struct trace_array_cpu *data,
struct mmiotrace_rw *rw)
{
- struct trace_entry *entry;
+ struct mmiotrace_rw *entry;
unsigned long irq_flags;
- raw_local_irq_save(irq_flags);
- __raw_spin_lock(&data->lock);
-
- entry = tracing_get_trace_entry(tr, data);
- tracing_generic_entry_update(entry, 0);
- entry->type = TRACE_MMIO_RW;
- entry->mmiorw = *rw;
-
- __raw_spin_unlock(&data->lock);
- raw_local_irq_restore(irq_flags);
+ entry = ring_buffer_lock_reserve(tr->buffer, TRACE_MMIO_RW,
+ sizeof(*entry), &irq_flags);
+ if (!entry)
+ return;
+ tracing_generic_entry_update(&entry->ent, 0);
+ *entry = *rw;
+ ring_buffer_unlock_commit(tr->buffer, entry, irq_flags);
trace_wake_up();
}
@@ -876,19 +544,16 @@ void __trace_mmiotrace_rw(struct trace_a
void __trace_mmiotrace_map(struct trace_array *tr, struct trace_array_cpu *data,
struct mmiotrace_map *map)
{
- struct trace_entry *entry;
+ struct mmiotrace_map *entry;
unsigned long irq_flags;
- raw_local_irq_save(irq_flags);
- __raw_spin_lock(&data->lock);
-
- entry = tracing_get_trace_entry(tr, data);
- tracing_generic_entry_update(entry, 0);
- entry->type = TRACE_MMIO_MAP;
- entry->mmiomap = *map;
-
- __raw_spin_unlock(&data->lock);
- raw_local_irq_restore(irq_flags);
+ entry = ring_buffer_lock_reserve(tr->buffer, TRACE_MMIO_MAP,
+ sizeof(*entry), &irq_flags);
+ if (!entry)
+ return;
+ tracing_generic_entry_update(&entry->ent, 0);
+ *entry = *map;
+ ring_buffer_unlock_commit(tr->buffer, entry, irq_flags);
trace_wake_up();
}
@@ -899,24 +564,28 @@ void __trace_stack(struct trace_array *t
unsigned long flags,
int skip)
{
- struct trace_entry *entry;
+ struct stack_entry *entry;
struct stack_trace trace;
+ unsigned long irq_flags;
if (!(trace_flags & TRACE_ITER_STACKTRACE))
return;
- entry = tracing_get_trace_entry(tr, data);
- tracing_generic_entry_update(entry, flags);
- entry->type = TRACE_STACK;
+ entry = ring_buffer_lock_reserve(tr->buffer, FTRACE_STACK_ENTRIES,
+ sizeof(*entry), &irq_flags);
+ if (!entry)
+ return;
+ tracing_generic_entry_update(&entry->ent, flags);
- memset(&entry->stack, 0, sizeof(entry->stack));
+ memset(&entry->caller, 0, sizeof(entry->caller));
trace.nr_entries = 0;
trace.max_entries = FTRACE_STACK_ENTRIES;
trace.skip = skip;
- trace.entries = entry->stack.caller;
+ trace.entries = entry->caller;
save_stack_trace(&trace);
+ ring_buffer_unlock_commit(tr->buffer, entry, irq_flags);
}
void
@@ -925,20 +594,19 @@ __trace_special(void *__tr, void *__data
{
struct trace_array_cpu *data = __data;
struct trace_array *tr = __tr;
- struct trace_entry *entry;
+ struct special_entry *entry;
unsigned long irq_flags;
- raw_local_irq_save(irq_flags);
- __raw_spin_lock(&data->lock);
- entry = tracing_get_trace_entry(tr, data);
- tracing_generic_entry_update(entry, 0);
- entry->type = TRACE_SPECIAL;
- entry->special.arg1 = arg1;
- entry->special.arg2 = arg2;
- entry->special.arg3 = arg3;
+ entry = ring_buffer_lock_reserve(tr->buffer, TRACE_SPECIAL,
+ sizeof(*entry), &irq_flags);
+ if (!entry)
+ return;
+ tracing_generic_entry_update(&entry->ent, 0);
+ entry->arg1 = arg1;
+ entry->arg2 = arg2;
+ entry->arg3 = arg3;
+ ring_buffer_unlock_commit(tr->buffer, entry, irq_flags);
__trace_stack(tr, data, irq_flags, 4);
- __raw_spin_unlock(&data->lock);
- raw_local_irq_restore(irq_flags);
trace_wake_up();
}
@@ -950,23 +618,22 @@ tracing_sched_switch_trace(struct trace_
struct task_struct *next,
unsigned long flags)
{
- struct trace_entry *entry;
+ struct ctx_switch_entry *entry;
unsigned long irq_flags;
- raw_local_irq_save(irq_flags);
- __raw_spin_lock(&data->lock);
- entry = tracing_get_trace_entry(tr, data);
- tracing_generic_entry_update(entry, flags);
- entry->type = TRACE_CTX;
- entry->ctx.prev_pid = prev->pid;
- entry->ctx.prev_prio = prev->prio;
- entry->ctx.prev_state = prev->state;
- entry->ctx.next_pid = next->pid;
- entry->ctx.next_prio = next->prio;
- entry->ctx.next_state = next->state;
+ entry = ring_buffer_lock_reserve(tr->buffer, TRACE_CTX,
+ sizeof(*entry), &irq_flags);
+ if (!entry)
+ return;
+ tracing_generic_entry_update(&entry->ent, flags);
+ entry->prev_pid = prev->pid;
+ entry->prev_prio = prev->prio;
+ entry->prev_state = prev->state;
+ entry->next_pid = next->pid;
+ entry->next_prio = next->prio;
+ entry->next_state = next->state;
+ ring_buffer_unlock_commit(tr->buffer, entry, irq_flags);
__trace_stack(tr, data, flags, 5);
- __raw_spin_unlock(&data->lock);
- raw_local_irq_restore(irq_flags);
}
void
@@ -976,23 +643,22 @@ tracing_sched_wakeup_trace(struct trace_
struct task_struct *curr,
unsigned long flags)
{
- struct trace_entry *entry;
+ struct ctx_switch_entry *entry;
unsigned long irq_flags;
- raw_local_irq_save(irq_flags);
- __raw_spin_lock(&data->lock);
- entry = tracing_get_trace_entry(tr, data);
- tracing_generic_entry_update(entry, flags);
- entry->type = TRACE_WAKE;
- entry->ctx.prev_pid = curr->pid;
- entry->ctx.prev_prio = curr->prio;
- entry->ctx.prev_state = curr->state;
- entry->ctx.next_pid = wakee->pid;
- entry->ctx.next_prio = wakee->prio;
- entry->ctx.next_state = wakee->state;
+ entry = ring_buffer_lock_reserve(tr->buffer, TRACE_WAKE,
+ sizeof(*entry), &irq_flags);
+ if (!entry)
+ return;
+ tracing_generic_entry_update(&entry->ent, flags);
+ entry->prev_pid = curr->pid;
+ entry->prev_prio = curr->prio;
+ entry->prev_state = curr->state;
+ entry->next_pid = wakee->pid;
+ entry->next_prio = wakee->prio;
+ entry->next_state = wakee->state;
+ ring_buffer_unlock_commit(tr->buffer, entry, irq_flags);
__trace_stack(tr, data, flags, 6);
- __raw_spin_unlock(&data->lock);
- raw_local_irq_restore(irq_flags);
trace_wake_up();
}
@@ -1070,112 +736,21 @@ void tracing_stop_function_trace(void)
#endif
enum trace_file_type {
- TRACE_FILE_LAT_FMT = 1,
+ TRACE_FILE_LAT_FMT = 1 << 0,
+ TRACE_FILE_USE_MAX = 1 << 1,
};
-static struct trace_entry *
-trace_entry_idx(struct trace_array *tr, struct trace_array_cpu *data,
- struct trace_iterator *iter, int cpu)
-{
- struct page *page;
- struct trace_entry *array;
-
- if (iter->next_idx[cpu] >= tr->entries ||
- iter->next_idx[cpu] >= data->trace_idx ||
- (data->trace_head == data->trace_tail &&
- data->trace_head_idx == data->trace_tail_idx))
- return NULL;
-
- if (!iter->next_page[cpu]) {
- /* Initialize the iterator for this cpu trace buffer */
- WARN_ON(!data->trace_tail);
- page = virt_to_page(data->trace_tail);
- iter->next_page[cpu] = &page->lru;
- iter->next_page_idx[cpu] = data->trace_tail_idx;
- }
-
- page = list_entry(iter->next_page[cpu], struct page, lru);
- BUG_ON(&data->trace_pages == &page->lru);
-
- array = page_address(page);
-
- WARN_ON(iter->next_page_idx[cpu] >= ENTRIES_PER_PAGE);
- return &array[iter->next_page_idx[cpu]];
-}
-
-static struct trace_entry *
-find_next_entry(struct trace_iterator *iter, int *ent_cpu)
-{
- struct trace_array *tr = iter->tr;
- struct trace_entry *ent, *next = NULL;
- int next_cpu = -1;
- int cpu;
-
- for_each_tracing_cpu(cpu) {
- if (!head_page(tr->data[cpu]))
- continue;
- ent = trace_entry_idx(tr, tr->data[cpu], iter, cpu);
- /*
- * Pick the entry with the smallest timestamp:
- */
- if (ent && (!next || ent->t < next->t)) {
- next = ent;
- next_cpu = cpu;
- }
- }
-
- if (ent_cpu)
- *ent_cpu = next_cpu;
-
- return next;
-}
-
-static void trace_iterator_increment(struct trace_iterator *iter)
-{
- iter->idx++;
- iter->next_idx[iter->cpu]++;
- iter->next_page_idx[iter->cpu]++;
-
- if (iter->next_page_idx[iter->cpu] >= ENTRIES_PER_PAGE) {
- struct trace_array_cpu *data = iter->tr->data[iter->cpu];
-
- iter->next_page_idx[iter->cpu] = 0;
- iter->next_page[iter->cpu] =
- trace_next_list(data, iter->next_page[iter->cpu]);
- }
-}
-
-static void trace_consume(struct trace_iterator *iter)
-{
- struct trace_array_cpu *data = iter->tr->data[iter->cpu];
-
- data->trace_tail_idx++;
- if (data->trace_tail_idx >= ENTRIES_PER_PAGE) {
- data->trace_tail = trace_next_page(data, data->trace_tail);
- data->trace_tail_idx = 0;
- }
-
- /* Check if we empty it, then reset the index */
- if (data->trace_head == data->trace_tail &&
- data->trace_head_idx == data->trace_tail_idx)
- data->trace_idx = 0;
-}
-
static void *find_next_entry_inc(struct trace_iterator *iter)
{
- struct trace_entry *next;
+ struct ring_buffer_event *next;
int next_cpu = -1;
- next = find_next_entry(iter, &next_cpu);
-
- iter->prev_ent = iter->ent;
- iter->prev_cpu = iter->cpu;
-
- iter->ent = next;
+ next = ring_buffer_read(iter->buffer_iter, &next_cpu);
+ iter->event = next;
iter->cpu = next_cpu;
if (next)
- trace_iterator_increment(iter);
+ iter->idx++;
return next ? iter : NULL;
}
@@ -1210,7 +785,6 @@ static void *s_start(struct seq_file *m,
struct trace_iterator *iter = m->private;
void *p = NULL;
loff_t l = 0;
- int i;
mutex_lock(&trace_types_lock);
@@ -1226,16 +800,9 @@ static void *s_start(struct seq_file *m,
current_trace->start(iter);
if (*pos != iter->pos) {
- iter->ent = NULL;
+ iter->event = NULL;
iter->cpu = 0;
iter->idx = -1;
- iter->prev_ent = NULL;
- iter->prev_cpu = -1;
-
- for_each_tracing_cpu(i) {
- iter->next_idx[i] = 0;
- iter->next_page[i] = NULL;
- }
for (p = iter; p && l < *pos; p = s_next(m, p, &l))
;
@@ -1276,27 +843,27 @@ static inline int kretprobed(unsigned lo
#endif /* CONFIG_KRETPROBES */
static int
-seq_print_sym_short(struct trace_seq *s, const char *fmt, unsigned long address)
+seq_print_sym_short(struct ring_buffer_seq *s, const char *fmt, unsigned long address)
{
#ifdef CONFIG_KALLSYMS
char str[KSYM_SYMBOL_LEN];
kallsyms_lookup(address, NULL, NULL, NULL, str);
- return trace_seq_printf(s, fmt, str);
+ return ring_buffer_seq_printf(s, fmt, str);
#endif
return 1;
}
static int
-seq_print_sym_offset(struct trace_seq *s, const char *fmt,
+seq_print_sym_offset(struct ring_buffer_seq *s, const char *fmt,
unsigned long address)
{
#ifdef CONFIG_KALLSYMS
char str[KSYM_SYMBOL_LEN];
sprint_symbol(str, address);
- return trace_seq_printf(s, fmt, str);
+ return ring_buffer_seq_printf(s, fmt, str);
#endif
return 1;
}
@@ -1308,12 +875,12 @@ seq_print_sym_offset(struct trace_seq *s
#endif
static int
-seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
+seq_print_ip_sym(struct ring_buffer_seq *s, unsigned long ip, unsigned long sym_flags)
{
int ret;
if (!ip)
- return trace_seq_printf(s, "0");
+ return ring_buffer_seq_printf(s, "0");
if (sym_flags & TRACE_ITER_SYM_OFFSET)
ret = seq_print_sym_offset(s, "%s", ip);
@@ -1324,7 +891,7 @@ seq_print_ip_sym(struct trace_seq *s, un
return 0;
if (sym_flags & TRACE_ITER_SYM_ADDR)
- ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
+ ret = ring_buffer_seq_printf(s, " <" IP_FMT ">", ip);
return ret;
}
@@ -1357,21 +924,12 @@ print_trace_header(struct seq_file *m, s
struct tracer *type = current_trace;
unsigned long total = 0;
unsigned long entries = 0;
- int cpu;
const char *name = "preemption";
if (type)
name = type->name;
- for_each_tracing_cpu(cpu) {
- if (head_page(tr->data[cpu])) {
- total += tr->data[cpu]->trace_idx;
- if (tr->data[cpu]->trace_idx > tr->entries)
- entries += tr->entries;
- else
- entries += tr->data[cpu]->trace_idx;
- }
- }
+ entries = ring_buffer_entries(iter->tr->buffer);
seq_printf(m, "%s latency trace v1.1.5 on %s\n",
name, UTS_RELEASE);
@@ -1379,7 +937,7 @@ print_trace_header(struct seq_file *m, s
"---------------------------------\n");
seq_printf(m, " latency: %lu us, #%lu/%lu, CPU#%d |"
" (M:%s VP:%d, KP:%d, SP:%d HP:%d",
- nsecs_to_usecs(data->saved_latency),
+ nsecs_to_usecs(tr->saved_latency),
entries,
total,
tr->cpu,
@@ -1402,17 +960,17 @@ print_trace_header(struct seq_file *m, s
seq_puts(m, " -----------------\n");
seq_printf(m, " | task: %.16s-%d "
"(uid:%d nice:%ld policy:%ld rt_prio:%ld)\n",
- data->comm, data->pid, data->uid, data->nice,
- data->policy, data->rt_priority);
+ tr->comm, tr->pid, tr->uid, tr->nice,
+ tr->policy, tr->rt_priority);
seq_puts(m, " -----------------\n");
if (data->critical_start) {
seq_puts(m, " => started at: ");
- seq_print_ip_sym(&iter->seq, data->critical_start, sym_flags);
- trace_print_seq(m, &iter->seq);
+ seq_print_ip_sym(iter->seq, data->critical_start, sym_flags);
+ ring_buffer_seq_to_seqfile(m, iter->seq);
seq_puts(m, "\n => ended at: ");
- seq_print_ip_sym(&iter->seq, data->critical_end, sym_flags);
- trace_print_seq(m, &iter->seq);
+ seq_print_ip_sym(iter->seq, data->critical_end, sym_flags);
+ ring_buffer_seq_to_seqfile(m, iter->seq);
seq_puts(m, "\n");
}
@@ -1420,71 +978,71 @@ print_trace_header(struct seq_file *m, s
}
static void
-lat_print_generic(struct trace_seq *s, struct trace_entry *entry, int cpu)
+lat_print_generic(struct ring_buffer_seq *s, struct trace_entry *entry, int cpu)
{
int hardirq, softirq;
char *comm;
comm = trace_find_cmdline(entry->pid);
- trace_seq_printf(s, "%8.8s-%-5d ", comm, entry->pid);
- trace_seq_printf(s, "%d", cpu);
- trace_seq_printf(s, "%c%c",
+ ring_buffer_seq_printf(s, "%8.8s-%-5d ", comm, entry->pid);
+ ring_buffer_seq_printf(s, "%d", cpu);
+ ring_buffer_seq_printf(s, "%c%c",
(entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : '.',
((entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.'));
hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
if (hardirq && softirq) {
- trace_seq_putc(s, 'H');
+ ring_buffer_seq_putc(s, 'H');
} else {
if (hardirq) {
- trace_seq_putc(s, 'h');
+ ring_buffer_seq_putc(s, 'h');
} else {
if (softirq)
- trace_seq_putc(s, 's');
+ ring_buffer_seq_putc(s, 's');
else
- trace_seq_putc(s, '.');
+ ring_buffer_seq_putc(s, '.');
}
}
if (entry->preempt_count)
- trace_seq_printf(s, "%x", entry->preempt_count);
+ ring_buffer_seq_printf(s, "%x", entry->preempt_count);
else
- trace_seq_puts(s, ".");
+ ring_buffer_seq_puts(s, ".");
}
unsigned long preempt_mark_thresh = 100;
static void
-lat_print_timestamp(struct trace_seq *s, unsigned long long abs_usecs,
+lat_print_timestamp(struct ring_buffer_seq *s, unsigned long long abs_usecs,
unsigned long rel_usecs)
{
- trace_seq_printf(s, " %4lldus", abs_usecs);
+ ring_buffer_seq_printf(s, " %4lldus", abs_usecs);
if (rel_usecs > preempt_mark_thresh)
- trace_seq_puts(s, "!: ");
+ ring_buffer_seq_puts(s, "!: ");
else if (rel_usecs > 1)
- trace_seq_puts(s, "+: ");
+ ring_buffer_seq_puts(s, "+: ");
else
- trace_seq_puts(s, " : ");
+ ring_buffer_seq_puts(s, " : ");
}
static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
#define SEQ_PUT_FIELD_RET(s, x) \
do { \
- if (!trace_seq_putmem(s, &(x), sizeof(x))) \
+ if (!ring_buffer_seq_putmem(s, &(x), sizeof(x))) \
return 0; \
} while (0)
#define SEQ_PUT_HEX_FIELD_RET(s, x) \
do { \
- if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \
+ if (!ring_buffer_seq_putmem_hex(s, &(x), sizeof(x))) \
return 0; \
} while (0)
static int
-trace_print_func(struct trace_seq *s, struct ftrace_entry *entry,
+trace_print_func(struct ring_buffer_seq *s, struct ftrace_entry *entry,
int sym_flags, int print_type)
{
int ret = 1;
@@ -1499,17 +1057,17 @@ trace_print_func(struct trace_seq *s, st
SEQ_PUT_HEX_FIELD_RET(s, entry->parent_ip);
break;
case TRACE_ITER_RAW:
- ret = trace_seq_printf(s, "%x %x\n",
+ ret = ring_buffer_seq_printf(s, "%lx %lx\n",
entry->ip, entry->parent_ip);
break;
case TRACE_FILE_LAT_FMT:
seq_print_ip_sym(s, entry->ip, sym_flags);
- trace_seq_puts(s, " (");
+ ring_buffer_seq_puts(s, " (");
if (kretprobed(entry->parent_ip))
- trace_seq_puts(s, KRETPROBE_MSG);
+ ring_buffer_seq_puts(s, KRETPROBE_MSG);
else
seq_print_ip_sym(s, entry->parent_ip, sym_flags);
- trace_seq_puts(s, ")\n");
+ ring_buffer_seq_puts(s, ")\n");
break;
default:
ret = seq_print_ip_sym(s, entry->ip, sym_flags);
@@ -1517,25 +1075,25 @@ trace_print_func(struct trace_seq *s, st
return 0;
if ((sym_flags & TRACE_ITER_PRINT_PARENT) &&
entry->parent_ip) {
- ret = trace_seq_printf(s, " <-");
+ ret = ring_buffer_seq_printf(s, " <-");
if (!ret)
return 0;
if (kretprobed(entry->parent_ip))
- ret = trace_seq_puts(s, KRETPROBE_MSG);
+ ret = ring_buffer_seq_puts(s, KRETPROBE_MSG);
else
ret = seq_print_ip_sym(s, entry->parent_ip,
sym_flags);
if (!ret)
return 0;
}
- ret = trace_seq_printf(s, "\n");
+ ret = ring_buffer_seq_printf(s, "\n");
}
return ret;
}
static int
-trace_print_ctx(struct trace_seq *s, struct ctx_switch_entry *entry,
+trace_print_ctx(struct ring_buffer_seq *s, struct ctx_switch_entry *entry,
int type, int print_type)
{
unsigned state;
@@ -1571,7 +1129,7 @@ trace_print_ctx(struct trace_seq *s, str
case TRACE_ITER_RAW:
if (type == TRACE_WAKE)
S = '+';
- ret = trace_seq_printf(s, "%d %d %c %d %d %c\n",
+ ret = ring_buffer_seq_printf(s, "%d %d %c %d %d %c\n",
entry->prev_pid,
entry->prev_prio,
S,
@@ -1581,7 +1139,7 @@ trace_print_ctx(struct trace_seq *s, str
break;
default:
comm = trace_find_cmdline(entry->next_pid);
- ret = trace_seq_printf(s, " %5d:%3d:%c %s %5d:%3d:%c %s\n",
+ ret = ring_buffer_seq_printf(s, " %5d:%3d:%c %s %5d:%3d:%c %s\n",
entry->prev_pid,
entry->prev_prio,
S, type == TRACE_CTX ? "==>" : " +",
@@ -1594,7 +1152,7 @@ trace_print_ctx(struct trace_seq *s, str
}
static int
-trace_print_special(struct trace_seq *s, struct special_entry *entry,
+trace_print_special(struct ring_buffer_seq *s, struct special_entry *entry,
int print_type)
{
int ret = 0;
@@ -1612,7 +1170,7 @@ trace_print_special(struct trace_seq *s,
break;
case TRACE_ITER_RAW:
default:
- ret = trace_seq_printf(s, "# %ld %ld %ld\n",
+ ret = ring_buffer_seq_printf(s, "# %ld %ld %ld\n",
entry->arg1,
entry->arg2,
entry->arg3);
@@ -1621,7 +1179,7 @@ trace_print_special(struct trace_seq *s,
}
static int
-trace_print_stack(struct trace_seq *s, struct stack_entry *entry, int sym_flags,
+trace_print_stack(struct ring_buffer_seq *s, struct stack_entry *entry, int sym_flags,
int print_type)
{
int i;
@@ -1634,7 +1192,7 @@ trace_print_stack(struct trace_seq *s, s
default:
for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
if (i) {
- ret = trace_seq_puts(s, " <= ");
+ ret = ring_buffer_seq_puts(s, " <= ");
if (!ret)
return 0;
}
@@ -1643,7 +1201,7 @@ trace_print_stack(struct trace_seq *s, s
if (!ret)
return 0;
}
- ret = trace_seq_puts(s, "\n");
+ ret = ring_buffer_seq_puts(s, "\n");
}
return ret;
@@ -1652,29 +1210,35 @@ trace_print_stack(struct trace_seq *s, s
static int
print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
{
- struct trace_seq *s = &iter->seq;
+ struct ring_buffer_seq *s = iter->seq;
unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
- struct trace_entry *next_entry = find_next_entry(iter, NULL);
+ struct ring_buffer_event *next_event = ring_buffer_peek(iter->buffer_iter, NULL);
unsigned long verbose = (trace_flags & TRACE_ITER_VERBOSE);
- struct trace_entry *entry = iter->ent;
+ struct trace_entry *entry = ring_buffer_event_data(iter->event);
+ unsigned long long ns1, ns2;
unsigned long abs_usecs;
unsigned long rel_usecs;
char *comm;
int print_type = TRACE_FILE_LAT_FMT;
+ int type;
+
+ if (!next_event)
+ next_event = iter->event;
+ ns1 = ring_buffer_event_counter(iter->event);
+ ns2 = ring_buffer_event_counter(next_event);
+ rel_usecs = ns2usecs(ns2 - ns1);
+ abs_usecs = ns2usecs(ns1 - iter->tr->time_start);
- if (!next_entry)
- next_entry = entry;
- rel_usecs = ns2usecs(next_entry->t - entry->t);
- abs_usecs = ns2usecs(entry->t - iter->tr->time_start);
+ type = ring_buffer_event_type(iter->event);
if (verbose) {
comm = trace_find_cmdline(entry->pid);
- trace_seq_printf(s, "%16s %5d %d %d %08x %08x [%08lx]"
+ ring_buffer_seq_printf(s, "%16s %5d %d %d %08x %08x [%08lx]"
" %ld.%03ldms (+%ld.%03ldms): ",
comm,
entry->pid, cpu, entry->flags,
entry->preempt_count, trace_idx,
- ns2usecs(entry->t),
+ ns2usecs(ns1),
abs_usecs/1000,
abs_usecs % 1000, rel_usecs/1000,
rel_usecs % 1000);
@@ -1682,74 +1246,77 @@ print_lat_fmt(struct trace_iterator *ite
lat_print_generic(s, entry, cpu);
lat_print_timestamp(s, abs_usecs, rel_usecs);
}
- switch (entry->type) {
+ switch (type) {
case TRACE_FN:
- trace_print_func(s, &entry->fn, sym_flags, print_type);
+ trace_print_func(s, (struct ftrace_entry *)entry, sym_flags, print_type);
break;
case TRACE_CTX:
case TRACE_WAKE:
- trace_print_ctx(s, &entry->ctx, entry->type, print_type);
+ trace_print_ctx(s, (struct ctx_switch_entry *)entry, type, print_type);
break;
case TRACE_SPECIAL:
- trace_print_special(s, &entry->special, print_type);
+ trace_print_special(s, (struct special_entry *)entry, print_type);
break;
case TRACE_STACK:
- trace_print_stack(s, &entry->stack, sym_flags, print_type);
+ trace_print_stack(s, (struct stack_entry *)entry, sym_flags, print_type);
break;
default:
- trace_seq_printf(s, "Unknown type %d\n", entry->type);
+ ring_buffer_seq_printf(s, "Unknown type %d\n", type);
}
return 1;
}
static int print_trace_fmt(struct trace_iterator *iter)
{
- struct trace_seq *s = &iter->seq;
+ struct ring_buffer_seq *s = iter->seq;
unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
struct trace_entry *entry;
unsigned long usec_rem;
- unsigned long long t;
+ unsigned long long t, ns;
unsigned long secs;
char *comm;
+ int type;
int ret;
- entry = iter->ent;
+ entry = ring_buffer_event_data(iter->event);
+ type = ring_buffer_event_type(iter->event);
+ ns = ring_buffer_event_counter(iter->event);
- comm = trace_find_cmdline(iter->ent->pid);
+ comm = trace_find_cmdline(entry->pid);
- t = ns2usecs(entry->t);
+ t = ns2usecs(ns);
usec_rem = do_div(t, 1000000ULL);
secs = (unsigned long)t;
- ret = trace_seq_printf(s, "%16s-%-5d ", comm, entry->pid);
+ ret = ring_buffer_seq_printf(s, "%16s-%-5d ", comm, entry->pid);
if (!ret)
return 0;
- ret = trace_seq_printf(s, "[%02d] ", iter->cpu);
+ ret = ring_buffer_seq_printf(s, "[%02d] ", iter->cpu);
if (!ret)
return 0;
- ret = trace_seq_printf(s, "%5lu.%06lu: ", secs, usec_rem);
+ ret = ring_buffer_seq_printf(s, "%5lu.%06lu: ", secs, usec_rem);
if (!ret)
return 0;
- switch (entry->type) {
+ switch (type) {
case TRACE_FN:
- ret = trace_print_func(s, &entry->fn, sym_flags, 0);
+ ret = trace_print_func(s, (struct ftrace_entry *)entry, sym_flags, 0);
if (!ret)
return 0;
break;
case TRACE_CTX:
case TRACE_WAKE:
- ret = trace_print_ctx(s, &entry->ctx, entry->type, 0);
+ ret = trace_print_ctx(s, (struct ctx_switch_entry *)entry, type, 0);
if (!ret)
return 0;
break;
case TRACE_SPECIAL:
- ret = trace_print_special(s, &entry->special, 0);
+ ret = trace_print_special(s, (struct special_entry *)entry, 0);
if (!ret)
return 0;
break;
case TRACE_STACK:
- ret = trace_print_stack(s, &entry->stack, sym_flags, 0);
+ ret = trace_print_stack(s, (struct stack_entry *)entry, sym_flags, 0);
if (!ret)
return 0;
break;
@@ -1759,33 +1326,37 @@ static int print_trace_fmt(struct trace_
static int print_raw_fmt(struct trace_iterator *iter)
{
- struct trace_seq *s = &iter->seq;
+ struct ring_buffer_seq *s = iter->seq;
struct trace_entry *entry;
+ unsigned long long t;
+ int type;
int print_type = TRACE_ITER_RAW;
int ret;
- entry = iter->ent;
+ entry = ring_buffer_event_data(iter->event);
+ type = ring_buffer_event_type(iter->event);
+ t = ring_buffer_event_counter(iter->event);
- ret = trace_seq_printf(s, "%d %d %llu ",
- entry->pid, iter->cpu, entry->t);
+ ret = ring_buffer_seq_printf(s, "%d %d %llu ",
+ entry->pid, iter->cpu, t);
if (!ret)
return 0;
- switch (entry->type) {
+ switch (type) {
case TRACE_FN:
- ret = trace_print_func(s, &entry->fn, 0, print_type);
+ ret = trace_print_func(s, (struct ftrace_entry *)entry, 0, print_type);
if (!ret)
return 0;
break;
case TRACE_CTX:
case TRACE_WAKE:
- ret = trace_print_ctx(s, &entry->ctx, entry->type, print_type);
+ ret = trace_print_ctx(s, (struct ctx_switch_entry *)entry, type, print_type);
if (!ret)
return 0;
break;
case TRACE_SPECIAL:
case TRACE_STACK:
- ret = trace_print_special(s, &entry->special, print_type);
+ ret = trace_print_special(s, (struct special_entry *)entry, print_type);
if (!ret)
return 0;
break;
@@ -1795,28 +1366,32 @@ static int print_raw_fmt(struct trace_it
static int print_hex_fmt(struct trace_iterator *iter)
{
- struct trace_seq *s = &iter->seq;
+ struct ring_buffer_seq *s = iter->seq;
unsigned char newline = '\n';
struct trace_entry *entry;
int print_type = TRACE_ITER_HEX;
+ unsigned long long t;
+ int type;
- entry = iter->ent;
+ entry = ring_buffer_event_data(iter->event);
+ type = ring_buffer_event_type(iter->event);
+ t = ring_buffer_event_counter(iter->event);
SEQ_PUT_HEX_FIELD_RET(s, entry->pid);
SEQ_PUT_HEX_FIELD_RET(s, iter->cpu);
- SEQ_PUT_HEX_FIELD_RET(s, entry->t);
+ SEQ_PUT_HEX_FIELD_RET(s, t);
- switch (entry->type) {
+ switch (type) {
case TRACE_FN:
- trace_print_func(s, &entry->fn, 0, print_type);
+ trace_print_func(s, (struct ftrace_entry *)entry, 0, print_type);
break;
case TRACE_CTX:
case TRACE_WAKE:
- trace_print_ctx(s, &entry->ctx, entry->type, print_type);
+ trace_print_ctx(s, (struct ctx_switch_entry *)entry, type, print_type);
break;
case TRACE_SPECIAL:
case TRACE_STACK:
- trace_print_special(s, &entry->special, print_type);
+ trace_print_special(s, (struct special_entry *)entry, print_type);
break;
}
SEQ_PUT_FIELD_RET(s, newline);
@@ -1826,26 +1401,30 @@ static int print_hex_fmt(struct trace_it
static int print_bin_fmt(struct trace_iterator *iter)
{
- struct trace_seq *s = &iter->seq;
+ struct ring_buffer_seq *s = iter->seq;
struct trace_entry *entry;
int print_type = TRACE_ITER_BIN;
+ unsigned long long t;
+ int type;
- entry = iter->ent;
+ entry = ring_buffer_event_data(iter->event);
+ type = ring_buffer_event_type(iter->event);
+ t = ring_buffer_event_counter(iter->event);
SEQ_PUT_FIELD_RET(s, entry->pid);
- SEQ_PUT_FIELD_RET(s, entry->cpu);
- SEQ_PUT_FIELD_RET(s, entry->t);
+ SEQ_PUT_FIELD_RET(s, iter->cpu);
+ SEQ_PUT_FIELD_RET(s, t);
- switch (entry->type) {
+ switch (type) {
case TRACE_FN:
- trace_print_func(s, &entry->fn, 0, print_type);
+ trace_print_func(s, (struct ftrace_entry *)entry, 0, print_type);
break;
case TRACE_CTX:
- trace_print_ctx(s, &entry->ctx, entry->type, print_type);
+ trace_print_ctx(s, (struct ctx_switch_entry *)entry, type, print_type);
break;
case TRACE_SPECIAL:
case TRACE_STACK:
- trace_print_special(s, &entry->special, print_type);
+ trace_print_special(s, (struct special_entry *)entry, print_type);
break;
}
return 1;
@@ -1853,18 +1432,7 @@ static int print_bin_fmt(struct trace_it
static int trace_empty(struct trace_iterator *iter)
{
- struct trace_array_cpu *data;
- int cpu;
-
- for_each_tracing_cpu(cpu) {
- data = iter->tr->data[cpu];
-
- if (head_page(data) && data->trace_idx &&
- (data->trace_tail != data->trace_head ||
- data->trace_tail_idx != data->trace_head_idx))
- return 0;
- }
- return 1;
+ return ring_buffer_empty(iter->tr->buffer);
}
static int print_trace_line(struct trace_iterator *iter)
@@ -1891,7 +1459,7 @@ static int s_show(struct seq_file *m, vo
{
struct trace_iterator *iter = v;
- if (iter->ent == NULL) {
+ if (iter->event == NULL) {
if (iter->tr) {
seq_printf(m, "# tracer: %s\n", iter->trace->name);
seq_puts(m, "#\n");
@@ -1909,7 +1477,7 @@ static int s_show(struct seq_file *m, vo
}
} else {
print_trace_line(iter);
- trace_print_seq(m, &iter->seq);
+ ring_buffer_seq_to_seqfile(m, iter->seq);
}
return 0;
@@ -1926,6 +1494,7 @@ static struct trace_iterator *
__tracing_open(struct inode *inode, struct file *file, int *ret)
{
struct trace_iterator *iter;
+ unsigned buf_flags = 0;
if (tracing_disabled) {
*ret = -ENODEV;
@@ -1938,11 +1507,32 @@ __tracing_open(struct inode *inode, stru
goto out;
}
+
+
mutex_lock(&trace_types_lock);
- if (current_trace && current_trace->print_max)
- iter->tr = &max_tr;
- else
- iter->tr = inode->i_private;
+
+ iter->tr = inode->i_private;
+
+ if (current_trace && current_trace->print_max) {
+ iter->iter_flags |= TRACE_FILE_USE_MAX;
+ buf_flags = RB_ITER_FL_SNAP;
+ }
+
+ iter->buffer_iter = ring_buffer_start(iter->tr->buffer, buf_flags);
+ if (!iter->buffer_iter) {
+ kfree(iter);
+ iter = NULL;
+ goto out_unlock;
+ }
+
+ iter->seq = ring_buffer_seq_alloc(GFP_KERNEL);
+ if (!iter->seq) {
+ ring_buffer_finish(iter->buffer_iter);
+ kfree(iter);
+ iter = NULL;
+ goto out_unlock;
+ }
+
iter->trace = current_trace;
iter->pos = -1;
@@ -1964,6 +1554,7 @@ __tracing_open(struct inode *inode, stru
kfree(iter);
iter = NULL;
}
+ out_unlock:
mutex_unlock(&trace_types_lock);
out:
@@ -1985,6 +1576,10 @@ int tracing_release(struct inode *inode,
struct trace_iterator *iter = m->private;
mutex_lock(&trace_types_lock);
+
+ ring_buffer_seq_free(iter->seq);
+ ring_buffer_finish(iter->buffer_iter);
+
if (iter->trace && iter->trace->close)
iter->trace->close(iter);
@@ -2491,6 +2086,7 @@ static atomic_t tracing_reader;
static int tracing_open_pipe(struct inode *inode, struct file *filp)
{
struct trace_iterator *iter;
+ int max_event_size;
if (tracing_disabled)
return -ENODEV;
@@ -2506,6 +2102,13 @@ static int tracing_open_pipe(struct inod
if (!iter)
return -ENOMEM;
+ max_event_size = ring_buffer_max_event_size(global_trace.buffer);
+ iter->last_event = kmalloc(max_event_size, GFP_KERNEL);
+ if (!iter->last_event) {
+ kfree(iter);
+ return -ENOMEM;
+ }
+
mutex_lock(&trace_types_lock);
iter->tr = &global_trace;
iter->trace = current_trace;
@@ -2522,6 +2125,7 @@ static int tracing_release_pipe(struct i
{
struct trace_iterator *iter = file->private_data;
+ kfree(iter->last_event);
kfree(iter);
atomic_dec(&tracing_reader);
@@ -2557,22 +2161,30 @@ tracing_read_pipe(struct file *filp, cha
size_t cnt, loff_t *ppos)
{
struct trace_iterator *iter = filp->private_data;
- struct trace_array_cpu *data;
- static cpumask_t mask;
+ struct ring_buffer_event *event;
unsigned long flags;
#ifdef CONFIG_FTRACE
int ftrace_save;
#endif
- int cpu;
+ static int save_event;
ssize_t sret;
/* return any leftover data */
- sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
+ sret = ring_buffer_seq_copy_to_user(iter->seq, ubuf, cnt);
if (sret != -EBUSY)
return sret;
sret = 0;
- trace_seq_reset(&iter->seq);
+ ring_buffer_seq_reset(iter->seq);
+
+ /* Check to see if we over flowed the iterator */
+ if (save_event) {
+ iter->event = iter->last_event;
+ print_trace_line(iter);
+ save_event = 0;
+ sret = ring_buffer_seq_copy_to_user(iter->seq, ubuf, cnt);
+ return sret;
+ }
mutex_lock(&trace_types_lock);
if (iter->trace->read) {
@@ -2652,68 +2264,40 @@ tracing_read_pipe(struct file *filp, cha
* and then release the locks again.
*/
- cpus_clear(mask);
- local_irq_save(flags);
#ifdef CONFIG_FTRACE
ftrace_save = ftrace_enabled;
ftrace_enabled = 0;
#endif
smp_wmb();
- for_each_tracing_cpu(cpu) {
- data = iter->tr->data[cpu];
-
- if (!head_page(data) || !data->trace_idx)
- continue;
+ ring_buffer_lock(iter->tr->buffer, &flags);
- atomic_inc(&data->disabled);
- cpu_set(cpu, mask);
- }
-
- for_each_cpu_mask(cpu, mask) {
- data = iter->tr->data[cpu];
- __raw_spin_lock(&data->lock);
-
- if (data->overrun > iter->last_overrun[cpu])
- iter->overrun[cpu] +=
- data->overrun - iter->last_overrun[cpu];
- iter->last_overrun[cpu] = data->overrun;
- }
-
- while (find_next_entry_inc(iter) != NULL) {
+ while ((event = ring_buffer_consume(iter->tr->buffer))) {
int ret;
- int len = iter->seq.len;
+ int len = ring_buffer_seq_length(iter->seq);
+ iter->event = event;
ret = print_trace_line(iter);
if (!ret) {
/* don't print partial lines */
- iter->seq.len = len;
+ ring_buffer_seq_set_length(iter->seq, len);
+ save_event = 1;
+ memcpy(iter->last_event, event,
+ ring_buffer_event_length(event));
break;
}
- trace_consume(iter);
-
- if (iter->seq.len >= cnt)
+ len = ring_buffer_seq_length(iter->seq);
+ if (len >= cnt)
break;
}
- for_each_cpu_mask(cpu, mask) {
- data = iter->tr->data[cpu];
- __raw_spin_unlock(&data->lock);
- }
-
- for_each_cpu_mask(cpu, mask) {
- data = iter->tr->data[cpu];
- atomic_dec(&data->disabled);
- }
#ifdef CONFIG_FTRACE
ftrace_enabled = ftrace_save;
#endif
- local_irq_restore(flags);
+ ring_buffer_unlock(iter->tr->buffer, flags);
/* Now copy what we have to the user */
- sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
- if (iter->seq.readpos >= iter->seq.len)
- trace_seq_reset(&iter->seq);
+ sret = ring_buffer_seq_copy_to_user(iter->seq, ubuf, cnt);
if (sret == -EBUSY)
sret = 0;
@@ -2731,17 +2315,28 @@ tracing_entries_read(struct file *filp,
char buf[64];
int r;
- r = sprintf(buf, "%lu\n", tr->entries);
+ r = sprintf(buf, "%lu\n", ring_buffer_size(tr->buffer));
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
}
+static void
+trace_default_print(struct ring_buffer *buffer,
+ struct ring_buffer_seq *seq,
+ struct ring_buffer_event *event)
+{
+ /* just some garbage for now */
+ ring_buffer_seq_printf(seq, "found %d\n",
+ ring_buffer_event_type(event));
+}
+
static ssize_t
tracing_entries_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
+ struct ring_buffer *buffer;
unsigned long val;
char buf[64];
- int i, ret;
+ int ret;
if (cnt >= sizeof(buf))
return -EINVAL;
@@ -2768,59 +2363,28 @@ tracing_entries_write(struct file *filp,
goto out;
}
- if (val > global_trace.entries) {
- long pages_requested;
- unsigned long freeable_pages;
-
- /* make sure we have enough memory before mapping */
- pages_requested =
- (val + (ENTRIES_PER_PAGE-1)) / ENTRIES_PER_PAGE;
-
- /* account for each buffer (and max_tr) */
- pages_requested *= tracing_nr_buffers * 2;
-
- /* Check for overflow */
- if (pages_requested < 0) {
- cnt = -ENOMEM;
- goto out;
- }
- freeable_pages = determine_dirtyable_memory();
+ if (val == ring_buffer_size(global_trace.buffer))
+ goto out_same;
- /* we only allow to request 1/4 of useable memory */
- if (pages_requested >
- ((freeable_pages + tracing_pages_allocated) / 4)) {
- cnt = -ENOMEM;
- goto out;
- }
-
- while (global_trace.entries < val) {
- if (trace_alloc_page()) {
- cnt = -ENOMEM;
- goto out;
- }
- /* double check that we don't go over the known pages */
- if (tracing_pages_allocated > pages_requested)
- break;
- }
-
- } else {
- /* include the number of entries in val (inc of page entries) */
- while (global_trace.entries > val + (ENTRIES_PER_PAGE - 1))
- trace_free_page();
+ buffer = ring_buffer_alloc(val,
+ TRACE_BUFFER_FLAGS, 0,
+ trace_default_print,
+ "ftrace_tmp");
+ if (!buffer) {
+ cnt = -ENOMEM;
+ goto out;
}
- /* check integrity */
- for_each_tracing_cpu(i)
- check_pages(global_trace.data[i]);
+ ring_buffer_free(global_trace.buffer);
+ ring_buffer_rename(buffer, FTRACE_BUF_NAME);
+ global_trace.buffer = buffer;
+
+ out_same:
filp->f_pos += cnt;
- /* If check pages failed, return ENOMEM */
- if (tracing_disabled)
- cnt = -ENOMEM;
out:
- max_tr.entries = global_trace.entries;
mutex_unlock(&trace_types_lock);
return cnt;
@@ -2883,17 +2447,23 @@ static struct dentry *d_tracer;
struct dentry *tracing_init_dentry(void)
{
static int once;
+ static DEFINE_MUTEX(mutex);
if (d_tracer)
return d_tracer;
+ mutex_lock(&mutex);
+ if (d_tracer)
+ goto out;
+
d_tracer = debugfs_create_dir("tracing", NULL);
if (!d_tracer && !once) {
once = 1;
pr_warning("Could not create debugfs directory 'tracing'\n");
- return NULL;
}
+ out:
+ mutex_unlock(&mutex);
return d_tracer;
}
@@ -2987,190 +2557,52 @@ static __init void tracer_init_debugfs(v
#endif
}
-static int trace_alloc_page(void)
+struct trace_array *
+trace_allocate_tracer(unsigned long size,
+ unsigned long flags,
+ unsigned long max_entry_size,
+ ring_buffer_print_func print_func,
+ char *name)
{
- struct trace_array_cpu *data;
- struct page *page, *tmp;
- LIST_HEAD(pages);
- void *array;
- unsigned pages_allocated = 0;
- int i;
-
- /* first allocate a page for each CPU */
- for_each_tracing_cpu(i) {
- array = (void *)__get_free_page(GFP_KERNEL);
- if (array == NULL) {
- printk(KERN_ERR "tracer: failed to allocate page"
- "for trace buffer!\n");
- goto free_pages;
- }
-
- pages_allocated++;
- page = virt_to_page(array);
- list_add(&page->lru, &pages);
-
-/* Only allocate if we are actually using the max trace */
-#ifdef CONFIG_TRACER_MAX_TRACE
- array = (void *)__get_free_page(GFP_KERNEL);
- if (array == NULL) {
- printk(KERN_ERR "tracer: failed to allocate page"
- "for trace buffer!\n");
- goto free_pages;
- }
- pages_allocated++;
- page = virt_to_page(array);
- list_add(&page->lru, &pages);
-#endif
- }
+ struct trace_array *tr;
- /* Now that we successfully allocate a page per CPU, add them */
- for_each_tracing_cpu(i) {
- data = global_trace.data[i];
- page = list_entry(pages.next, struct page, lru);
- list_del_init(&page->lru);
- list_add_tail(&page->lru, &data->trace_pages);
- ClearPageLRU(page);
-
-#ifdef CONFIG_TRACER_MAX_TRACE
- data = max_tr.data[i];
- page = list_entry(pages.next, struct page, lru);
- list_del_init(&page->lru);
- list_add_tail(&page->lru, &data->trace_pages);
- SetPageLRU(page);
-#endif
- }
- tracing_pages_allocated += pages_allocated;
- global_trace.entries += ENTRIES_PER_PAGE;
+ tr = kzalloc(ALIGN(sizeof(*tr), cache_line_size()), GFP_KERNEL);
+ if (!tr)
+ return NULL;
- return 0;
+ tr->buffer = ring_buffer_alloc(size, flags, max_entry_size,
+ print_func, name);
- free_pages:
- list_for_each_entry_safe(page, tmp, &pages, lru) {
- list_del_init(&page->lru);
- __free_page(page);
- }
- return -ENOMEM;
-}
+ if (!tr->buffer)
+ goto fail_free_trace;
-static int trace_free_page(void)
-{
- struct trace_array_cpu *data;
- struct page *page;
- struct list_head *p;
- int i;
- int ret = 0;
+ tr->ctrl = tracer_enabled;
- /* free one page from each buffer */
- for_each_tracing_cpu(i) {
- data = global_trace.data[i];
- p = data->trace_pages.next;
- if (p == &data->trace_pages) {
- /* should never happen */
- WARN_ON(1);
- tracing_disabled = 1;
- ret = -1;
- break;
- }
- page = list_entry(p, struct page, lru);
- ClearPageLRU(page);
- list_del(&page->lru);
- tracing_pages_allocated--;
- tracing_pages_allocated--;
- __free_page(page);
-
- tracing_reset(data);
-
-#ifdef CONFIG_TRACER_MAX_TRACE
- data = max_tr.data[i];
- p = data->trace_pages.next;
- if (p == &data->trace_pages) {
- /* should never happen */
- WARN_ON(1);
- tracing_disabled = 1;
- ret = -1;
- break;
- }
- page = list_entry(p, struct page, lru);
- ClearPageLRU(page);
- list_del(&page->lru);
- __free_page(page);
+ return tr;
- tracing_reset(data);
-#endif
- }
- global_trace.entries -= ENTRIES_PER_PAGE;
-
- return ret;
+ fail_free_trace:
+ kfree(tr);
+ return NULL;
}
__init static int tracer_alloc_buffers(void)
{
- struct trace_array_cpu *data;
- void *array;
- struct page *page;
- int pages = 0;
- int ret = -ENOMEM;
int i;
- /* TODO: make the number of buffers hot pluggable with CPUS */
- tracing_nr_buffers = num_possible_cpus();
tracing_buffer_mask = cpu_possible_map;
- /* Allocate the first page for all buffers */
- for_each_tracing_cpu(i) {
- data = global_trace.data[i] = &per_cpu(global_trace_cpu, i);
- max_tr.data[i] = &per_cpu(max_data, i);
-
- array = (void *)__get_free_page(GFP_KERNEL);
- if (array == NULL) {
- printk(KERN_ERR "tracer: failed to allocate page"
- "for trace buffer!\n");
- goto free_buffers;
- }
-
- /* set the array to the list */
- INIT_LIST_HEAD(&data->trace_pages);
- page = virt_to_page(array);
- list_add(&page->lru, &data->trace_pages);
- /* use the LRU flag to differentiate the two buffers */
- ClearPageLRU(page);
-
- data->lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
- max_tr.data[i]->lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
-
-/* Only allocate if we are actually using the max trace */
-#ifdef CONFIG_TRACER_MAX_TRACE
- array = (void *)__get_free_page(GFP_KERNEL);
- if (array == NULL) {
- printk(KERN_ERR "tracer: failed to allocate page"
- "for trace buffer!\n");
- goto free_buffers;
- }
-
- INIT_LIST_HEAD(&max_tr.data[i]->trace_pages);
- page = virt_to_page(array);
- list_add(&page->lru, &max_tr.data[i]->trace_pages);
- SetPageLRU(page);
-#endif
+ global_trace.buffer = ring_buffer_alloc(trace_buf_size,
+ TRACE_BUFFER_FLAGS, 0,
+ trace_default_print,
+ FTRACE_BUF_NAME);
+ if (!global_trace.buffer) {
+ printk(KERN_ERR "tracer: failed to allocate buffer\n");
+ return -ENOMEM;
}
- /*
- * Since we allocate by orders of pages, we may be able to
- * round up a bit.
- */
- global_trace.entries = ENTRIES_PER_PAGE;
- pages++;
-
- while (global_trace.entries < trace_nr_entries) {
- if (trace_alloc_page())
- break;
- pages++;
- }
- max_tr.entries = global_trace.entries;
+ for_each_tracing_cpu(i)
+ global_trace.data[i] = &per_cpu(global_trace_cpu, i);
- pr_info("tracer: %d pages allocated for %ld entries of %ld bytes\n",
- pages, trace_nr_entries, (long)TRACE_ENTRY_SIZE);
- pr_info(" actual entries %ld\n", global_trace.entries);
tracer_init_debugfs();
@@ -3184,31 +2616,5 @@ __init static int tracer_alloc_buffers(v
tracing_disabled = 0;
return 0;
-
- free_buffers:
- for (i-- ; i >= 0; i--) {
- struct page *page, *tmp;
- struct trace_array_cpu *data = global_trace.data[i];
-
- if (data) {
- list_for_each_entry_safe(page, tmp,
- &data->trace_pages, lru) {
- list_del_init(&page->lru);
- __free_page(page);
- }
- }
-
-#ifdef CONFIG_TRACER_MAX_TRACE
- data = max_tr.data[i];
- if (data) {
- list_for_each_entry_safe(page, tmp,
- &data->trace_pages, lru) {
- list_del_init(&page->lru);
- __free_page(page);
- }
- }
-#endif
- }
- return ret;
}
fs_initcall(tracer_alloc_buffers);
Index: linux-compile.git/kernel/trace/trace.h
===================================================================
--- linux-compile.git.orig/kernel/trace/trace.h 2008-09-23 23:33:29.000000000 -0400
+++ linux-compile.git/kernel/trace/trace.h 2008-09-23 23:34:46.000000000 -0400
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include <linux/clocksource.h>
#include <linux/mmiotrace.h>
+#include <linux/ring_buffer.h>
enum trace_type {
__TRACE_FIRST_TYPE = 0,
@@ -25,6 +26,7 @@ enum trace_type {
* Function trace entry - function address and parent function addres:
*/
struct ftrace_entry {
+ struct trace_entry ent;
unsigned long ip;
unsigned long parent_ip;
};
@@ -33,6 +35,7 @@ struct ftrace_entry {
* Context switch trace entry - which task (and prio) we switched from/to:
*/
struct ctx_switch_entry {
+ struct trace_entry ent;
unsigned int prev_pid;
unsigned char prev_prio;
unsigned char prev_state;
@@ -45,6 +48,7 @@ struct ctx_switch_entry {
* Special (free-form) trace entry:
*/
struct special_entry {
+ struct trace_entry ent;
unsigned long arg1;
unsigned long arg2;
unsigned long arg3;
@@ -57,63 +61,23 @@ struct special_entry {
#define FTRACE_STACK_ENTRIES 8
struct stack_entry {
+ struct trace_entry ent;
unsigned long caller[FTRACE_STACK_ENTRIES];
};
/*
- * The trace entry - the most basic unit of tracing. This is what
- * is printed in the end as a single line in the trace output, such as:
- *
- * bash-15816 [01] 235.197585: idle_cpu <- irq_enter
- */
-struct trace_entry {
- char type;
- char cpu;
- char flags;
- char preempt_count;
- int pid;
- cycle_t t;
- union {
- struct ftrace_entry fn;
- struct ctx_switch_entry ctx;
- struct special_entry special;
- struct stack_entry stack;
- struct mmiotrace_rw mmiorw;
- struct mmiotrace_map mmiomap;
- };
-};
-
-#define TRACE_ENTRY_SIZE sizeof(struct trace_entry)
-
-/*
* 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 list_head trace_pages;
atomic_t disabled;
- raw_spinlock_t lock;
- struct lock_class_key lock_key;
/* these fields get copied into max-trace: */
- unsigned trace_head_idx;
- unsigned trace_tail_idx;
- void *trace_head; /* producer */
- void *trace_tail; /* consumer */
- unsigned long trace_idx;
- unsigned long overrun;
- unsigned long saved_latency;
unsigned long critical_start;
unsigned long critical_end;
unsigned long critical_sequence;
- unsigned long nice;
- unsigned long policy;
- unsigned long rt_priority;
cycle_t preempt_timestamp;
- pid_t pid;
- uid_t uid;
- char comm[TASK_COMM_LEN];
};
struct trace_iterator;
@@ -124,12 +88,20 @@ struct trace_iterator;
* They have on/off state as well:
*/
struct trace_array {
- unsigned long entries;
+ struct ring_buffer *buffer;
long ctrl;
int cpu;
cycle_t time_start;
struct task_struct *waiter;
struct trace_array_cpu *data[NR_CPUS];
+
+ unsigned long saved_latency;
+ unsigned long nice;
+ unsigned long policy;
+ unsigned long rt_priority;
+ pid_t pid;
+ uid_t uid;
+ char comm[TASK_COMM_LEN];
};
/*
@@ -137,6 +109,7 @@ struct trace_array {
*/
struct tracer {
const char *name;
+ struct trace_array *tr;
void (*init)(struct trace_array *tr);
void (*reset)(struct trace_array *tr);
void (*open)(struct trace_iterator *iter);
@@ -157,12 +130,6 @@ struct tracer {
int print_max;
};
-struct trace_seq {
- unsigned char buffer[PAGE_SIZE];
- unsigned int len;
- unsigned int readpos;
-};
-
/*
* Trace iterator - used by printout routines who present trace
* results to users and which routines might sleep, etc:
@@ -171,26 +138,21 @@ struct trace_iterator {
struct trace_array *tr;
struct tracer *trace;
void *private;
- long last_overrun[NR_CPUS];
- long overrun[NR_CPUS];
/* The below is zeroed out in pipe_read */
- struct trace_seq seq;
- struct trace_entry *ent;
+ struct ring_buffer_seq *seq;
int cpu;
- struct trace_entry *prev_ent;
- int prev_cpu;
+ struct ring_buffer_event *event;
+ struct ring_buffer_event *last_event;
+ struct ring_buffer_iter *buffer_iter;
unsigned long iter_flags;
loff_t pos;
- unsigned long next_idx[NR_CPUS];
- struct list_head *next_page[NR_CPUS];
- unsigned next_page_idx[NR_CPUS];
long idx;
};
-void tracing_reset(struct trace_array_cpu *data);
+void tracing_reset(struct trace_array *tr, int cpu);
int tracing_open_generic(struct inode *inode, struct file *filp);
struct dentry *tracing_init_dentry(void);
void init_tracer_sysprof_debugfs(struct dentry *d_tracer);
@@ -227,6 +189,11 @@ void tracing_start_cmdline_record(void);
void tracing_stop_cmdline_record(void);
int register_tracer(struct tracer *type);
void unregister_tracer(struct tracer *type);
+struct trace_array *trace_allocate_tracer(unsigned long size,
+ unsigned long flags,
+ unsigned long max_entry_size,
+ ring_buffer_print_func print_func,
+ char *name);
extern unsigned long nsecs_to_usecs(unsigned long nsecs);
@@ -308,10 +275,6 @@ extern int trace_selftest_startup_syspro
#endif
#endif /* CONFIG_FTRACE_STARTUP_TEST */
-extern void *head_page(struct trace_array_cpu *data);
-extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...);
-extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
- size_t cnt);
extern long ns2usecs(cycle_t nsec);
extern unsigned long trace_flags;
Index: linux-compile.git/include/linux/ftrace.h
===================================================================
--- linux-compile.git.orig/include/linux/ftrace.h 2008-09-23 23:33:29.000000000 -0400
+++ linux-compile.git/include/linux/ftrace.h 2008-09-23 23:34:46.000000000 -0400
@@ -162,4 +162,10 @@ static inline void
ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { }
#endif
+struct trace_entry {
+ char flags;
+ char preempt_count;
+ int pid;
+};
+
#endif /* _LINUX_FTRACE_H */
Index: linux-compile.git/include/linux/mmiotrace.h
===================================================================
--- linux-compile.git.orig/include/linux/mmiotrace.h 2008-09-23 23:33:29.000000000 -0400
+++ linux-compile.git/include/linux/mmiotrace.h 2008-09-23 23:34:46.000000000 -0400
@@ -1,6 +1,7 @@
#ifndef MMIOTRACE_H
#define MMIOTRACE_H
+#include <linux/ftrace.h>
#include <linux/types.h>
#include <linux/list.h>
@@ -60,6 +61,7 @@ enum mm_io_opcode {
};
struct mmiotrace_rw {
+ struct trace_entry ent;
resource_size_t phys; /* PCI address of register */
unsigned long value;
unsigned long pc; /* optional program counter */
@@ -69,6 +71,7 @@ struct mmiotrace_rw {
};
struct mmiotrace_map {
+ struct trace_entry ent;
resource_size_t phys; /* base address in PCI space */
unsigned long virt; /* base virtual address */
unsigned long len; /* mapping size */
Index: linux-compile.git/kernel/trace/trace_functions.c
===================================================================
--- linux-compile.git.orig/kernel/trace/trace_functions.c 2008-09-23 23:33:29.000000000 -0400
+++ linux-compile.git/kernel/trace/trace_functions.c 2008-09-23 23:34:46.000000000 -0400
@@ -23,7 +23,7 @@ static void function_reset(struct trace_
tr->time_start = ftrace_now(tr->cpu);
for_each_online_cpu(cpu)
- tracing_reset(tr->data[cpu]);
+ tracing_reset(tr, cpu);
}
static void start_function_trace(struct trace_array *tr)
Index: linux-compile.git/kernel/trace/trace_irqsoff.c
===================================================================
--- linux-compile.git.orig/kernel/trace/trace_irqsoff.c 2008-09-23 23:33:29.000000000 -0400
+++ linux-compile.git/kernel/trace/trace_irqsoff.c 2008-09-23 23:34:46.000000000 -0400
@@ -20,6 +20,7 @@
static struct trace_array *irqsoff_trace __read_mostly;
static int tracer_enabled __read_mostly;
+static int preemptirq_buffer_size = 10000;
static DEFINE_PER_CPU(int, tracing_cpu);
@@ -173,7 +174,7 @@ out_unlock:
out:
data->critical_sequence = max_sequence;
data->preempt_timestamp = ftrace_now(cpu);
- tracing_reset(data);
+ tracing_reset(tr, cpu);
trace_function(tr, data, CALLER_ADDR0, parent_ip, flags);
}
@@ -203,7 +204,7 @@ start_critical_timing(unsigned long ip,
data->critical_sequence = max_sequence;
data->preempt_timestamp = ftrace_now(cpu);
data->critical_start = parent_ip ? : ip;
- tracing_reset(data);
+ tracing_reset(tr, cpu);
local_save_flags(flags);
@@ -234,8 +235,7 @@ stop_critical_timing(unsigned long ip, u
data = tr->data[cpu];
- if (unlikely(!data) || unlikely(!head_page(data)) ||
- !data->critical_start || atomic_read(&data->disabled))
+ if (unlikely(!data) || !data->critical_start || atomic_read(&data->disabled))
return;
atomic_inc(&data->disabled);
@@ -399,6 +399,13 @@ static void irqsoff_tracer_close(struct
start_irqsoff_tracer(iter->tr);
}
+static void
+register_preemptirq_tracer(struct tracer *trace, struct trace_array *tr)
+{
+ trace->tr = tr;
+ register_tracer(trace);
+}
+
#ifdef CONFIG_IRQSOFF_TRACER
static void irqsoff_tracer_init(struct trace_array *tr)
{
@@ -419,7 +426,7 @@ static struct tracer irqsoff_tracer __re
.selftest = trace_selftest_startup_irqsoff,
#endif
};
-# define register_irqsoff(trace) register_tracer(&trace)
+# define register_irqsoff(trace, tr) register_preemptirq_tracer(trace, tr)
#else
# define register_irqsoff(trace) do { } while (0)
#endif
@@ -445,7 +452,7 @@ static struct tracer preemptoff_tracer _
.selftest = trace_selftest_startup_preemptoff,
#endif
};
-# define register_preemptoff(trace) register_tracer(&trace)
+# define register_preemptoff(trace, tr) register_preemptirq_tracer(trace, tr)
#else
# define register_preemptoff(trace) do { } while (0)
#endif
@@ -474,16 +481,25 @@ static struct tracer preemptirqsoff_trac
#endif
};
-# define register_preemptirqsoff(trace) register_tracer(&trace)
+# define register_preemptirqsoff(trace, tr) register_preemptirq_tracer(trace, tr)
#else
-# define register_preemptirqsoff(trace) do { } while (0)
+# define register_preemptirqsoff(trace, tr) do { } while (0)
#endif
__init static int init_irqsoff_tracer(void)
{
- register_irqsoff(irqsoff_tracer);
- register_preemptoff(preemptoff_tracer);
- register_preemptirqsoff(preemptirqsoff_tracer);
+ struct trace_array *tr = NULL;
+#if 0
+ tr = trace_allocate_tracer(preemptirq_buffer_size,
+ RB_FL_SNAPSHOT | RB_FL_OVERWRITE, 0,
+ NULL, "preemptirqs");
+ if (!tr)
+ return -ENOMEM;
+#endif
+
+ register_irqsoff(&irqsoff_tracer, tr);
+ register_preemptoff(&preemptoff_tracer, tr);
+ register_preemptirqsoff(&preemptirqsoff_tracer, tr);
return 0;
}
Index: linux-compile.git/kernel/trace/trace_mmiotrace.c
===================================================================
--- linux-compile.git.orig/kernel/trace/trace_mmiotrace.c 2008-09-23 23:33:29.000000000 -0400
+++ linux-compile.git/kernel/trace/trace_mmiotrace.c 2008-09-23 23:34:46.000000000 -0400
@@ -27,7 +27,7 @@ static void mmio_reset_data(struct trace
tr->time_start = ftrace_now(tr->cpu);
for_each_online_cpu(cpu)
- tracing_reset(tr->data[cpu]);
+ tracing_reset(tr, cpu);
}
static void mmio_trace_init(struct trace_array *tr)
@@ -60,17 +60,17 @@ static void mmio_trace_ctrl_update(struc
}
}
-static int mmio_print_pcidev(struct trace_seq *s, const struct pci_dev *dev)
+static int mmio_print_pcidev(struct ring_buffer_seq *s, const struct pci_dev *dev)
{
int ret = 0;
int i;
resource_size_t start, end;
const struct pci_driver *drv = pci_dev_driver(dev);
- /* XXX: incomplete checks for trace_seq_printf() return value */
- ret += trace_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x",
- dev->bus->number, dev->devfn,
- dev->vendor, dev->device, dev->irq);
+ /* XXX: incomplete checks for ring_buffer_seq_printf() return value */
+ ret += ring_buffer_seq_printf(s, "PCIDEV %02x%02x %04x%04x %x",
+ dev->bus->number, dev->devfn,
+ dev->vendor, dev->device, dev->irq);
/*
* XXX: is pci_resource_to_user() appropriate, since we are
* supposed to interpret the __ioremap() phys_addr argument based on
@@ -78,20 +78,20 @@ static int mmio_print_pcidev(struct trac
*/
for (i = 0; i < 7; i++) {
pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
- ret += trace_seq_printf(s, " %llx",
+ ret += ring_buffer_seq_printf(s, " %llx",
(unsigned long long)(start |
(dev->resource[i].flags & PCI_REGION_FLAG_MASK)));
}
for (i = 0; i < 7; i++) {
pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);
- ret += trace_seq_printf(s, " %llx",
+ ret += ring_buffer_seq_printf(s, " %llx",
dev->resource[i].start < dev->resource[i].end ?
(unsigned long long)(end - start) + 1 : 0);
}
if (drv)
- ret += trace_seq_printf(s, " %s\n", drv->name);
+ ret += ring_buffer_seq_printf(s, " %s\n", drv->name);
else
- ret += trace_seq_printf(s, " \n");
+ ret += ring_buffer_seq_printf(s, " \n");
return ret;
}
@@ -106,9 +106,9 @@ static void destroy_header_iter(struct h
static void mmio_pipe_open(struct trace_iterator *iter)
{
struct header_iter *hiter;
- struct trace_seq *s = &iter->seq;
+ struct ring_buffer_seq *s = iter->seq;
- trace_seq_printf(s, "VERSION 20070824\n");
+ ring_buffer_seq_printf(s, "VERSION 20070824\n");
hiter = kzalloc(sizeof(*hiter), GFP_KERNEL);
if (!hiter)
@@ -128,13 +128,7 @@ static void mmio_close(struct trace_iter
static unsigned long count_overruns(struct trace_iterator *iter)
{
- int cpu;
- unsigned long cnt = 0;
- for_each_online_cpu(cpu) {
- cnt += iter->overrun[cpu];
- iter->overrun[cpu] = 0;
- }
- return cnt;
+ return ring_buffer_overruns(iter->tr->buffer);
}
static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp,
@@ -142,13 +136,13 @@ static ssize_t mmio_read(struct trace_it
{
ssize_t ret;
struct header_iter *hiter = iter->private;
- struct trace_seq *s = &iter->seq;
+ struct ring_buffer_seq *s = iter->seq;
unsigned long n;
n = count_overruns(iter);
if (n) {
/* XXX: This is later than where events were lost. */
- trace_seq_printf(s, "MARK 0.000000 Lost %lu events.\n", n);
+ ring_buffer_seq_printf(s, "MARK 0.000000 Lost %lu events.\n", n);
if (!overrun_detected)
pr_warning("mmiotrace has lost events.\n");
overrun_detected = true;
@@ -167,37 +161,37 @@ static ssize_t mmio_read(struct trace_it
}
print_out:
- ret = trace_seq_to_user(s, ubuf, cnt);
+ ret = ring_buffer_seq_copy_to_user(s, ubuf, cnt);
return (ret == -EBUSY) ? 0 : ret;
}
static int mmio_print_rw(struct trace_iterator *iter)
{
- struct trace_entry *entry = iter->ent;
- struct mmiotrace_rw *rw = &entry->mmiorw;
- struct trace_seq *s = &iter->seq;
- unsigned long long t = ns2usecs(entry->t);
+ struct ring_buffer_event *event = iter->event;
+ struct mmiotrace_rw *rw = ring_buffer_event_data(event);
+ struct ring_buffer_seq *s = iter->seq;
+ unsigned long long t = ns2usecs(ring_buffer_event_counter(event));
unsigned long usec_rem = do_div(t, 1000000ULL);
unsigned secs = (unsigned long)t;
int ret = 1;
- switch (entry->mmiorw.opcode) {
+ switch (rw->opcode) {
case MMIO_READ:
- ret = trace_seq_printf(s,
+ ret = ring_buffer_seq_printf(s,
"R %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
rw->width, secs, usec_rem, rw->map_id,
(unsigned long long)rw->phys,
rw->value, rw->pc, 0);
break;
case MMIO_WRITE:
- ret = trace_seq_printf(s,
+ ret = ring_buffer_seq_printf(s,
"W %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
rw->width, secs, usec_rem, rw->map_id,
(unsigned long long)rw->phys,
rw->value, rw->pc, 0);
break;
case MMIO_UNKNOWN_OP:
- ret = trace_seq_printf(s,
+ ret = ring_buffer_seq_printf(s,
"UNKNOWN %lu.%06lu %d 0x%llx %02x,%02x,%02x 0x%lx %d\n",
secs, usec_rem, rw->map_id,
(unsigned long long)rw->phys,
@@ -205,7 +199,7 @@ static int mmio_print_rw(struct trace_it
(rw->value >> 0) & 0xff, rw->pc, 0);
break;
default:
- ret = trace_seq_printf(s, "rw what?\n");
+ ret = ring_buffer_seq_printf(s, "rw what?\n");
break;
}
if (ret)
@@ -215,29 +209,28 @@ static int mmio_print_rw(struct trace_it
static int mmio_print_map(struct trace_iterator *iter)
{
- struct trace_entry *entry = iter->ent;
- struct mmiotrace_map *m = &entry->mmiomap;
- struct trace_seq *s = &iter->seq;
- unsigned long long t = ns2usecs(entry->t);
+ struct mmiotrace_map *m = ring_buffer_event_data(iter->event);
+ struct ring_buffer_seq *s = iter->seq;
+ unsigned long long t = ns2usecs(ring_buffer_event_counter(iter->event));
unsigned long usec_rem = do_div(t, 1000000ULL);
unsigned secs = (unsigned long)t;
int ret = 1;
- switch (entry->mmiorw.opcode) {
+ switch (m->opcode) {
case MMIO_PROBE:
- ret = trace_seq_printf(s,
+ ret = ring_buffer_seq_printf(s,
"MAP %lu.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n",
secs, usec_rem, m->map_id,
(unsigned long long)m->phys, m->virt, m->len,
0UL, 0);
break;
case MMIO_UNPROBE:
- ret = trace_seq_printf(s,
+ ret = ring_buffer_seq_printf(s,
"UNMAP %lu.%06lu %d 0x%lx %d\n",
secs, usec_rem, m->map_id, 0UL, 0);
break;
default:
- ret = trace_seq_printf(s, "map what?\n");
+ ret = ring_buffer_seq_printf(s, "map what?\n");
break;
}
if (ret)
@@ -248,7 +241,7 @@ static int mmio_print_map(struct trace_i
/* return 0 to abort printing without consuming current entry in pipe mode */
static int mmio_print_line(struct trace_iterator *iter)
{
- switch (iter->ent->type) {
+ switch (ring_buffer_event_type(iter->event)) {
case TRACE_MMIO_RW:
return mmio_print_rw(iter);
case TRACE_MMIO_MAP:
Index: linux-compile.git/kernel/trace/trace_sched_switch.c
===================================================================
--- linux-compile.git.orig/kernel/trace/trace_sched_switch.c 2008-09-23 23:33:29.000000000 -0400
+++ linux-compile.git/kernel/trace/trace_sched_switch.c 2008-09-23 23:34:46.000000000 -0400
@@ -133,7 +133,7 @@ static void sched_switch_reset(struct tr
tr->time_start = ftrace_now(tr->cpu);
for_each_online_cpu(cpu)
- tracing_reset(tr->data[cpu]);
+ tracing_reset(tr, cpu);
}
static int tracing_sched_register(void)
Index: linux-compile.git/kernel/trace/trace_sched_wakeup.c
===================================================================
--- linux-compile.git.orig/kernel/trace/trace_sched_wakeup.c 2008-09-23 23:33:29.000000000 -0400
+++ linux-compile.git/kernel/trace/trace_sched_wakeup.c 2008-09-23 23:34:46.000000000 -0400
@@ -215,8 +215,7 @@ static void __wakeup_reset(struct trace_
int cpu;
for_each_possible_cpu(cpu) {
- data = tr->data[cpu];
- tracing_reset(data);
+ tracing_reset(tr, cpu);
}
wakeup_cpu = -1;
Index: linux-compile.git/arch/x86/kernel/Makefile
===================================================================
--- linux-compile.git.orig/arch/x86/kernel/Makefile 2008-09-23 23:33:29.000000000 -0400
+++ linux-compile.git/arch/x86/kernel/Makefile 2008-09-23 23:34:46.000000000 -0400
@@ -11,6 +11,7 @@ ifdef CONFIG_FTRACE
CFLAGS_REMOVE_tsc.o = -pg
CFLAGS_REMOVE_rtc.o = -pg
CFLAGS_REMOVE_paravirt.o = -pg
+CFLAGS_REMOVE_early_printk.o = -pg
endif
#
--
prev parent reply other threads:[~2008-09-24 5:14 UTC|newest]
Thread overview: 109+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-24 5:10 [RFC PATCH 0/3] An Unified tracing buffer (attempt) Steven Rostedt
2008-09-24 5:10 ` [RFC PATCH 1/3] Unified trace buffer Steven Rostedt
2008-09-24 15:03 ` Peter Zijlstra
2008-09-24 15:44 ` Steven Rostedt
2008-09-25 10:38 ` Ingo Molnar
2008-09-24 15:47 ` Martin Bligh
2008-09-24 16:11 ` Peter Zijlstra
2008-09-24 16:24 ` Linus Torvalds
2008-09-24 16:37 ` Steven Rostedt
2008-09-24 16:56 ` Martin Bligh
2008-09-24 17:25 ` Linus Torvalds
2008-09-24 18:01 ` Mathieu Desnoyers
2008-09-24 20:49 ` Linus Torvalds
2008-09-24 16:26 ` Steven Rostedt
2008-09-24 16:49 ` Martin Bligh
2008-09-24 17:36 ` Linus Torvalds
2008-09-24 17:49 ` Steven Rostedt
2008-09-24 20:23 ` Linus Torvalds
2008-09-24 20:37 ` David Miller
2008-09-24 20:48 ` Steven Rostedt
2008-09-24 20:51 ` Martin Bligh
2008-09-24 21:24 ` Frank Ch. Eigler
2008-09-24 21:33 ` Steven Rostedt
2008-09-24 20:47 ` Steven Rostedt
2008-09-24 21:03 ` Martin Bligh
2008-09-24 21:17 ` Steven Rostedt
2008-09-24 21:51 ` Steven Rostedt
2008-09-25 10:41 ` Peter Zijlstra
2008-09-25 14:33 ` Martin Bligh
2008-09-25 14:53 ` Peter Zijlstra
2008-09-25 15:05 ` Linus Torvalds
2008-09-25 15:25 ` Martin Bligh
2008-09-25 15:36 ` Ingo Molnar
2008-09-25 16:23 ` Mathieu Desnoyers
2008-09-25 16:32 ` Steven Rostedt
2008-09-25 17:20 ` Mathieu Desnoyers
2008-09-25 17:32 ` Steven Rostedt
2008-09-25 16:40 ` Linus Torvalds
2008-09-25 16:53 ` Steven Rostedt
2008-09-25 17:07 ` Linus Torvalds
2008-09-25 19:55 ` Ingo Molnar
2008-09-25 20:12 ` Ingo Molnar
2008-09-25 20:24 ` Linus Torvalds
2008-09-25 20:29 ` Linus Torvalds
2008-09-25 20:47 ` Steven Rostedt
2008-09-25 21:01 ` Steven Rostedt
2008-09-25 21:10 ` Ingo Molnar
2008-09-25 21:16 ` Ingo Molnar
2008-09-25 21:41 ` Ingo Molnar
2008-09-25 21:56 ` Ingo Molnar
2008-09-25 21:58 ` Linus Torvalds
2008-09-25 22:14 ` Ingo Molnar
2008-09-25 23:33 ` Linus Torvalds
2008-09-27 17:16 ` Ingo Molnar
2008-09-27 17:36 ` Ingo Molnar
2008-09-27 17:38 ` Steven Rostedt
2008-09-27 17:50 ` Peter Zijlstra
2008-09-27 18:18 ` Steven Rostedt
2008-09-27 18:42 ` Ingo Molnar
2008-09-25 20:52 ` Ingo Molnar
2008-09-25 21:14 ` Jeremy Fitzhardinge
2008-09-25 21:15 ` Martin Bligh
2008-09-25 20:29 ` Mathieu Desnoyers
2008-09-25 20:20 ` Ingo Molnar
2008-09-25 21:02 ` Jeremy Fitzhardinge
2008-09-25 21:55 ` Linus Torvalds
2008-09-25 22:25 ` Ingo Molnar
2008-09-25 22:45 ` Steven Rostedt
2008-09-25 23:04 ` Jeremy Fitzhardinge
2008-09-25 23:25 ` Ingo Molnar
2008-09-26 14:04 ` Thomas Gleixner
2008-09-25 22:39 ` Jeremy Fitzhardinge
2008-09-25 22:55 ` Ingo Molnar
2008-09-26 1:17 ` Jeremy Fitzhardinge
2008-09-26 1:27 ` Steven Rostedt
2008-09-26 1:49 ` Jeremy Fitzhardinge
2008-09-25 22:59 ` Steven Rostedt
2008-09-26 1:27 ` Jeremy Fitzhardinge
2008-09-26 1:35 ` Steven Rostedt
2008-09-26 2:07 ` Jeremy Fitzhardinge
2008-09-26 2:25 ` Steven Rostedt
2008-09-26 5:31 ` Jeremy Fitzhardinge
2008-09-26 10:41 ` Steven Rostedt
2008-09-25 15:26 ` Steven Rostedt
2008-09-25 17:22 ` Linus Torvalds
2008-09-25 17:39 ` Steven Rostedt
2008-09-25 18:14 ` Linus Torvalds
2008-09-25 15:20 ` Steven Rostedt
2008-09-24 17:54 ` Martin Bligh
2008-09-24 18:04 ` Martin Bligh
2008-09-24 20:39 ` Linus Torvalds
2008-09-24 20:56 ` Martin Bligh
2008-09-24 21:08 ` Steven Rostedt
2008-09-24 20:30 ` Linus Torvalds
2008-09-24 20:53 ` Mathieu Desnoyers
2008-09-24 22:28 ` Linus Torvalds
2008-09-24 22:41 ` Linus Torvalds
2008-09-25 17:15 ` Mathieu Desnoyers
2008-09-25 17:29 ` Linus Torvalds
2008-09-25 17:42 ` Mathieu Desnoyers
2008-09-25 16:37 ` Mathieu Desnoyers
2008-09-25 16:49 ` Linus Torvalds
2008-09-25 17:02 ` Steven Rostedt
2008-09-24 16:13 ` Mathieu Desnoyers
2008-09-24 16:31 ` Steven Rostedt
2008-09-24 16:39 ` Peter Zijlstra
2008-09-24 16:51 ` Mathieu Desnoyers
2008-09-24 5:10 ` [RFC PATCH 2/3] ftrace: combine some print formating Steven Rostedt
2008-09-24 5:10 ` Steven Rostedt [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080924051400.552924670@goodmis.org \
--to=rostedt@goodmis.org \
--cc=akpm@linux-foundation.org \
--cc=compudj@krystal.dyndns.org \
--cc=dwilder@us.ibm.com \
--cc=fche@redhat.com \
--cc=hch@lst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=mbligh@google.com \
--cc=mingo@elte.hu \
--cc=peterz@infradead.org \
--cc=prasad@linux.vnet.ibm.com \
--cc=srostedt@redhat.com \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
--cc=zanussi@comcast.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.