ftrace: make work with new ring buffer

This patch ports ftrace over to the new ring buffer.

Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Steven Rostedt 2008-09-29 23:02:41 -04:00 committed by Ingo Molnar
parent ed56829cb3
commit 3928a8a2d9
11 changed files with 292 additions and 802 deletions

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@
#include <asm/atomic.h>
#include <linux/sched.h>
#include <linux/clocksource.h>
#include <linux/ring_buffer.h>
#include <linux/mmiotrace.h>
#include <linux/ftrace.h>
@ -102,7 +103,6 @@ struct trace_field {
char flags;
char preempt_count;
int pid;
cycle_t t;
union {
struct ftrace_entry fn;
struct ctx_switch_entry ctx;
@ -139,16 +139,9 @@ struct trace_entry {
* 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;
@ -172,6 +165,7 @@ struct trace_iterator;
* They have on/off state as well:
*/
struct trace_array {
struct ring_buffer *buffer;
unsigned long entries;
long ctrl;
int cpu;
@ -219,27 +213,21 @@ struct trace_iterator {
struct trace_array *tr;
struct tracer *trace;
void *private;
long last_overrun[NR_CPUS];
long overrun[NR_CPUS];
struct ring_buffer_iter *buffer_iter[NR_CPUS];
/* The below is zeroed out in pipe_read */
struct trace_seq seq;
struct trace_entry *ent;
int cpu;
struct trace_entry *prev_ent;
int prev_cpu;
u64 ts;
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 trace_wake_up(void);
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);

View File

@ -34,7 +34,7 @@ static void boot_trace_init(struct trace_array *tr)
trace_boot_enabled = 0;
for_each_cpu_mask(cpu, cpu_possible_map)
tracing_reset(tr->data[cpu]);
tracing_reset(tr, cpu);
}
static void boot_trace_ctrl_update(struct trace_array *tr)
@ -74,6 +74,7 @@ struct tracer boot_tracer __read_mostly =
void trace_boot(struct boot_trace *it)
{
struct ring_buffer_event *event;
struct trace_entry *entry;
struct trace_array_cpu *data;
unsigned long irq_flags;
@ -85,17 +86,18 @@ void trace_boot(struct boot_trace *it)
preempt_disable();
data = tr->data[smp_processor_id()];
raw_local_irq_save(irq_flags);
__raw_spin_lock(&data->lock);
entry = tracing_get_trace_entry(tr, data);
event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
&irq_flags);
if (!event)
goto out;
entry = ring_buffer_event_data(event);
tracing_generic_entry_update(entry, 0);
entry->type = TRACE_BOOT;
entry->field.initcall = *it;
ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
__raw_spin_unlock(&data->lock);
raw_local_irq_restore(irq_flags);
trace_wake_up();
out:
preempt_enable();
}

View File

@ -23,7 +23,7 @@ static void function_reset(struct trace_array *tr)
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)

View File

@ -173,7 +173,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 +203,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_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,7 +234,7 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip)
data = tr->data[cpu];
if (unlikely(!data) || unlikely(!head_page(data)) ||
if (unlikely(!data) ||
!data->critical_start || atomic_read(&data->disabled))
return;

View File

@ -27,7 +27,7 @@ static void mmio_reset_data(struct trace_array *tr)
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)
@ -130,10 +130,14 @@ static unsigned long count_overruns(struct trace_iterator *iter)
{
int cpu;
unsigned long cnt = 0;
/* FIXME: */
#if 0
for_each_online_cpu(cpu) {
cnt += iter->overrun[cpu];
iter->overrun[cpu] = 0;
}
#endif
(void)cpu;
return cnt;
}
@ -176,7 +180,7 @@ static int mmio_print_rw(struct trace_iterator *iter)
struct trace_entry *entry = iter->ent;
struct mmiotrace_rw *rw = &entry->field.mmiorw;
struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(entry->field.t);
unsigned long long t = ns2usecs(iter->ts);
unsigned long usec_rem = do_div(t, 1000000ULL);
unsigned secs = (unsigned long)t;
int ret = 1;
@ -218,7 +222,7 @@ static int mmio_print_map(struct trace_iterator *iter)
struct trace_entry *entry = iter->ent;
struct mmiotrace_map *m = &entry->field.mmiomap;
struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(entry->field.t);
unsigned long long t = ns2usecs(iter->ts);
unsigned long usec_rem = do_div(t, 1000000ULL);
unsigned secs = (unsigned long)t;
int ret = 1;
@ -250,7 +254,7 @@ static int mmio_print_mark(struct trace_iterator *iter)
struct trace_entry *entry = iter->ent;
const char *msg = entry->field.print.buf;
struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(entry->field.t);
unsigned long long t = ns2usecs(iter->ts);
unsigned long usec_rem = do_div(t, 1000000ULL);
unsigned secs = (unsigned long)t;
int ret;
@ -303,19 +307,19 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,
struct trace_array_cpu *data,
struct mmiotrace_rw *rw)
{
struct ring_buffer_event *event;
struct trace_entry *entry;
unsigned long irq_flags;
raw_local_irq_save(irq_flags);
__raw_spin_lock(&data->lock);
entry = tracing_get_trace_entry(tr, data);
event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
&irq_flags);
if (!event)
return;
entry = ring_buffer_event_data(event);
tracing_generic_entry_update(entry, 0);
entry->type = TRACE_MMIO_RW;
entry->field.mmiorw = *rw;
__raw_spin_unlock(&data->lock);
raw_local_irq_restore(irq_flags);
ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
trace_wake_up();
}
@ -331,19 +335,19 @@ static void __trace_mmiotrace_map(struct trace_array *tr,
struct trace_array_cpu *data,
struct mmiotrace_map *map)
{
struct ring_buffer_event *event;
struct trace_entry *entry;
unsigned long irq_flags;
raw_local_irq_save(irq_flags);
__raw_spin_lock(&data->lock);
entry = tracing_get_trace_entry(tr, data);
event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
&irq_flags);
if (!event)
return;
entry = ring_buffer_event_data(event);
tracing_generic_entry_update(entry, 0);
entry->type = TRACE_MMIO_MAP;
entry->field.mmiomap = *map;
__raw_spin_unlock(&data->lock);
raw_local_irq_restore(irq_flags);
ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
trace_wake_up();
}

View File

@ -30,7 +30,7 @@ static void nop_trace_init(struct trace_array *tr)
ctx_trace = tr;
for_each_online_cpu(cpu)
tracing_reset(tr->data[cpu]);
tracing_reset(tr, cpu);
if (tr->ctrl)
start_nop_trace(tr);

View File

@ -81,7 +81,7 @@ static void sched_switch_reset(struct trace_array *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)

View File

@ -191,7 +191,7 @@ static void __wakeup_reset(struct trace_array *tr)
for_each_possible_cpu(cpu) {
data = tr->data[cpu];
tracing_reset(data);
tracing_reset(tr, cpu);
}
wakeup_cpu = -1;

View File

@ -18,58 +18,20 @@ static inline int trace_valid_entry(struct trace_entry *entry)
return 0;
}
static int
trace_test_buffer_cpu(struct trace_array *tr, struct trace_array_cpu *data)
static int trace_test_buffer_cpu(struct trace_array *tr, int cpu)
{
struct trace_entry *entries;
struct page *page;
int idx = 0;
int i;
struct ring_buffer_event *event;
struct trace_entry *entry;
BUG_ON(list_empty(&data->trace_pages));
page = list_entry(data->trace_pages.next, struct page, lru);
entries = page_address(page);
while ((event = ring_buffer_consume(tr->buffer, cpu, NULL))) {
entry = ring_buffer_event_data(event);
check_pages(data);
if (head_page(data) != entries)
goto failed;
/*
* The starting trace buffer always has valid elements,
* if any element exists.
*/
entries = head_page(data);
for (i = 0; i < tr->entries; i++) {
if (i < data->trace_idx && !trace_valid_entry(&entries[idx])) {
if (!trace_valid_entry(entry)) {
printk(KERN_CONT ".. invalid entry %d ",
entries[idx].type);
entry->type);
goto failed;
}
idx++;
if (idx >= ENTRIES_PER_PAGE) {
page = virt_to_page(entries);
if (page->lru.next == &data->trace_pages) {
if (i != tr->entries - 1) {
printk(KERN_CONT ".. entries buffer mismatch");
goto failed;
}
} else {
page = list_entry(page->lru.next, struct page, lru);
entries = page_address(page);
}
idx = 0;
}
}
page = virt_to_page(entries);
if (page->lru.next != &data->trace_pages) {
printk(KERN_CONT ".. too many entries");
goto failed;
}
return 0;
failed:
@ -91,13 +53,11 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
/* Don't allow flipping of max traces now */
raw_local_irq_save(flags);
__raw_spin_lock(&ftrace_max_lock);
cnt = ring_buffer_entries(tr->buffer);
for_each_possible_cpu(cpu) {
if (!head_page(tr->data[cpu]))
continue;
cnt += tr->data[cpu]->trace_idx;
ret = trace_test_buffer_cpu(tr, tr->data[cpu]);
ret = trace_test_buffer_cpu(tr, cpu);
if (ret)
break;
}

View File

@ -241,7 +241,7 @@ static void stack_reset(struct trace_array *tr)
tr->time_start = ftrace_now(tr->cpu);
for_each_online_cpu(cpu)
tracing_reset(tr->data[cpu]);
tracing_reset(tr, cpu);
}
static void start_stack_trace(struct trace_array *tr)