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

Commit 675eef66 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'tip/perf/core' of...

Merge branch 'tip/perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace into perf/core
parents 03f70388 96de37b6
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -2437,6 +2437,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
	stacktrace	[FTRACE]
	stacktrace	[FTRACE]
			Enabled the stack tracer on boot up.
			Enabled the stack tracer on boot up.


	stacktrace_filter=[function-list]
			[FTRACE] Limit the functions that the stack tracer
			will trace at boot up. function-list is a comma separated
			list of functions. This list can be changed at run
			time by the stack_trace_filter file in the debugfs
			tracing directory. Note, this enables stack tracing
			and the stacktrace above is not needed.

	sti=		[PARISC,HW]
	sti=		[PARISC,HW]
			Format: <num>
			Format: <num>
			Set the STI (builtin display/keyboard on the HP-PARISC
			Set the STI (builtin display/keyboard on the HP-PARISC
+5 −0
Original line number Original line Diff line number Diff line
@@ -50,6 +50,11 @@
# define inline		inline		__attribute__((always_inline))
# define inline		inline		__attribute__((always_inline))
# define __inline__	__inline__	__attribute__((always_inline))
# define __inline__	__inline__	__attribute__((always_inline))
# define __inline	__inline	__attribute__((always_inline))
# define __inline	__inline	__attribute__((always_inline))
#else
/* A lot of inline functions can cause havoc with function tracing */
# define inline		inline		notrace
# define __inline__	__inline__	notrace
# define __inline	__inline	notrace
#endif
#endif


#define __deprecated			__attribute__((deprecated))
#define __deprecated			__attribute__((deprecated))
+72 −5
Original line number Original line Diff line number Diff line
@@ -133,6 +133,8 @@ struct ftrace_func_command {
int ftrace_arch_code_modify_prepare(void);
int ftrace_arch_code_modify_prepare(void);
int ftrace_arch_code_modify_post_process(void);
int ftrace_arch_code_modify_post_process(void);


void ftrace_bug(int err, unsigned long ip);

struct seq_file;
struct seq_file;


struct ftrace_probe_ops {
struct ftrace_probe_ops {
@@ -161,7 +163,6 @@ extern int ftrace_text_reserved(void *start, void *end);


enum {
enum {
	FTRACE_FL_ENABLED	= (1 << 30),
	FTRACE_FL_ENABLED	= (1 << 30),
	FTRACE_FL_FREE		= (1 << 31),
};
};


#define FTRACE_FL_MASK		(0x3UL << 30)
#define FTRACE_FL_MASK		(0x3UL << 30)
@@ -172,10 +173,7 @@ struct dyn_ftrace {
		unsigned long		ip; /* address of mcount call-site */
		unsigned long		ip; /* address of mcount call-site */
		struct dyn_ftrace	*freelist;
		struct dyn_ftrace	*freelist;
	};
	};
	union {
	unsigned long		flags;
	unsigned long		flags;
		struct dyn_ftrace	*newlist;
	};
	struct dyn_arch_ftrace		arch;
	struct dyn_arch_ftrace		arch;
};
};


@@ -190,6 +188,56 @@ void ftrace_set_global_notrace(unsigned char *buf, int len, int reset);
int register_ftrace_command(struct ftrace_func_command *cmd);
int register_ftrace_command(struct ftrace_func_command *cmd);
int unregister_ftrace_command(struct ftrace_func_command *cmd);
int unregister_ftrace_command(struct ftrace_func_command *cmd);


enum {
	FTRACE_UPDATE_CALLS		= (1 << 0),
	FTRACE_DISABLE_CALLS		= (1 << 1),
	FTRACE_UPDATE_TRACE_FUNC	= (1 << 2),
	FTRACE_START_FUNC_RET		= (1 << 3),
	FTRACE_STOP_FUNC_RET		= (1 << 4),
};

enum {
	FTRACE_UPDATE_IGNORE,
	FTRACE_UPDATE_MAKE_CALL,
	FTRACE_UPDATE_MAKE_NOP,
};

enum {
	FTRACE_ITER_FILTER	= (1 << 0),
	FTRACE_ITER_NOTRACE	= (1 << 1),
	FTRACE_ITER_PRINTALL	= (1 << 2),
	FTRACE_ITER_DO_HASH	= (1 << 3),
	FTRACE_ITER_HASH	= (1 << 4),
	FTRACE_ITER_ENABLED	= (1 << 5),
};

void arch_ftrace_update_code(int command);

struct ftrace_rec_iter;

struct ftrace_rec_iter *ftrace_rec_iter_start(void);
struct ftrace_rec_iter *ftrace_rec_iter_next(struct ftrace_rec_iter *iter);
struct dyn_ftrace *ftrace_rec_iter_record(struct ftrace_rec_iter *iter);

int ftrace_update_record(struct dyn_ftrace *rec, int enable);
int ftrace_test_record(struct dyn_ftrace *rec, int enable);
void ftrace_run_stop_machine(int command);
int ftrace_location(unsigned long ip);

extern ftrace_func_t ftrace_trace_function;

int ftrace_regex_open(struct ftrace_ops *ops, int flag,
		  struct inode *inode, struct file *file);
ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf,
			    size_t cnt, loff_t *ppos);
ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf,
			     size_t cnt, loff_t *ppos);
loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int origin);
int ftrace_regex_release(struct inode *inode, struct file *file);

void __init
ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable);

/* 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);
@@ -284,6 +332,25 @@ static inline int ftrace_text_reserved(void *start, void *end)
{
{
	return 0;
	return 0;
}
}

/*
 * Again users of functions that have ftrace_ops may not
 * have them defined when ftrace is not enabled, but these
 * functions may still be called. Use a macro instead of inline.
 */
#define ftrace_regex_open(ops, flag, inod, file) ({ -ENODEV; })
#define ftrace_set_early_filter(ops, buf, enable) do { } while (0)

static inline ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf,
			    size_t cnt, loff_t *ppos) { return -ENODEV; }
static inline ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf,
			     size_t cnt, loff_t *ppos) { return -ENODEV; }
static inline loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int origin)
{
	return -ENODEV;
}
static inline int
ftrace_regex_release(struct inode *inode, struct file *file) { return -ENODEV; }
#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 */
+512 −203

File changed.

Preview size limit exceeded, changes collapsed.

+142 −141
Original line number Original line Diff line number Diff line
@@ -1738,11 +1738,121 @@ static int replace_system_preds(struct event_subsystem *system,
	return -ENOMEM;
	return -ENOMEM;
}
}


static int create_filter_start(char *filter_str, bool set_str,
			       struct filter_parse_state **psp,
			       struct event_filter **filterp)
{
	struct event_filter *filter;
	struct filter_parse_state *ps = NULL;
	int err = 0;

	WARN_ON_ONCE(*psp || *filterp);

	/* allocate everything, and if any fails, free all and fail */
	filter = __alloc_filter();
	if (filter && set_str)
		err = replace_filter_string(filter, filter_str);

	ps = kzalloc(sizeof(*ps), GFP_KERNEL);

	if (!filter || !ps || err) {
		kfree(ps);
		__free_filter(filter);
		return -ENOMEM;
	}

	/* we're committed to creating a new filter */
	*filterp = filter;
	*psp = ps;

	parse_init(ps, filter_ops, filter_str);
	err = filter_parse(ps);
	if (err && set_str)
		append_filter_err(ps, filter);
	return err;
}

static void create_filter_finish(struct filter_parse_state *ps)
{
	if (ps) {
		filter_opstack_clear(ps);
		postfix_clear(ps);
		kfree(ps);
	}
}

/**
 * create_filter - create a filter for a ftrace_event_call
 * @call: ftrace_event_call to create a filter for
 * @filter_str: filter string
 * @set_str: remember @filter_str and enable detailed error in filter
 * @filterp: out param for created filter (always updated on return)
 *
 * Creates a filter for @call with @filter_str.  If @set_str is %true,
 * @filter_str is copied and recorded in the new filter.
 *
 * On success, returns 0 and *@filterp points to the new filter.  On
 * failure, returns -errno and *@filterp may point to %NULL or to a new
 * filter.  In the latter case, the returned filter contains error
 * information if @set_str is %true and the caller is responsible for
 * freeing it.
 */
static int create_filter(struct ftrace_event_call *call,
			 char *filter_str, bool set_str,
			 struct event_filter **filterp)
{
	struct event_filter *filter = NULL;
	struct filter_parse_state *ps = NULL;
	int err;

	err = create_filter_start(filter_str, set_str, &ps, &filter);
	if (!err) {
		err = replace_preds(call, filter, ps, filter_str, false);
		if (err && set_str)
			append_filter_err(ps, filter);
	}
	create_filter_finish(ps);

	*filterp = filter;
	return err;
}

/**
 * create_system_filter - create a filter for an event_subsystem
 * @system: event_subsystem to create a filter for
 * @filter_str: filter string
 * @filterp: out param for created filter (always updated on return)
 *
 * Identical to create_filter() except that it creates a subsystem filter
 * and always remembers @filter_str.
 */
static int create_system_filter(struct event_subsystem *system,
				char *filter_str, struct event_filter **filterp)
{
	struct event_filter *filter = NULL;
	struct filter_parse_state *ps = NULL;
	int err;

	err = create_filter_start(filter_str, true, &ps, &filter);
	if (!err) {
		err = replace_system_preds(system, ps, filter_str);
		if (!err) {
			/* System filters just show a default message */
			kfree(filter->filter_string);
			filter->filter_string = NULL;
		} else {
			append_filter_err(ps, filter);
		}
	}
	create_filter_finish(ps);

	*filterp = filter;
	return err;
}

int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
{
{
	struct filter_parse_state *ps;
	struct event_filter *filter;
	struct event_filter *filter;
	struct event_filter *tmp;
	int err = 0;
	int err = 0;


	mutex_lock(&event_mutex);
	mutex_lock(&event_mutex);
@@ -1759,49 +1869,30 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
		goto out_unlock;
		goto out_unlock;
	}
	}


	err = -ENOMEM;
	err = create_filter(call, filter_string, true, &filter);
	ps = kzalloc(sizeof(*ps), GFP_KERNEL);
	if (!ps)
		goto out_unlock;

	filter = __alloc_filter();
	if (!filter) {
		kfree(ps);
		goto out_unlock;
	}

	replace_filter_string(filter, filter_string);


	parse_init(ps, filter_ops, filter_string);
	err = filter_parse(ps);
	if (err) {
		append_filter_err(ps, filter);
		goto out;
	}

	err = replace_preds(call, filter, ps, filter_string, false);
	if (err) {
		filter_disable(call);
		append_filter_err(ps, filter);
	} else
		call->flags |= TRACE_EVENT_FL_FILTERED;
out:
	/*
	/*
	 * Always swap the call filter with the new filter
	 * Always swap the call filter with the new filter
	 * even if there was an error. If there was an error
	 * even if there was an error. If there was an error
	 * in the filter, we disable the filter and show the error
	 * in the filter, we disable the filter and show the error
	 * string
	 * string
	 */
	 */
	tmp = call->filter;
	if (filter) {
		struct event_filter *tmp = call->filter;

		if (!err)
			call->flags |= TRACE_EVENT_FL_FILTERED;
		else
			filter_disable(call);

		rcu_assign_pointer(call->filter, filter);
		rcu_assign_pointer(call->filter, filter);

		if (tmp) {
		if (tmp) {
			/* Make sure the call is done with the filter */
			/* Make sure the call is done with the filter */
			synchronize_sched();
			synchronize_sched();
			__free_filter(tmp);
			__free_filter(tmp);
		}
		}
	filter_opstack_clear(ps);
	}
	postfix_clear(ps);
	kfree(ps);
out_unlock:
out_unlock:
	mutex_unlock(&event_mutex);
	mutex_unlock(&event_mutex);


@@ -1811,7 +1902,6 @@ out_unlock:
int apply_subsystem_event_filter(struct event_subsystem *system,
int apply_subsystem_event_filter(struct event_subsystem *system,
				 char *filter_string)
				 char *filter_string)
{
{
	struct filter_parse_state *ps;
	struct event_filter *filter;
	struct event_filter *filter;
	int err = 0;
	int err = 0;


@@ -1835,48 +1925,19 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
		goto out_unlock;
		goto out_unlock;
	}
	}


	err = -ENOMEM;
	err = create_system_filter(system, filter_string, &filter);
	ps = kzalloc(sizeof(*ps), GFP_KERNEL);
	if (filter) {
	if (!ps)
		goto out_unlock;

	filter = __alloc_filter();
	if (!filter)
		goto out;

	/* System filters just show a default message */
	kfree(filter->filter_string);
	filter->filter_string = NULL;

		/*
		/*
		 * No event actually uses the system filter
		 * No event actually uses the system filter
		 * we can free it without synchronize_sched().
		 * we can free it without synchronize_sched().
		 */
		 */
		__free_filter(system->filter);
		__free_filter(system->filter);
		system->filter = filter;
		system->filter = filter;

	}
	parse_init(ps, filter_ops, filter_string);
	err = filter_parse(ps);
	if (err)
		goto err_filter;

	err = replace_system_preds(system, ps, filter_string);
	if (err)
		goto err_filter;

out:
	filter_opstack_clear(ps);
	postfix_clear(ps);
	kfree(ps);
out_unlock:
out_unlock:
	mutex_unlock(&event_mutex);
	mutex_unlock(&event_mutex);


	return err;
	return err;

err_filter:
	replace_filter_string(filter, filter_string);
	append_filter_err(ps, system->filter);
	goto out;
}
}


#ifdef CONFIG_PERF_EVENTS
#ifdef CONFIG_PERF_EVENTS
@@ -1894,7 +1955,6 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
{
{
	int err;
	int err;
	struct event_filter *filter;
	struct event_filter *filter;
	struct filter_parse_state *ps;
	struct ftrace_event_call *call;
	struct ftrace_event_call *call;


	mutex_lock(&event_mutex);
	mutex_lock(&event_mutex);
@@ -1909,33 +1969,10 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
	if (event->filter)
	if (event->filter)
		goto out_unlock;
		goto out_unlock;


	filter = __alloc_filter();
	err = create_filter(call, filter_str, false, &filter);
	if (!filter) {
		err = PTR_ERR(filter);
		goto out_unlock;
	}

	err = -ENOMEM;
	ps = kzalloc(sizeof(*ps), GFP_KERNEL);
	if (!ps)
		goto free_filter;

	parse_init(ps, filter_ops, filter_str);
	err = filter_parse(ps);
	if (err)
		goto free_ps;

	err = replace_preds(call, filter, ps, filter_str, false);
	if (!err)
	if (!err)
		event->filter = filter;
		event->filter = filter;

	else
free_ps:
	filter_opstack_clear(ps);
	postfix_clear(ps);
	kfree(ps);

free_filter:
	if (err)
		__free_filter(filter);
		__free_filter(filter);


out_unlock:
out_unlock:
@@ -1954,43 +1991,6 @@ out_unlock:
#define CREATE_TRACE_POINTS
#define CREATE_TRACE_POINTS
#include "trace_events_filter_test.h"
#include "trace_events_filter_test.h"


static int test_get_filter(char *filter_str, struct ftrace_event_call *call,
			   struct event_filter **pfilter)
{
	struct event_filter *filter;
	struct filter_parse_state *ps;
	int err = -ENOMEM;

	filter = __alloc_filter();
	if (!filter)
		goto out;

	ps = kzalloc(sizeof(*ps), GFP_KERNEL);
	if (!ps)
		goto free_filter;

	parse_init(ps, filter_ops, filter_str);
	err = filter_parse(ps);
	if (err)
		goto free_ps;

	err = replace_preds(call, filter, ps, filter_str, false);
	if (!err)
		*pfilter = filter;

 free_ps:
	filter_opstack_clear(ps);
	postfix_clear(ps);
	kfree(ps);

 free_filter:
	if (err)
		__free_filter(filter);

 out:
	return err;
}

#define DATA_REC(m, va, vb, vc, vd, ve, vf, vg, vh, nvisit) \
#define DATA_REC(m, va, vb, vc, vd, ve, vf, vg, vh, nvisit) \
{ \
{ \
	.filter = FILTER, \
	.filter = FILTER, \
@@ -2109,12 +2109,13 @@ static __init int ftrace_test_event_filter(void)
		struct test_filter_data_t *d = &test_filter_data[i];
		struct test_filter_data_t *d = &test_filter_data[i];
		int err;
		int err;


		err = test_get_filter(d->filter, &event_ftrace_test_filter,
		err = create_filter(&event_ftrace_test_filter, d->filter,
				      &filter);
				    false, &filter);
		if (err) {
		if (err) {
			printk(KERN_INFO
			printk(KERN_INFO
			       "Failed to get filter for '%s', err %d\n",
			       "Failed to get filter for '%s', err %d\n",
			       d->filter, err);
			       d->filter, err);
			__free_filter(filter);
			break;
			break;
		}
		}


Loading