lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <87txh2okn9.fsf@sejong.aot.lge.com>
Date:	Mon, 30 Sep 2013 16:04:26 +0900
From:	Namhyung Kim <namhyung@...nel.org>
To:	Steven Rostedt <rostedt@...dmis.org>
Cc:	Frederic Weisbecker <fweisbec@...il.com>,
	Ingo Molnar <mingo@...nel.org>,
	LKML <linux-kernel@...r.kernel.org>,
	Namhyung Kim <namhyung.kim@....com>
Subject: Re: [RFC/PATCH] ftrace: add set_graph_notrace filter

Ping!

On Tue,  3 Sep 2013 14:05:08 +0900, Namhyung Kim wrote:
> From: Namhyung Kim <namhyung.kim@....com>
>
> The set_graph_notrace filter is analogous to set_ftrace_notrace and
> can be used for eliminating uninteresting part of function graph trace
> output.  It also works with set_graph_function nicely.
>
>   # cd /sys/kernel/debug/tracing/
>   # echo do_page_fault > set_graph_function
>   # perf ftrace live true
>    2)               |  do_page_fault() {
>    2)               |    __do_page_fault() {
>    2)   0.381 us    |      down_read_trylock();
>    2)   0.055 us    |      __might_sleep();
>    2)   0.696 us    |      find_vma();
>    2)               |      handle_mm_fault() {
>    2)               |        handle_pte_fault() {
>    2)               |          __do_fault() {
>    2)               |            filemap_fault() {
>    2)               |              find_get_page() {
>    2)   0.033 us    |                __rcu_read_lock();
>    2)   0.035 us    |                __rcu_read_unlock();
>    2)   1.696 us    |              }
>    2)   0.031 us    |              __might_sleep();
>    2)   2.831 us    |            }
>    2)               |            _raw_spin_lock() {
>    2)   0.046 us    |              add_preempt_count();
>    2)   0.841 us    |            }
>    2)   0.033 us    |            page_add_file_rmap();
>    2)               |            _raw_spin_unlock() {
>    2)   0.057 us    |              sub_preempt_count();
>    2)   0.568 us    |            }
>    2)               |            unlock_page() {
>    2)   0.084 us    |              page_waitqueue();
>    2)   0.126 us    |              __wake_up_bit();
>    2)   1.117 us    |            }
>    2)   7.729 us    |          }
>    2)   8.397 us    |        }
>    2)   8.956 us    |      }
>    2)   0.085 us    |      up_read();
>    2) + 12.745 us   |    }
>    2) + 13.401 us   |  }
>   ...
>
>   # echo handle_mm_fault > set_graph_notrace
>   # perf ftrace live true
>    1)               |  do_page_fault() {
>    1)               |    __do_page_fault() {
>    1)   0.205 us    |      down_read_trylock();
>    1)   0.041 us    |      __might_sleep();
>    1)   0.344 us    |      find_vma();
>    1)   0.069 us    |      up_read();
>    1)   4.692 us    |    }
>    1)   5.311 us    |  }
>   ...
>
> Signed-off-by: Namhyung Kim <namhyung@...nel.org>
> ---
>  include/linux/ftrace.h               |   1 +
>  kernel/trace/ftrace.c                | 118 ++++++++++++++++++++++++++++++++++-
>  kernel/trace/trace.h                 |  23 +++++++
>  kernel/trace/trace_functions_graph.c |  21 ++++++-
>  4 files changed, 159 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
> index 9f15c0064c50..ec85d48619e1 100644
> --- a/include/linux/ftrace.h
> +++ b/include/linux/ftrace.h
> @@ -721,6 +721,7 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
>  extern char __irqentry_text_start[];
>  extern char __irqentry_text_end[];
>  
> +#define FTRACE_NOTRACE_DEPTH 65536
>  #define FTRACE_RETFUNC_DEPTH 50
>  #define FTRACE_RETSTACK_ALLOC_SIZE 32
>  extern int register_ftrace_graph(trace_func_graph_ret_t retfunc,
> diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
> index a6d098c6df3f..1b1f3409f788 100644
> --- a/kernel/trace/ftrace.c
> +++ b/kernel/trace/ftrace.c
> @@ -3819,6 +3819,43 @@ static const struct seq_operations ftrace_graph_seq_ops = {
>  	.show = g_show,
>  };
>  
> +int ftrace_graph_notrace_count;
> +int ftrace_graph_notrace_enabled;
> +unsigned long ftrace_graph_notrace_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
> +
> +static void *
> +__n_next(struct seq_file *m, loff_t *pos)
> +{
> +	if (*pos >= ftrace_graph_notrace_count)
> +		return NULL;
> +	return &ftrace_graph_notrace_funcs[*pos];
> +}
> +
> +static void *
> +n_next(struct seq_file *m, void *v, loff_t *pos)
> +{
> +	(*pos)++;
> +	return __n_next(m, pos);
> +}
> +
> +static void *n_start(struct seq_file *m, loff_t *pos)
> +{
> +	mutex_lock(&graph_lock);
> +
> +	/* Nothing, tell g_show to print all functions are enabled */
> +	if (!ftrace_graph_notrace_enabled && !*pos)
> +		return (void *)1;
> +
> +	return __n_next(m, pos);
> +}
> +
> +static const struct seq_operations ftrace_graph_notrace_seq_ops = {
> +	.start = n_start,
> +	.next = n_next,
> +	.stop = g_stop,
> +	.show = g_show,
> +};
> +
>  static int
>  ftrace_graph_open(struct inode *inode, struct file *file)
>  {
> @@ -3843,6 +3880,30 @@ ftrace_graph_open(struct inode *inode, struct file *file)
>  }
>  
>  static int
> +ftrace_graph_notrace_open(struct inode *inode, struct file *file)
> +{
> +	int ret = 0;
> +
> +	if (unlikely(ftrace_disabled))
> +		return -ENODEV;
> +
> +	mutex_lock(&graph_lock);
> +	if ((file->f_mode & FMODE_WRITE) &&
> +	    (file->f_flags & O_TRUNC)) {
> +		ftrace_graph_notrace_enabled = 0;
> +		ftrace_graph_notrace_count = 0;
> +		memset(ftrace_graph_notrace_funcs, 0,
> +		       sizeof(ftrace_graph_notrace_funcs));
> +	}
> +	mutex_unlock(&graph_lock);
> +
> +	if (file->f_mode & FMODE_READ)
> +		ret = seq_open(file, &ftrace_graph_notrace_seq_ops);
> +
> +	return ret;
> +}
> +
> +static int
>  ftrace_graph_release(struct inode *inode, struct file *file)
>  {
>  	if (file->f_mode & FMODE_READ)
> @@ -3910,8 +3971,6 @@ out:
>  	if (fail)
>  		return -EINVAL;
>  
> -	ftrace_graph_filter_enabled = !!(*idx);
> -
>  	return 0;
>  }
>  
> @@ -3946,6 +4005,50 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
>  
>  	ret = read;
>  
> +	ftrace_graph_filter_enabled = ftrace_graph_count > 0;
> +
> +out_free:
> +	trace_parser_put(&parser);
> +out_unlock:
> +	mutex_unlock(&graph_lock);
> +
> +	return ret;
> +}
> +
> +static ssize_t
> +ftrace_graph_notrace_write(struct file *file, const char __user *ubuf,
> +			   size_t cnt, loff_t *ppos)
> +{
> +	struct trace_parser parser;
> +	ssize_t read, ret;
> +
> +	if (!cnt)
> +		return 0;
> +
> +	mutex_lock(&graph_lock);
> +
> +	if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) {
> +		ret = -ENOMEM;
> +		goto out_unlock;
> +	}
> +
> +	read = trace_get_user(&parser, ubuf, cnt, ppos);
> +
> +	if (read >= 0 && trace_parser_loaded((&parser))) {
> +		parser.buffer[parser.idx] = 0;
> +
> +		/* we allow only one expression at a time */
> +		ret = ftrace_set_func(ftrace_graph_notrace_funcs,
> +				      &ftrace_graph_notrace_count,
> +				      parser.buffer);
> +		if (ret)
> +			goto out_free;
> +	}
> +
> +	ret = read;
> +
> +	ftrace_graph_notrace_enabled = ftrace_graph_notrace_count > 0;
> +
>  out_free:
>  	trace_parser_put(&parser);
>  out_unlock:
> @@ -3961,6 +4064,14 @@ static const struct file_operations ftrace_graph_fops = {
>  	.llseek		= ftrace_filter_lseek,
>  	.release	= ftrace_graph_release,
>  };
> +
> +static const struct file_operations ftrace_graph_notrace_fops = {
> +	.open		= ftrace_graph_notrace_open,
> +	.read		= seq_read,
> +	.write		= ftrace_graph_notrace_write,
> +	.llseek		= ftrace_filter_lseek,
> +	.release	= ftrace_graph_release,
> +};
>  #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
>  
>  static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
> @@ -3982,6 +4093,9 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)
>  	trace_create_file("set_graph_function", 0444, d_tracer,
>  				    NULL,
>  				    &ftrace_graph_fops);
> +	trace_create_file("set_graph_notrace", 0444, d_tracer,
> +				    NULL,
> +				    &ftrace_graph_notrace_fops);
>  #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
>  
>  	return 0;
> diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
> index fe39acd4c1aa..797f6f7f3f56 100644
> --- a/kernel/trace/trace.h
> +++ b/kernel/trace/trace.h
> @@ -732,6 +732,9 @@ extern void __trace_graph_return(struct trace_array *tr,
>  extern int ftrace_graph_filter_enabled;
>  extern int ftrace_graph_count;
>  extern unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS];
> +extern int ftrace_graph_notrace_enabled;
> +extern int ftrace_graph_notrace_count;
> +extern unsigned long ftrace_graph_notrace_funcs[FTRACE_GRAPH_MAX_FUNCS];
>  
>  static inline int ftrace_graph_addr(unsigned long addr)
>  {
> @@ -757,11 +760,31 @@ static inline int ftrace_graph_addr(unsigned long addr)
>  
>  	return 0;
>  }
> +
> +static inline int ftrace_graph_notrace_addr(unsigned long addr)
> +{
> +	int i;
> +
> +	if (!ftrace_graph_notrace_enabled)
> +		return 0;
> +
> +	for (i = 0; i < ftrace_graph_notrace_count; i++) {
> +		if (addr == ftrace_graph_notrace_funcs[i])
> +			return 1;
> +	}
> +
> +	return 0;
> +}
>  #else
>  static inline int ftrace_graph_addr(unsigned long addr)
>  {
>  	return 1;
>  }
> +
> +static inline int ftrace_graph_notrace_addr(unsigned long addr)
> +{
> +	return 0;
> +}
>  #endif /* CONFIG_DYNAMIC_FTRACE */
>  #else /* CONFIG_FUNCTION_GRAPH_TRACER */
>  static inline enum print_line_t
> diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
> index b5c09242683d..3ba240daa5e0 100644
> --- a/kernel/trace/trace_functions_graph.c
> +++ b/kernel/trace/trace_functions_graph.c
> @@ -114,16 +114,22 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
>  		return -EBUSY;
>  	}
>  
> +	/* The function was filtered out */
> +	if (current->curr_ret_stack < -1)
> +		return -EBUSY;
> +
>  	calltime = trace_clock_local();
>  
>  	index = ++current->curr_ret_stack;
> +	if (ftrace_graph_notrace_addr(func))
> +		current->curr_ret_stack -= FTRACE_NOTRACE_DEPTH;
>  	barrier();
>  	current->ret_stack[index].ret = ret;
>  	current->ret_stack[index].func = func;
>  	current->ret_stack[index].calltime = calltime;
>  	current->ret_stack[index].subtime = 0;
>  	current->ret_stack[index].fp = frame_pointer;
> -	*depth = index;
> +	*depth = current->curr_ret_stack;
>  
>  	return 0;
>  }
> @@ -137,6 +143,9 @@ ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret,
>  
>  	index = current->curr_ret_stack;
>  
> +	if (index < 0)
> +		index += FTRACE_NOTRACE_DEPTH;
> +
>  	if (unlikely(index < 0)) {
>  		ftrace_graph_stop();
>  		WARN_ON(1);
> @@ -193,6 +202,10 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
>  	trace.rettime = trace_clock_local();
>  	barrier();
>  	current->curr_ret_stack--;
> +	if (current->curr_ret_stack < -1) {
> +		current->curr_ret_stack += FTRACE_NOTRACE_DEPTH;
> +		return ret;
> +	}
>  
>  	/*
>  	 * The trace should run after decrementing the ret counter
> @@ -259,10 +272,14 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
>  
>  	/* trace it when it is-nested-in or is a function enabled. */
>  	if ((!(trace->depth || ftrace_graph_addr(trace->func)) ||
> -	     ftrace_graph_ignore_irqs()) ||
> +	     ftrace_graph_ignore_irqs()) || (trace->depth < 0) ||
>  	    (max_depth && trace->depth >= max_depth))
>  		return 0;
>  
> +	/* need to reserve a ret_stack entry to recover the depth */
> +	if (ftrace_graph_notrace_addr(trace->func))
> +		return 1;
> +
>  	local_irq_save(flags);
>  	cpu = raw_smp_processor_id();
>  	data = per_cpu_ptr(tr->trace_buffer.data, cpu);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ