Merge branches 'tracing/branch-tracer', 'tracing/fastboot', 'tracing/ftrace', 'tracing/function-return-tracer', 'tracing/power-tracer', 'tracing/powerpc', 'tracing/ring-buffer', 'tracing/stack-tracer' and 'tracing/urgent' into tracing/core
This commit is contained in:

@@ -3,6 +3,9 @@
|
||||
# select HAVE_FUNCTION_TRACER:
|
||||
#
|
||||
|
||||
config USER_STACKTRACE_SUPPORT
|
||||
bool
|
||||
|
||||
config NOP_TRACER
|
||||
bool
|
||||
|
||||
|
@@ -1498,10 +1498,77 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
|
||||
|
||||
#ifdef CONFIG_FUNCTION_RET_TRACER
|
||||
|
||||
static atomic_t ftrace_retfunc_active;
|
||||
|
||||
/* The callback that hooks the return of a function */
|
||||
trace_function_return_t ftrace_function_return =
|
||||
(trace_function_return_t)ftrace_stub;
|
||||
|
||||
|
||||
/* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */
|
||||
static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
int start = 0, end = FTRACE_RETSTACK_ALLOC_SIZE;
|
||||
struct task_struct *g, *t;
|
||||
|
||||
for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) {
|
||||
ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH
|
||||
* sizeof(struct ftrace_ret_stack),
|
||||
GFP_KERNEL);
|
||||
if (!ret_stack_list[i]) {
|
||||
start = 0;
|
||||
end = i;
|
||||
ret = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
|
||||
read_lock_irqsave(&tasklist_lock, flags);
|
||||
do_each_thread(g, t) {
|
||||
if (start == end) {
|
||||
ret = -EAGAIN;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (t->ret_stack == NULL) {
|
||||
t->ret_stack = ret_stack_list[start++];
|
||||
t->curr_ret_stack = -1;
|
||||
atomic_set(&t->trace_overrun, 0);
|
||||
}
|
||||
} while_each_thread(g, t);
|
||||
|
||||
unlock:
|
||||
read_unlock_irqrestore(&tasklist_lock, flags);
|
||||
free:
|
||||
for (i = start; i < end; i++)
|
||||
kfree(ret_stack_list[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate a return stack for each task */
|
||||
static int start_return_tracing(void)
|
||||
{
|
||||
struct ftrace_ret_stack **ret_stack_list;
|
||||
int ret;
|
||||
|
||||
ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
|
||||
sizeof(struct ftrace_ret_stack *),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!ret_stack_list)
|
||||
return -ENOMEM;
|
||||
|
||||
do {
|
||||
ret = alloc_retstack_tasklist(ret_stack_list);
|
||||
} while (ret == -EAGAIN);
|
||||
|
||||
kfree(ret_stack_list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int register_ftrace_return(trace_function_return_t func)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -1516,7 +1583,12 @@ int register_ftrace_return(trace_function_return_t func)
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
atomic_inc(&ftrace_retfunc_active);
|
||||
ret = start_return_tracing();
|
||||
if (ret) {
|
||||
atomic_dec(&ftrace_retfunc_active);
|
||||
goto out;
|
||||
}
|
||||
ftrace_tracing_type = FTRACE_TYPE_RETURN;
|
||||
ftrace_function_return = func;
|
||||
ftrace_startup();
|
||||
@@ -1530,6 +1602,7 @@ void unregister_ftrace_return(void)
|
||||
{
|
||||
mutex_lock(&ftrace_sysctl_lock);
|
||||
|
||||
atomic_dec(&ftrace_retfunc_active);
|
||||
ftrace_function_return = (trace_function_return_t)ftrace_stub;
|
||||
ftrace_shutdown();
|
||||
/* Restore normal tracing type */
|
||||
@@ -1537,6 +1610,32 @@ void unregister_ftrace_return(void)
|
||||
|
||||
mutex_unlock(&ftrace_sysctl_lock);
|
||||
}
|
||||
|
||||
/* Allocate a return stack for newly created task */
|
||||
void ftrace_retfunc_init_task(struct task_struct *t)
|
||||
{
|
||||
if (atomic_read(&ftrace_retfunc_active)) {
|
||||
t->ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
|
||||
* sizeof(struct ftrace_ret_stack),
|
||||
GFP_KERNEL);
|
||||
if (!t->ret_stack)
|
||||
return;
|
||||
t->curr_ret_stack = -1;
|
||||
atomic_set(&t->trace_overrun, 0);
|
||||
} else
|
||||
t->ret_stack = NULL;
|
||||
}
|
||||
|
||||
void ftrace_retfunc_exit_task(struct task_struct *t)
|
||||
{
|
||||
struct ftrace_ret_stack *ret_stack = t->ret_stack;
|
||||
|
||||
t->ret_stack = NULL;
|
||||
/* NULL must become visible to IRQs before we free it: */
|
||||
barrier();
|
||||
|
||||
kfree(ret_stack);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -18,8 +18,46 @@
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
/* Global flag to disable all recording to ring buffers */
|
||||
static int ring_buffers_off __read_mostly;
|
||||
/*
|
||||
* A fast way to enable or disable all ring buffers is to
|
||||
* call tracing_on or tracing_off. Turning off the ring buffers
|
||||
* prevents all ring buffers from being recorded to.
|
||||
* Turning this switch on, makes it OK to write to the
|
||||
* ring buffer, if the ring buffer is enabled itself.
|
||||
*
|
||||
* There's three layers that must be on in order to write
|
||||
* to the ring buffer.
|
||||
*
|
||||
* 1) This global flag must be set.
|
||||
* 2) The ring buffer must be enabled for recording.
|
||||
* 3) The per cpu buffer must be enabled for recording.
|
||||
*
|
||||
* In case of an anomaly, this global flag has a bit set that
|
||||
* will permantly disable all ring buffers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Global flag to disable all recording to ring buffers
|
||||
* This has two bits: ON, DISABLED
|
||||
*
|
||||
* ON DISABLED
|
||||
* ---- ----------
|
||||
* 0 0 : ring buffers are off
|
||||
* 1 0 : ring buffers are on
|
||||
* X 1 : ring buffers are permanently disabled
|
||||
*/
|
||||
|
||||
enum {
|
||||
RB_BUFFERS_ON_BIT = 0,
|
||||
RB_BUFFERS_DISABLED_BIT = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
RB_BUFFERS_ON = 1 << RB_BUFFERS_ON_BIT,
|
||||
RB_BUFFERS_DISABLED = 1 << RB_BUFFERS_DISABLED_BIT,
|
||||
};
|
||||
|
||||
static long ring_buffer_flags __read_mostly = RB_BUFFERS_ON;
|
||||
|
||||
/**
|
||||
* tracing_on - enable all tracing buffers
|
||||
@@ -29,7 +67,7 @@ static int ring_buffers_off __read_mostly;
|
||||
*/
|
||||
void tracing_on(void)
|
||||
{
|
||||
ring_buffers_off = 0;
|
||||
set_bit(RB_BUFFERS_ON_BIT, &ring_buffer_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,7 +80,18 @@ void tracing_on(void)
|
||||
*/
|
||||
void tracing_off(void)
|
||||
{
|
||||
ring_buffers_off = 1;
|
||||
clear_bit(RB_BUFFERS_ON_BIT, &ring_buffer_flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* tracing_off_permanent - permanently disable ring buffers
|
||||
*
|
||||
* This function, once called, will disable all ring buffers
|
||||
* permanenty.
|
||||
*/
|
||||
void tracing_off_permanent(void)
|
||||
{
|
||||
set_bit(RB_BUFFERS_DISABLED_BIT, &ring_buffer_flags);
|
||||
}
|
||||
|
||||
#include "trace.h"
|
||||
@@ -1185,7 +1234,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer,
|
||||
struct ring_buffer_event *event;
|
||||
int cpu, resched;
|
||||
|
||||
if (ring_buffers_off)
|
||||
if (ring_buffer_flags != RB_BUFFERS_ON)
|
||||
return NULL;
|
||||
|
||||
if (atomic_read(&buffer->record_disabled))
|
||||
@@ -1297,7 +1346,7 @@ int ring_buffer_write(struct ring_buffer *buffer,
|
||||
int ret = -EBUSY;
|
||||
int cpu, resched;
|
||||
|
||||
if (ring_buffers_off)
|
||||
if (ring_buffer_flags != RB_BUFFERS_ON)
|
||||
return -EBUSY;
|
||||
|
||||
if (atomic_read(&buffer->record_disabled))
|
||||
@@ -2178,12 +2227,14 @@ static ssize_t
|
||||
rb_simple_read(struct file *filp, char __user *ubuf,
|
||||
size_t cnt, loff_t *ppos)
|
||||
{
|
||||
int *p = filp->private_data;
|
||||
long *p = filp->private_data;
|
||||
char buf[64];
|
||||
int r;
|
||||
|
||||
/* !ring_buffers_off == tracing_on */
|
||||
r = sprintf(buf, "%d\n", !*p);
|
||||
if (test_bit(RB_BUFFERS_DISABLED_BIT, p))
|
||||
r = sprintf(buf, "permanently disabled\n");
|
||||
else
|
||||
r = sprintf(buf, "%d\n", test_bit(RB_BUFFERS_ON_BIT, p));
|
||||
|
||||
return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
|
||||
}
|
||||
@@ -2192,7 +2243,7 @@ static ssize_t
|
||||
rb_simple_write(struct file *filp, const char __user *ubuf,
|
||||
size_t cnt, loff_t *ppos)
|
||||
{
|
||||
int *p = filp->private_data;
|
||||
long *p = filp->private_data;
|
||||
char buf[64];
|
||||
long val;
|
||||
int ret;
|
||||
@@ -2209,8 +2260,10 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* !ring_buffers_off == tracing_on */
|
||||
*p = !val;
|
||||
if (val)
|
||||
set_bit(RB_BUFFERS_ON_BIT, p);
|
||||
else
|
||||
clear_bit(RB_BUFFERS_ON_BIT, p);
|
||||
|
||||
(*ppos)++;
|
||||
|
||||
@@ -2232,7 +2285,7 @@ static __init int rb_init_debugfs(void)
|
||||
d_tracer = tracing_init_dentry();
|
||||
|
||||
entry = debugfs_create_file("tracing_on", 0644, d_tracer,
|
||||
&ring_buffers_off, &rb_simple_fops);
|
||||
&ring_buffer_flags, &rb_simple_fops);
|
||||
if (!entry)
|
||||
pr_warning("Could not create debugfs 'tracing_on' entry\n");
|
||||
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/writeback.h>
|
||||
|
||||
#include <linux/stacktrace.h>
|
||||
@@ -275,6 +276,8 @@ static const char *trace_options[] = {
|
||||
"ftrace_preempt",
|
||||
"branch",
|
||||
"annotate",
|
||||
"userstacktrace",
|
||||
"sym-userobj",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -421,6 +424,28 @@ trace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len)
|
||||
return trace_seq_putmem(s, hex, j);
|
||||
}
|
||||
|
||||
static int
|
||||
trace_seq_path(struct trace_seq *s, struct path *path)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
if (s->len >= (PAGE_SIZE - 1))
|
||||
return 0;
|
||||
p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
|
||||
if (!IS_ERR(p)) {
|
||||
p = mangle_path(s->buffer + s->len, p, "\n");
|
||||
if (p) {
|
||||
s->len = p - s->buffer;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
s->buffer[s->len++] = '?';
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
trace_seq_reset(struct trace_seq *s)
|
||||
{
|
||||
@@ -660,6 +685,21 @@ static void trace_init_cmdlines(void)
|
||||
static int trace_stop_count;
|
||||
static DEFINE_SPINLOCK(tracing_start_lock);
|
||||
|
||||
/**
|
||||
* ftrace_off_permanent - disable all ftrace code permanently
|
||||
*
|
||||
* This should only be called when a serious anomally has
|
||||
* been detected. This will turn off the function tracing,
|
||||
* ring buffers, and other tracing utilites. It takes no
|
||||
* locks and can be called from any context.
|
||||
*/
|
||||
void ftrace_off_permanent(void)
|
||||
{
|
||||
tracing_disabled = 1;
|
||||
ftrace_stop();
|
||||
tracing_off_permanent();
|
||||
}
|
||||
|
||||
/**
|
||||
* tracing_start - quick start of the tracer
|
||||
*
|
||||
@@ -801,6 +841,7 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
|
||||
|
||||
entry->preempt_count = pc & 0xff;
|
||||
entry->pid = (tsk) ? tsk->pid : 0;
|
||||
entry->tgid = (tsk) ? tsk->tgid : 0;
|
||||
entry->flags =
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
|
||||
(irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
|
||||
@@ -918,6 +959,44 @@ void __trace_stack(struct trace_array *tr,
|
||||
ftrace_trace_stack(tr, data, flags, skip, preempt_count());
|
||||
}
|
||||
|
||||
static void ftrace_trace_userstack(struct trace_array *tr,
|
||||
struct trace_array_cpu *data,
|
||||
unsigned long flags, int pc)
|
||||
{
|
||||
struct ring_buffer_event *event;
|
||||
struct userstack_entry *entry;
|
||||
struct stack_trace trace;
|
||||
unsigned long irq_flags;
|
||||
|
||||
if (!(trace_flags & TRACE_ITER_USERSTACKTRACE))
|
||||
return;
|
||||
|
||||
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->ent, flags, pc);
|
||||
entry->ent.type = TRACE_USER_STACK;
|
||||
|
||||
memset(&entry->caller, 0, sizeof(entry->caller));
|
||||
|
||||
trace.nr_entries = 0;
|
||||
trace.max_entries = FTRACE_STACK_ENTRIES;
|
||||
trace.skip = 0;
|
||||
trace.entries = entry->caller;
|
||||
|
||||
save_stack_trace_user(&trace);
|
||||
ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
|
||||
}
|
||||
|
||||
void __trace_userstack(struct trace_array *tr,
|
||||
struct trace_array_cpu *data,
|
||||
unsigned long flags)
|
||||
{
|
||||
ftrace_trace_userstack(tr, data, flags, preempt_count());
|
||||
}
|
||||
|
||||
static void
|
||||
ftrace_trace_special(void *__tr, void *__data,
|
||||
unsigned long arg1, unsigned long arg2, unsigned long arg3,
|
||||
@@ -941,6 +1020,7 @@ ftrace_trace_special(void *__tr, void *__data,
|
||||
entry->arg3 = arg3;
|
||||
ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
|
||||
ftrace_trace_stack(tr, data, irq_flags, 4, pc);
|
||||
ftrace_trace_userstack(tr, data, irq_flags, pc);
|
||||
|
||||
trace_wake_up();
|
||||
}
|
||||
@@ -979,6 +1059,7 @@ tracing_sched_switch_trace(struct trace_array *tr,
|
||||
entry->next_cpu = task_cpu(next);
|
||||
ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
|
||||
ftrace_trace_stack(tr, data, flags, 5, pc);
|
||||
ftrace_trace_userstack(tr, data, flags, pc);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1008,6 +1089,7 @@ tracing_sched_wakeup_trace(struct trace_array *tr,
|
||||
entry->next_cpu = task_cpu(wakee);
|
||||
ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
|
||||
ftrace_trace_stack(tr, data, flags, 6, pc);
|
||||
ftrace_trace_userstack(tr, data, flags, pc);
|
||||
|
||||
trace_wake_up();
|
||||
}
|
||||
@@ -1387,6 +1469,78 @@ seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm,
|
||||
unsigned long ip, unsigned long sym_flags)
|
||||
{
|
||||
struct file *file = NULL;
|
||||
unsigned long vmstart = 0;
|
||||
int ret = 1;
|
||||
|
||||
if (mm) {
|
||||
const struct vm_area_struct *vma;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, ip);
|
||||
if (vma) {
|
||||
file = vma->vm_file;
|
||||
vmstart = vma->vm_start;
|
||||
}
|
||||
if (file) {
|
||||
ret = trace_seq_path(s, &file->f_path);
|
||||
if (ret)
|
||||
ret = trace_seq_printf(s, "[+0x%lx]", ip - vmstart);
|
||||
}
|
||||
up_read(&mm->mmap_sem);
|
||||
}
|
||||
if (ret && ((sym_flags & TRACE_ITER_SYM_ADDR) || !file))
|
||||
ret = trace_seq_printf(s, " <" IP_FMT ">", ip);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
seq_print_userip_objs(const struct userstack_entry *entry, struct trace_seq *s,
|
||||
unsigned long sym_flags)
|
||||
{
|
||||
struct mm_struct *mm = NULL;
|
||||
int ret = 1;
|
||||
unsigned int i;
|
||||
|
||||
if (trace_flags & TRACE_ITER_SYM_USEROBJ) {
|
||||
struct task_struct *task;
|
||||
/*
|
||||
* we do the lookup on the thread group leader,
|
||||
* since individual threads might have already quit!
|
||||
*/
|
||||
rcu_read_lock();
|
||||
task = find_task_by_vpid(entry->ent.tgid);
|
||||
if (task)
|
||||
mm = get_task_mm(task);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
for (i = 0; i < FTRACE_STACK_ENTRIES; i++) {
|
||||
unsigned long ip = entry->caller[i];
|
||||
|
||||
if (ip == ULONG_MAX || !ret)
|
||||
break;
|
||||
if (i && ret)
|
||||
ret = trace_seq_puts(s, " <- ");
|
||||
if (!ip) {
|
||||
if (ret)
|
||||
ret = trace_seq_puts(s, "??");
|
||||
continue;
|
||||
}
|
||||
if (!ret)
|
||||
break;
|
||||
if (ret)
|
||||
ret = seq_print_user_ip(s, mm, ip, sym_flags);
|
||||
}
|
||||
|
||||
if (mm)
|
||||
mmput(mm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void print_lat_help_header(struct seq_file *m)
|
||||
{
|
||||
seq_puts(m, "# _------=> CPU# \n");
|
||||
@@ -1702,6 +1856,15 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
|
||||
field->line);
|
||||
break;
|
||||
}
|
||||
case TRACE_USER_STACK: {
|
||||
struct userstack_entry *field;
|
||||
|
||||
trace_assign_type(field, entry);
|
||||
|
||||
seq_print_userip_objs(field, s, sym_flags);
|
||||
trace_seq_putc(s, '\n');
|
||||
break;
|
||||
}
|
||||
default:
|
||||
trace_seq_printf(s, "Unknown type %d\n", entry->type);
|
||||
}
|
||||
@@ -1853,6 +2016,19 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
|
||||
field->line);
|
||||
break;
|
||||
}
|
||||
case TRACE_USER_STACK: {
|
||||
struct userstack_entry *field;
|
||||
|
||||
trace_assign_type(field, entry);
|
||||
|
||||
ret = seq_print_userip_objs(field, s, sym_flags);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
ret = trace_seq_putc(s, '\n');
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRACE_TYPE_HANDLED;
|
||||
}
|
||||
@@ -1912,6 +2088,7 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
|
||||
break;
|
||||
}
|
||||
case TRACE_SPECIAL:
|
||||
case TRACE_USER_STACK:
|
||||
case TRACE_STACK: {
|
||||
struct special_entry *field;
|
||||
|
||||
@@ -2000,6 +2177,7 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
|
||||
break;
|
||||
}
|
||||
case TRACE_SPECIAL:
|
||||
case TRACE_USER_STACK:
|
||||
case TRACE_STACK: {
|
||||
struct special_entry *field;
|
||||
|
||||
@@ -2054,6 +2232,7 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
|
||||
break;
|
||||
}
|
||||
case TRACE_SPECIAL:
|
||||
case TRACE_USER_STACK:
|
||||
case TRACE_STACK: {
|
||||
struct special_entry *field;
|
||||
|
||||
@@ -3488,6 +3667,9 @@ void ftrace_dump(void)
|
||||
atomic_inc(&global_trace.data[cpu]->disabled);
|
||||
}
|
||||
|
||||
/* don't look at user memory in panic mode */
|
||||
trace_flags &= ~TRACE_ITER_SYM_USEROBJ;
|
||||
|
||||
printk(KERN_TRACE "Dumping ftrace buffer:\n");
|
||||
|
||||
iter.tr = &global_trace;
|
||||
|
@@ -26,6 +26,7 @@ enum trace_type {
|
||||
TRACE_BOOT_CALL,
|
||||
TRACE_BOOT_RET,
|
||||
TRACE_FN_RET,
|
||||
TRACE_USER_STACK,
|
||||
|
||||
__TRACE_LAST_TYPE
|
||||
};
|
||||
@@ -42,6 +43,7 @@ struct trace_entry {
|
||||
unsigned char flags;
|
||||
unsigned char preempt_count;
|
||||
int pid;
|
||||
int tgid;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -99,6 +101,11 @@ struct stack_entry {
|
||||
unsigned long caller[FTRACE_STACK_ENTRIES];
|
||||
};
|
||||
|
||||
struct userstack_entry {
|
||||
struct trace_entry ent;
|
||||
unsigned long caller[FTRACE_STACK_ENTRIES];
|
||||
};
|
||||
|
||||
/*
|
||||
* ftrace_printk entry:
|
||||
*/
|
||||
@@ -240,6 +247,7 @@ extern void __ftrace_bad_type(void);
|
||||
IF_ASSIGN(var, ent, struct ctx_switch_entry, 0); \
|
||||
IF_ASSIGN(var, ent, struct trace_field_cont, TRACE_CONT); \
|
||||
IF_ASSIGN(var, ent, struct stack_entry, TRACE_STACK); \
|
||||
IF_ASSIGN(var, ent, struct userstack_entry, TRACE_USER_STACK);\
|
||||
IF_ASSIGN(var, ent, struct print_entry, TRACE_PRINT); \
|
||||
IF_ASSIGN(var, ent, struct special_entry, 0); \
|
||||
IF_ASSIGN(var, ent, struct trace_mmiotrace_rw, \
|
||||
@@ -500,6 +508,8 @@ enum trace_iterator_flags {
|
||||
TRACE_ITER_PREEMPTONLY = 0x800,
|
||||
TRACE_ITER_BRANCH = 0x1000,
|
||||
TRACE_ITER_ANNOTATE = 0x2000,
|
||||
TRACE_ITER_USERSTACKTRACE = 0x4000,
|
||||
TRACE_ITER_SYM_USEROBJ = 0x8000
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -18,12 +18,14 @@ struct header_iter {
|
||||
|
||||
static struct trace_array *mmio_trace_array;
|
||||
static bool overrun_detected;
|
||||
static unsigned long prev_overruns;
|
||||
|
||||
static void mmio_reset_data(struct trace_array *tr)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
overrun_detected = false;
|
||||
prev_overruns = 0;
|
||||
tr->time_start = ftrace_now(tr->cpu);
|
||||
|
||||
for_each_online_cpu(cpu)
|
||||
@@ -123,16 +125,12 @@ static void mmio_close(struct trace_iterator *iter)
|
||||
|
||||
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;
|
||||
unsigned long over = ring_buffer_overruns(iter->tr->buffer);
|
||||
|
||||
if (over > prev_overruns)
|
||||
cnt = over - prev_overruns;
|
||||
prev_overruns = over;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user