Commit 777e208d authored by Steven Rostedt's avatar Steven Rostedt Committed by Ingo Molnar

ftrace: take advantage of variable length entries

Now that the underlining ring buffer for ftrace now hold variable length
entries, we can take advantage of this by only storing the size of the
actual event into the buffer. This happens to increase the number of
entries in the buffer dramatically.

We can also get rid of the "trace_cont" operation, but I'm keeping that
until we have no more users. Some of the ftrace tracers can now change
their code to adapt to this new feature.
Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 3928a8a2
This diff is collapsed.
...@@ -26,10 +26,25 @@ enum trace_type { ...@@ -26,10 +26,25 @@ enum trace_type {
__TRACE_LAST_TYPE __TRACE_LAST_TYPE
}; };
/*
* 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 {
unsigned char type;
unsigned char cpu;
unsigned char flags;
unsigned char preempt_count;
int pid;
};
/* /*
* Function trace entry - function address and parent function addres: * Function trace entry - function address and parent function addres:
*/ */
struct ftrace_entry { struct ftrace_entry {
struct trace_entry ent;
unsigned long ip; unsigned long ip;
unsigned long parent_ip; unsigned long parent_ip;
}; };
...@@ -39,6 +54,7 @@ extern struct tracer boot_tracer; ...@@ -39,6 +54,7 @@ extern struct tracer boot_tracer;
* Context switch trace entry - which task (and prio) we switched from/to: * Context switch trace entry - which task (and prio) we switched from/to:
*/ */
struct ctx_switch_entry { struct ctx_switch_entry {
struct trace_entry ent;
unsigned int prev_pid; unsigned int prev_pid;
unsigned char prev_prio; unsigned char prev_prio;
unsigned char prev_state; unsigned char prev_state;
...@@ -52,6 +68,7 @@ struct ctx_switch_entry { ...@@ -52,6 +68,7 @@ struct ctx_switch_entry {
* Special (free-form) trace entry: * Special (free-form) trace entry:
*/ */
struct special_entry { struct special_entry {
struct trace_entry ent;
unsigned long arg1; unsigned long arg1;
unsigned long arg2; unsigned long arg2;
unsigned long arg3; unsigned long arg3;
...@@ -64,6 +81,7 @@ struct special_entry { ...@@ -64,6 +81,7 @@ struct special_entry {
#define FTRACE_STACK_ENTRIES 8 #define FTRACE_STACK_ENTRIES 8
struct stack_entry { struct stack_entry {
struct trace_entry ent;
unsigned long caller[FTRACE_STACK_ENTRIES]; unsigned long caller[FTRACE_STACK_ENTRIES];
}; };
...@@ -71,10 +89,34 @@ struct stack_entry { ...@@ -71,10 +89,34 @@ struct stack_entry {
* ftrace_printk entry: * ftrace_printk entry:
*/ */
struct print_entry { struct print_entry {
struct trace_entry ent;
unsigned long ip; unsigned long ip;
char buf[]; char buf[];
}; };
#define TRACE_OLD_SIZE 88
struct trace_field_cont {
unsigned char type;
/* Temporary till we get rid of this completely */
char buf[TRACE_OLD_SIZE - 1];
};
struct trace_mmiotrace_rw {
struct trace_entry ent;
struct mmiotrace_rw rw;
};
struct trace_mmiotrace_map {
struct trace_entry ent;
struct mmiotrace_map map;
};
struct trace_boot {
struct trace_entry ent;
struct boot_trace initcall;
};
/* /*
* trace_flag_type is an enumeration that holds different * trace_flag_type is an enumeration that holds different
* states when a trace occurs. These are: * states when a trace occurs. These are:
...@@ -92,46 +134,7 @@ enum trace_flag_type { ...@@ -92,46 +134,7 @@ enum trace_flag_type {
TRACE_FLAG_CONT = 0x10, TRACE_FLAG_CONT = 0x10,
}; };
/*
* The trace field - 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_field {
char cpu;
char flags;
char preempt_count;
int pid;
union {
struct ftrace_entry fn;
struct ctx_switch_entry ctx;
struct special_entry special;
struct stack_entry stack;
struct print_entry print;
struct mmiotrace_rw mmiorw;
struct mmiotrace_map mmiomap;
struct boot_trace initcall;
};
};
struct trace_field_cont {
char buf[sizeof(struct trace_field)];
};
struct trace_entry {
char type;
union {
struct trace_field field;
struct trace_field_cont cont;
};
};
#define TRACE_ENTRY_SIZE sizeof(struct trace_entry)
#define TRACE_BUF_SIZE 1024 #define TRACE_BUF_SIZE 1024
#define TRACE_PRINT_BUF_SIZE \
(sizeof(struct trace_field) - offsetof(struct trace_field, print.buf))
#define TRACE_CONT_BUF_SIZE sizeof(struct trace_field)
/* /*
* The CPU trace array - it consists of thousands of trace entries * The CPU trace array - it consists of thousands of trace entries
......
...@@ -49,10 +49,11 @@ static int initcall_print_line(struct trace_iterator *iter) ...@@ -49,10 +49,11 @@ static int initcall_print_line(struct trace_iterator *iter)
{ {
int ret = 0; int ret = 0;
struct trace_entry *entry = iter->ent; struct trace_entry *entry = iter->ent;
struct boot_trace *it = &entry->field.initcall; struct trace_boot *field = (struct trace_boot *)entry;
struct boot_trace *it = &field->initcall;
struct trace_seq *s = &iter->seq; struct trace_seq *s = &iter->seq;
if (iter->ent->type == TRACE_BOOT) if (entry->type == TRACE_BOOT)
ret = trace_seq_printf(s, "%pF called from %i " ret = trace_seq_printf(s, "%pF called from %i "
"returned %d after %lld msecs\n", "returned %d after %lld msecs\n",
it->func, it->caller, it->result, it->func, it->caller, it->result,
...@@ -75,7 +76,7 @@ struct tracer boot_tracer __read_mostly = ...@@ -75,7 +76,7 @@ struct tracer boot_tracer __read_mostly =
void trace_boot(struct boot_trace *it) void trace_boot(struct boot_trace *it)
{ {
struct ring_buffer_event *event; struct ring_buffer_event *event;
struct trace_entry *entry; struct trace_boot *entry;
struct trace_array_cpu *data; struct trace_array_cpu *data;
unsigned long irq_flags; unsigned long irq_flags;
struct trace_array *tr = boot_trace; struct trace_array *tr = boot_trace;
...@@ -91,9 +92,9 @@ void trace_boot(struct boot_trace *it) ...@@ -91,9 +92,9 @@ void trace_boot(struct boot_trace *it)
if (!event) if (!event)
goto out; goto out;
entry = ring_buffer_event_data(event); entry = ring_buffer_event_data(event);
tracing_generic_entry_update(entry, 0); tracing_generic_entry_update(&entry->ent, 0);
entry->type = TRACE_BOOT; entry->ent.type = TRACE_BOOT;
entry->field.initcall = *it; entry->initcall = *it;
ring_buffer_unlock_commit(tr->buffer, event, irq_flags); ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
trace_wake_up(); trace_wake_up();
......
...@@ -178,14 +178,16 @@ static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp, ...@@ -178,14 +178,16 @@ static ssize_t mmio_read(struct trace_iterator *iter, struct file *filp,
static int mmio_print_rw(struct trace_iterator *iter) static int mmio_print_rw(struct trace_iterator *iter)
{ {
struct trace_entry *entry = iter->ent; struct trace_entry *entry = iter->ent;
struct mmiotrace_rw *rw = &entry->field.mmiorw; struct trace_mmiotrace_rw *field =
(struct trace_mmiotrace_rw *)entry;
struct mmiotrace_rw *rw = &field->rw;
struct trace_seq *s = &iter->seq; struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(iter->ts); unsigned long long t = ns2usecs(iter->ts);
unsigned long usec_rem = do_div(t, 1000000ULL); unsigned long usec_rem = do_div(t, 1000000ULL);
unsigned secs = (unsigned long)t; unsigned secs = (unsigned long)t;
int ret = 1; int ret = 1;
switch (entry->field.mmiorw.opcode) { switch (rw->opcode) {
case MMIO_READ: case MMIO_READ:
ret = trace_seq_printf(s, ret = trace_seq_printf(s,
"R %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n", "R %d %lu.%06lu %d 0x%llx 0x%lx 0x%lx %d\n",
...@@ -220,14 +222,14 @@ static int mmio_print_rw(struct trace_iterator *iter) ...@@ -220,14 +222,14 @@ static int mmio_print_rw(struct trace_iterator *iter)
static int mmio_print_map(struct trace_iterator *iter) static int mmio_print_map(struct trace_iterator *iter)
{ {
struct trace_entry *entry = iter->ent; struct trace_entry *entry = iter->ent;
struct mmiotrace_map *m = &entry->field.mmiomap; struct mmiotrace_map *m = (struct mmiotrace_map *)entry;
struct trace_seq *s = &iter->seq; struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(iter->ts); unsigned long long t = ns2usecs(iter->ts);
unsigned long usec_rem = do_div(t, 1000000ULL); unsigned long usec_rem = do_div(t, 1000000ULL);
unsigned secs = (unsigned long)t; unsigned secs = (unsigned long)t;
int ret = 1; int ret = 1;
switch (entry->field.mmiorw.opcode) { switch (m->opcode) {
case MMIO_PROBE: case MMIO_PROBE:
ret = trace_seq_printf(s, ret = trace_seq_printf(s,
"MAP %lu.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n", "MAP %lu.%06lu %d 0x%llx 0x%lx 0x%lx 0x%lx %d\n",
...@@ -252,7 +254,8 @@ static int mmio_print_map(struct trace_iterator *iter) ...@@ -252,7 +254,8 @@ static int mmio_print_map(struct trace_iterator *iter)
static int mmio_print_mark(struct trace_iterator *iter) static int mmio_print_mark(struct trace_iterator *iter)
{ {
struct trace_entry *entry = iter->ent; struct trace_entry *entry = iter->ent;
const char *msg = entry->field.print.buf; struct print_entry *print = (struct print_entry *)entry;
const char *msg = print->buf;
struct trace_seq *s = &iter->seq; struct trace_seq *s = &iter->seq;
unsigned long long t = ns2usecs(iter->ts); unsigned long long t = ns2usecs(iter->ts);
unsigned long usec_rem = do_div(t, 1000000ULL); unsigned long usec_rem = do_div(t, 1000000ULL);
...@@ -264,7 +267,7 @@ static int mmio_print_mark(struct trace_iterator *iter) ...@@ -264,7 +267,7 @@ static int mmio_print_mark(struct trace_iterator *iter)
if (!ret) if (!ret)
return 0; return 0;
if (entry->field.flags & TRACE_FLAG_CONT) if (entry->flags & TRACE_FLAG_CONT)
trace_seq_print_cont(s, iter); trace_seq_print_cont(s, iter);
return 1; return 1;
...@@ -308,7 +311,7 @@ static void __trace_mmiotrace_rw(struct trace_array *tr, ...@@ -308,7 +311,7 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,
struct mmiotrace_rw *rw) struct mmiotrace_rw *rw)
{ {
struct ring_buffer_event *event; struct ring_buffer_event *event;
struct trace_entry *entry; struct trace_mmiotrace_rw *entry;
unsigned long irq_flags; unsigned long irq_flags;
event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
...@@ -316,9 +319,9 @@ static void __trace_mmiotrace_rw(struct trace_array *tr, ...@@ -316,9 +319,9 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,
if (!event) if (!event)
return; return;
entry = ring_buffer_event_data(event); entry = ring_buffer_event_data(event);
tracing_generic_entry_update(entry, 0); tracing_generic_entry_update(&entry->ent, 0);
entry->type = TRACE_MMIO_RW; entry->ent.type = TRACE_MMIO_RW;
entry->field.mmiorw = *rw; entry->rw = *rw;
ring_buffer_unlock_commit(tr->buffer, event, irq_flags); ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
trace_wake_up(); trace_wake_up();
...@@ -336,7 +339,7 @@ static void __trace_mmiotrace_map(struct trace_array *tr, ...@@ -336,7 +339,7 @@ static void __trace_mmiotrace_map(struct trace_array *tr,
struct mmiotrace_map *map) struct mmiotrace_map *map)
{ {
struct ring_buffer_event *event; struct ring_buffer_event *event;
struct trace_entry *entry; struct trace_mmiotrace_map *entry;
unsigned long irq_flags; unsigned long irq_flags;
event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
...@@ -344,9 +347,9 @@ static void __trace_mmiotrace_map(struct trace_array *tr, ...@@ -344,9 +347,9 @@ static void __trace_mmiotrace_map(struct trace_array *tr,
if (!event) if (!event)
return; return;
entry = ring_buffer_event_data(event); entry = ring_buffer_event_data(event);
tracing_generic_entry_update(entry, 0); tracing_generic_entry_update(&entry->ent, 0);
entry->type = TRACE_MMIO_MAP; entry->ent.type = TRACE_MMIO_MAP;
entry->field.mmiomap = *map; entry->map = *map;
ring_buffer_unlock_commit(tr->buffer, event, irq_flags); ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
trace_wake_up(); trace_wake_up();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment