Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f492d3f8 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'tip/tracing/ftrace' of...

Merge branch 'tip/tracing/ftrace' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into tracing/ftrace
parents c4e2b432 e110e3d1
Loading
Loading
Loading
Loading
+40 −0
Original line number Original line Diff line number Diff line
@@ -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 */
+2 −0
Original line number Original line Diff line number Diff line
@@ -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);
+732 −197

File changed.

Preview size limit exceeded, changes collapsed.

+9 −0
Original line number Original line Diff line number Diff line
@@ -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 */
+163 −0
Original line number Original line Diff line number Diff line
@@ -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(&param, ":");

	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);