Merge branch 'tip/tracing/ftrace' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into tracing/ftrace
This commit is contained in:
@@ -95,10 +95,41 @@ stack_trace_sysctl(struct ctl_table *table, int write,
|
|||||||
loff_t *ppos);
|
loff_t *ppos);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct ftrace_func_command {
|
||||||
|
struct list_head list;
|
||||||
|
char *name;
|
||||||
|
int (*func)(char *func, char *cmd,
|
||||||
|
char *params, int enable);
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||||
/* asm/ftrace.h must be defined for archs supporting dynamic ftrace */
|
/* asm/ftrace.h must be defined for archs supporting dynamic ftrace */
|
||||||
#include <asm/ftrace.h>
|
#include <asm/ftrace.h>
|
||||||
|
|
||||||
|
struct seq_file;
|
||||||
|
|
||||||
|
struct ftrace_hook_ops {
|
||||||
|
void (*func)(unsigned long ip,
|
||||||
|
unsigned long parent_ip,
|
||||||
|
void **data);
|
||||||
|
int (*callback)(unsigned long ip, void **data);
|
||||||
|
void (*free)(void **data);
|
||||||
|
int (*print)(struct seq_file *m,
|
||||||
|
unsigned long ip,
|
||||||
|
struct ftrace_hook_ops *ops,
|
||||||
|
void *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int
|
||||||
|
register_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops,
|
||||||
|
void *data);
|
||||||
|
extern void
|
||||||
|
unregister_ftrace_function_hook(char *glob, struct ftrace_hook_ops *ops,
|
||||||
|
void *data);
|
||||||
|
extern void
|
||||||
|
unregister_ftrace_function_hook_func(char *glob, struct ftrace_hook_ops *ops);
|
||||||
|
extern void unregister_ftrace_function_hook_all(char *glob);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
FTRACE_FL_FREE = (1 << 0),
|
FTRACE_FL_FREE = (1 << 0),
|
||||||
FTRACE_FL_FAILED = (1 << 1),
|
FTRACE_FL_FAILED = (1 << 1),
|
||||||
@@ -119,6 +150,9 @@ struct dyn_ftrace {
|
|||||||
int ftrace_force_update(void);
|
int ftrace_force_update(void);
|
||||||
void ftrace_set_filter(unsigned char *buf, int len, int reset);
|
void ftrace_set_filter(unsigned char *buf, int len, int reset);
|
||||||
|
|
||||||
|
int register_ftrace_command(struct ftrace_func_command *cmd);
|
||||||
|
int unregister_ftrace_command(struct ftrace_func_command *cmd);
|
||||||
|
|
||||||
/* defined in arch */
|
/* defined in arch */
|
||||||
extern int ftrace_ip_converted(unsigned long ip);
|
extern int ftrace_ip_converted(unsigned long ip);
|
||||||
extern int ftrace_dyn_arch_init(void *data);
|
extern int ftrace_dyn_arch_init(void *data);
|
||||||
@@ -202,6 +236,12 @@ extern void ftrace_enable_daemon(void);
|
|||||||
# define ftrace_disable_daemon() do { } while (0)
|
# define ftrace_disable_daemon() do { } while (0)
|
||||||
# define ftrace_enable_daemon() do { } while (0)
|
# define ftrace_enable_daemon() do { } while (0)
|
||||||
static inline void ftrace_release(void *start, unsigned long size) { }
|
static inline void ftrace_release(void *start, unsigned long size) { }
|
||||||
|
static inline int register_ftrace_command(struct ftrace_func_command *cmd)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline int unregister_ftrace_command(char *cmd_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||||
|
|
||||||
/* totally disable ftrace - can not re-enable after this */
|
/* totally disable ftrace - can not re-enable after this */
|
||||||
|
@@ -128,10 +128,12 @@ void ring_buffer_normalize_time_stamp(int cpu, u64 *ts);
|
|||||||
void tracing_on(void);
|
void tracing_on(void);
|
||||||
void tracing_off(void);
|
void tracing_off(void);
|
||||||
void tracing_off_permanent(void);
|
void tracing_off_permanent(void);
|
||||||
|
int tracing_is_on(void);
|
||||||
#else
|
#else
|
||||||
static inline void tracing_on(void) { }
|
static inline void tracing_on(void) { }
|
||||||
static inline void tracing_off(void) { }
|
static inline void tracing_off(void) { }
|
||||||
static inline void tracing_off_permanent(void) { }
|
static inline void tracing_off_permanent(void) { }
|
||||||
|
static inline int tracing_is_on(void) { return 0; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void *ring_buffer_alloc_read_page(struct ring_buffer *buffer);
|
void *ring_buffer_alloc_read_page(struct ring_buffer *buffer);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -98,6 +98,15 @@ void tracing_off_permanent(void)
|
|||||||
set_bit(RB_BUFFERS_DISABLED_BIT, &ring_buffer_flags);
|
set_bit(RB_BUFFERS_DISABLED_BIT, &ring_buffer_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tracing_is_on - show state of ring buffers enabled
|
||||||
|
*/
|
||||||
|
int tracing_is_on(void)
|
||||||
|
{
|
||||||
|
return ring_buffer_flags == RB_BUFFERS_ON;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tracing_is_on);
|
||||||
|
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
/* Up this if you want to test the TIME_EXTENTS and normalization */
|
/* Up this if you want to test the TIME_EXTENTS and normalization */
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
* Copyright (C) 2004-2006 Ingo Molnar
|
* Copyright (C) 2004-2006 Ingo Molnar
|
||||||
* Copyright (C) 2004 William Lee Irwin III
|
* Copyright (C) 2004 William Lee Irwin III
|
||||||
*/
|
*/
|
||||||
|
#include <linux/ring_buffer.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/ftrace.h>
|
#include <linux/ftrace.h>
|
||||||
@@ -231,9 +232,171 @@ static struct tracer function_trace __read_mostly =
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||||
|
static void
|
||||||
|
ftrace_traceon(unsigned long ip, unsigned long parent_ip, void **data)
|
||||||
|
{
|
||||||
|
long *count = (long *)data;
|
||||||
|
|
||||||
|
if (tracing_is_on())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!*count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (*count != -1)
|
||||||
|
(*count)--;
|
||||||
|
|
||||||
|
tracing_on();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ftrace_traceoff(unsigned long ip, unsigned long parent_ip, void **data)
|
||||||
|
{
|
||||||
|
long *count = (long *)data;
|
||||||
|
|
||||||
|
if (!tracing_is_on())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!*count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (*count != -1)
|
||||||
|
(*count)--;
|
||||||
|
|
||||||
|
tracing_off();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip,
|
||||||
|
struct ftrace_hook_ops *ops, void *data);
|
||||||
|
|
||||||
|
static struct ftrace_hook_ops traceon_hook_ops = {
|
||||||
|
.func = ftrace_traceon,
|
||||||
|
.print = ftrace_trace_onoff_print,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ftrace_hook_ops traceoff_hook_ops = {
|
||||||
|
.func = ftrace_traceoff,
|
||||||
|
.print = ftrace_trace_onoff_print,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip,
|
||||||
|
struct ftrace_hook_ops *ops, void *data)
|
||||||
|
{
|
||||||
|
char str[KSYM_SYMBOL_LEN];
|
||||||
|
long count = (long)data;
|
||||||
|
|
||||||
|
kallsyms_lookup(ip, NULL, NULL, NULL, str);
|
||||||
|
seq_printf(m, "%s:", str);
|
||||||
|
|
||||||
|
if (ops == &traceon_hook_ops)
|
||||||
|
seq_printf(m, "traceon");
|
||||||
|
else
|
||||||
|
seq_printf(m, "traceoff");
|
||||||
|
|
||||||
|
if (count != -1)
|
||||||
|
seq_printf(m, ":count=%ld", count);
|
||||||
|
seq_putc(m, '\n');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ftrace_trace_onoff_unreg(char *glob, char *cmd, char *param)
|
||||||
|
{
|
||||||
|
struct ftrace_hook_ops *ops;
|
||||||
|
|
||||||
|
/* we register both traceon and traceoff to this callback */
|
||||||
|
if (strcmp(cmd, "traceon") == 0)
|
||||||
|
ops = &traceon_hook_ops;
|
||||||
|
else
|
||||||
|
ops = &traceoff_hook_ops;
|
||||||
|
|
||||||
|
unregister_ftrace_function_hook_func(glob, ops);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable)
|
||||||
|
{
|
||||||
|
struct ftrace_hook_ops *ops;
|
||||||
|
void *count = (void *)-1;
|
||||||
|
char *number;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* hash funcs only work with set_ftrace_filter */
|
||||||
|
if (!enable)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (glob[0] == '!')
|
||||||
|
return ftrace_trace_onoff_unreg(glob+1, cmd, param);
|
||||||
|
|
||||||
|
/* we register both traceon and traceoff to this callback */
|
||||||
|
if (strcmp(cmd, "traceon") == 0)
|
||||||
|
ops = &traceon_hook_ops;
|
||||||
|
else
|
||||||
|
ops = &traceoff_hook_ops;
|
||||||
|
|
||||||
|
if (!param)
|
||||||
|
goto out_reg;
|
||||||
|
|
||||||
|
number = strsep(¶m, ":");
|
||||||
|
|
||||||
|
if (!strlen(number))
|
||||||
|
goto out_reg;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use the callback data field (which is a pointer)
|
||||||
|
* as our counter.
|
||||||
|
*/
|
||||||
|
ret = strict_strtoul(number, 0, (unsigned long *)&count);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
out_reg:
|
||||||
|
ret = register_ftrace_function_hook(glob, ops, count);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ftrace_func_command ftrace_traceon_cmd = {
|
||||||
|
.name = "traceon",
|
||||||
|
.func = ftrace_trace_onoff_callback,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ftrace_func_command ftrace_traceoff_cmd = {
|
||||||
|
.name = "traceoff",
|
||||||
|
.func = ftrace_trace_onoff_callback,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init init_func_cmd_traceon(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = register_ftrace_command(&ftrace_traceoff_cmd);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = register_ftrace_command(&ftrace_traceon_cmd);
|
||||||
|
if (ret)
|
||||||
|
unregister_ftrace_command(&ftrace_traceoff_cmd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline int init_func_cmd_traceon(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||||
|
|
||||||
static __init int init_function_trace(void)
|
static __init int init_function_trace(void)
|
||||||
{
|
{
|
||||||
|
init_func_cmd_traceon();
|
||||||
return register_tracer(&function_trace);
|
return register_tracer(&function_trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
device_initcall(init_function_trace);
|
device_initcall(init_function_trace);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user