Skip to content

Commit

Permalink
ftrace: make work with new ring buffer
Browse files Browse the repository at this point in the history
This patch ports ftrace over to the new ring buffer.

Signed-off-by: Steven Rostedt <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
rostedt authored and Ingo Molnar committed Oct 14, 2008
1 parent ed56829 commit 3928a8a
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 798 deletions.
932 changes: 234 additions & 698 deletions kernel/trace/trace.c

Large diffs are not rendered by default.

22 changes: 5 additions & 17 deletions kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
16 changes: 9 additions & 7 deletions kernel/trace/trace_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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();
}
2 changes: 1 addition & 1 deletion kernel/trace/trace_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions kernel/trace/trace_irqsoff.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ check_critical_timing(struct trace_array *tr,
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);
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand Down
40 changes: 22 additions & 18 deletions kernel/trace/trace_mmiotrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
Expand All @@ -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();
}
Expand Down
2 changes: 1 addition & 1 deletion kernel/trace/trace_nop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion kernel/trace/trace_sched_switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion kernel/trace/trace_sched_wakeup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
60 changes: 10 additions & 50 deletions kernel/trace/trace_selftest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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);
for_each_possible_cpu(cpu) {
if (!head_page(tr->data[cpu]))
continue;

cnt += tr->data[cpu]->trace_idx;
cnt = ring_buffer_entries(tr->buffer);

ret = trace_test_buffer_cpu(tr, tr->data[cpu]);
for_each_possible_cpu(cpu) {
ret = trace_test_buffer_cpu(tr, cpu);
if (ret)
break;
}
Expand Down
2 changes: 1 addition & 1 deletion kernel/trace/trace_sysprof.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 3928a8a

Please sign in to comment.