diff options
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/Makefile | 2 | ||||
| -rw-r--r-- | kernel/trace/blktrace.c | 1 | ||||
| -rw-r--r-- | kernel/trace/ftrace.c | 31 | ||||
| -rw-r--r-- | kernel/trace/power-traces.c | 1 | ||||
| -rw-r--r-- | kernel/trace/ring_buffer.c | 39 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 51 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 5 | ||||
| -rw-r--r-- | kernel/trace/trace_clock.c | 5 | ||||
| -rw-r--r-- | kernel/trace/trace_event_perf.c (renamed from kernel/trace/trace_event_profile.c) | 63 | ||||
| -rw-r--r-- | kernel/trace/trace_events.c | 3 | ||||
| -rw-r--r-- | kernel/trace/trace_events_filter.c | 1 | ||||
| -rw-r--r-- | kernel/trace/trace_functions_graph.c | 28 | ||||
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 29 | ||||
| -rw-r--r-- | kernel/trace/trace_ksym.c | 1 | ||||
| -rw-r--r-- | kernel/trace/trace_mmiotrace.c | 1 | ||||
| -rw-r--r-- | kernel/trace/trace_selftest.c | 1 | ||||
| -rw-r--r-- | kernel/trace/trace_stat.c | 1 | ||||
| -rw-r--r-- | kernel/trace/trace_syscalls.c | 73 | ||||
| -rw-r--r-- | kernel/trace/trace_workqueue.c | 1 | 
19 files changed, 214 insertions, 123 deletions
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index d00c6fe23f5..78edc649003 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -52,7 +52,7 @@ obj-$(CONFIG_EVENT_TRACING) += trace_events.o  obj-$(CONFIG_EVENT_TRACING) += trace_export.o  obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o  ifeq ($(CONFIG_PERF_EVENTS),y) -obj-$(CONFIG_EVENT_TRACING) += trace_event_profile.o +obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o  endif  obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o  obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 07f945a9943..b3bc91a3f51 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -21,6 +21,7 @@  #include <linux/percpu.h>  #include <linux/init.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <linux/debugfs.h>  #include <linux/smp_lock.h>  #include <linux/time.h> diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 83783579378..2404b59b309 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -24,9 +24,11 @@  #include <linux/uaccess.h>  #include <linux/ftrace.h>  #include <linux/sysctl.h> +#include <linux/slab.h>  #include <linux/ctype.h>  #include <linux/list.h>  #include <linux/hash.h> +#include <linux/rcupdate.h>  #include <trace/events/sched.h> @@ -84,22 +86,22 @@ ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;  ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;  ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub; -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -static int ftrace_set_func(unsigned long *array, int *idx, char *buffer); -#endif - +/* + * Traverse the ftrace_list, invoking all entries.  The reason that we + * can use rcu_dereference_raw() is that elements removed from this list + * are simply leaked, so there is no need to interact with a grace-period + * mechanism.  The rcu_dereference_raw() calls are needed to handle + * concurrent insertions into the ftrace_list. + * + * Silly Alpha and silly pointer-speculation compiler optimizations! + */  static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)  { -	struct ftrace_ops *op = ftrace_list; - -	/* in case someone actually ports this to alpha! */ -	read_barrier_depends(); +	struct ftrace_ops *op = rcu_dereference_raw(ftrace_list); /*see above*/  	while (op != &ftrace_list_end) { -		/* silly alpha */ -		read_barrier_depends();  		op->func(ip, parent_ip); -		op = op->next; +		op = rcu_dereference_raw(op->next); /*see above*/  	};  } @@ -154,8 +156,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops)  	 * the ops->next pointer is valid before another CPU sees  	 * the ops pointer included into the ftrace_list.  	 */ -	smp_wmb(); -	ftrace_list = ops; +	rcu_assign_pointer(ftrace_list, ops);  	if (ftrace_enabled) {  		ftrace_func_t func; @@ -2276,6 +2277,8 @@ __setup("ftrace_filter=", set_ftrace_filter);  #ifdef CONFIG_FUNCTION_GRAPH_TRACER  static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata; +static int ftrace_set_func(unsigned long *array, int *idx, char *buffer); +  static int __init set_graph_function(char *str)  {  	strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE); @@ -3351,6 +3354,7 @@ void ftrace_graph_init_task(struct task_struct *t)  {  	/* Make sure we do not use the parent ret_stack */  	t->ret_stack = NULL; +	t->curr_ret_stack = -1;  	if (ftrace_graph_active) {  		struct ftrace_ret_stack *ret_stack; @@ -3360,7 +3364,6 @@ void ftrace_graph_init_task(struct task_struct *t)  				GFP_KERNEL);  		if (!ret_stack)  			return; -		t->curr_ret_stack = -1;  		atomic_set(&t->tracing_graph_pause, 0);  		atomic_set(&t->trace_overrun, 0);  		t->ftrace_timestamp = 0; diff --git a/kernel/trace/power-traces.c b/kernel/trace/power-traces.c index 9f4f565b01e..a22582a0616 100644 --- a/kernel/trace/power-traces.c +++ b/kernel/trace/power-traces.c @@ -9,7 +9,6 @@  #include <linux/workqueue.h>  #include <linux/sched.h>  #include <linux/module.h> -#include <linux/slab.h>  #define CREATE_TRACE_POINTS  #include <trace/events/power.h> diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 0287f9f52f5..41ca394feb2 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -14,6 +14,7 @@  #include <linux/module.h>  #include <linux/percpu.h>  #include <linux/mutex.h> +#include <linux/slab.h>  #include <linux/init.h>  #include <linux/hash.h>  #include <linux/list.h> @@ -207,6 +208,14 @@ EXPORT_SYMBOL_GPL(tracing_is_on);  #define RB_MAX_SMALL_DATA	(RB_ALIGNMENT * RINGBUF_TYPE_DATA_TYPE_LEN_MAX)  #define RB_EVNT_MIN_SIZE	8U	/* two 32bit words */ +#if !defined(CONFIG_64BIT) || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) +# define RB_FORCE_8BYTE_ALIGNMENT	0 +# define RB_ARCH_ALIGNMENT		RB_ALIGNMENT +#else +# define RB_FORCE_8BYTE_ALIGNMENT	1 +# define RB_ARCH_ALIGNMENT		8U +#endif +  /* define RINGBUF_TYPE_DATA for 'case RINGBUF_TYPE_DATA:' */  #define RINGBUF_TYPE_DATA 0 ... RINGBUF_TYPE_DATA_TYPE_LEN_MAX @@ -1201,18 +1210,19 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned nr_pages)  	for (i = 0; i < nr_pages; i++) {  		if (RB_WARN_ON(cpu_buffer, list_empty(cpu_buffer->pages))) -			return; +			goto out;  		p = cpu_buffer->pages->next;  		bpage = list_entry(p, struct buffer_page, list);  		list_del_init(&bpage->list);  		free_buffer_page(bpage);  	}  	if (RB_WARN_ON(cpu_buffer, list_empty(cpu_buffer->pages))) -		return; +		goto out;  	rb_reset_cpu(cpu_buffer);  	rb_check_pages(cpu_buffer); +out:  	spin_unlock_irq(&cpu_buffer->reader_lock);  } @@ -1229,7 +1239,7 @@ rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer,  	for (i = 0; i < nr_pages; i++) {  		if (RB_WARN_ON(cpu_buffer, list_empty(pages))) -			return; +			goto out;  		p = pages->next;  		bpage = list_entry(p, struct buffer_page, list);  		list_del_init(&bpage->list); @@ -1238,6 +1248,7 @@ rb_insert_pages(struct ring_buffer_per_cpu *cpu_buffer,  	rb_reset_cpu(cpu_buffer);  	rb_check_pages(cpu_buffer); +out:  	spin_unlock_irq(&cpu_buffer->reader_lock);  } @@ -1547,7 +1558,7 @@ rb_update_event(struct ring_buffer_event *event,  	case 0:  		length -= RB_EVNT_HDR_SIZE; -		if (length > RB_MAX_SMALL_DATA) +		if (length > RB_MAX_SMALL_DATA || RB_FORCE_8BYTE_ALIGNMENT)  			event->array[0] = length;  		else  			event->type_len = DIV_ROUND_UP(length, RB_ALIGNMENT); @@ -1722,11 +1733,11 @@ static unsigned rb_calculate_event_length(unsigned length)  	if (!length)  		length = 1; -	if (length > RB_MAX_SMALL_DATA) +	if (length > RB_MAX_SMALL_DATA || RB_FORCE_8BYTE_ALIGNMENT)  		length += sizeof(event.array[0]);  	length += RB_EVNT_HDR_SIZE; -	length = ALIGN(length, RB_ALIGNMENT); +	length = ALIGN(length, RB_ARCH_ALIGNMENT);  	return length;  } @@ -2233,12 +2244,12 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, unsigned long length)  	if (ring_buffer_flags != RB_BUFFERS_ON)  		return NULL; -	if (atomic_read(&buffer->record_disabled)) -		return NULL; -  	/* If we are tracing schedule, we don't want to recurse */  	resched = ftrace_preempt_disable(); +	if (atomic_read(&buffer->record_disabled)) +		goto out_nocheck; +  	if (trace_recursive_lock())  		goto out_nocheck; @@ -2470,11 +2481,11 @@ int ring_buffer_write(struct ring_buffer *buffer,  	if (ring_buffer_flags != RB_BUFFERS_ON)  		return -EBUSY; -	if (atomic_read(&buffer->record_disabled)) -		return -EBUSY; -  	resched = ftrace_preempt_disable(); +	if (atomic_read(&buffer->record_disabled)) +		goto out; +  	cpu = raw_smp_processor_id();  	if (!cpumask_test_cpu(cpu, buffer->cpumask)) @@ -2542,7 +2553,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_record_disable);   * @buffer: The ring buffer to enable writes   *   * Note, multiple disables will need the same number of enables - * to truely enable the writing (much like preempt_disable). + * to truly enable the writing (much like preempt_disable).   */  void ring_buffer_record_enable(struct ring_buffer *buffer)  { @@ -2578,7 +2589,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_record_disable_cpu);   * @cpu: The CPU to enable.   *   * Note, multiple disables will need the same number of enables - * to truely enable the writing (much like preempt_disable). + * to truly enable the writing (much like preempt_disable).   */  void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu)  { diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index ed01fdba4a5..44f916a0406 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -33,10 +33,10 @@  #include <linux/kdebug.h>  #include <linux/string.h>  #include <linux/rwsem.h> +#include <linux/slab.h>  #include <linux/ctype.h>  #include <linux/init.h>  #include <linux/poll.h> -#include <linux/gfp.h>  #include <linux/fs.h>  #include "trace.h" @@ -374,6 +374,21 @@ static int __init set_buf_size(char *str)  }  __setup("trace_buf_size=", set_buf_size); +static int __init set_tracing_thresh(char *str) +{ +	unsigned long threshhold; +	int ret; + +	if (!str) +		return 0; +	ret = strict_strtoul(str, 0, &threshhold); +	if (ret < 0) +		return 0; +	tracing_thresh = threshhold * 1000; +	return 1; +} +__setup("tracing_thresh=", set_tracing_thresh); +  unsigned long nsecs_to_usecs(unsigned long nsecs)  {  	return nsecs / 1000; @@ -579,9 +594,10 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)  static arch_spinlock_t ftrace_max_lock =  	(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; +unsigned long __read_mostly	tracing_thresh; +  #ifdef CONFIG_TRACER_MAX_TRACE  unsigned long __read_mostly	tracing_max_latency; -unsigned long __read_mostly	tracing_thresh;  /*   * Copy the new maximum trace into the separate maximum-trace @@ -592,7 +608,7 @@ static void  __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)  {  	struct trace_array_cpu *data = tr->data[cpu]; -	struct trace_array_cpu *max_data = tr->data[cpu]; +	struct trace_array_cpu *max_data;  	max_tr.cpu = cpu;  	max_tr.time_start = data->preempt_timestamp; @@ -602,7 +618,7 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)  	max_data->critical_start = data->critical_start;  	max_data->critical_end = data->critical_end; -	memcpy(data->comm, tsk->comm, TASK_COMM_LEN); +	memcpy(max_data->comm, tsk->comm, TASK_COMM_LEN);  	max_data->pid = tsk->pid;  	max_data->uid = task_uid(tsk);  	max_data->nice = tsk->static_prio - 20 - MAX_RT_PRIO; @@ -824,10 +840,10 @@ out:  	mutex_unlock(&trace_types_lock);  } -static void __tracing_reset(struct trace_array *tr, int cpu) +static void __tracing_reset(struct ring_buffer *buffer, int cpu)  {  	ftrace_disable_cpu(); -	ring_buffer_reset_cpu(tr->buffer, cpu); +	ring_buffer_reset_cpu(buffer, cpu);  	ftrace_enable_cpu();  } @@ -839,7 +855,7 @@ void tracing_reset(struct trace_array *tr, int cpu)  	/* Make sure all commits have finished */  	synchronize_sched(); -	__tracing_reset(tr, cpu); +	__tracing_reset(buffer, cpu);  	ring_buffer_record_enable(buffer);  } @@ -857,7 +873,7 @@ void tracing_reset_online_cpus(struct trace_array *tr)  	tr->time_start = ftrace_now(tr->cpu);  	for_each_online_cpu(cpu) -		__tracing_reset(tr, cpu); +		__tracing_reset(buffer, cpu);  	ring_buffer_record_enable(buffer);  } @@ -934,6 +950,8 @@ void tracing_start(void)  		goto out;  	} +	/* Prevent the buffers from switching */ +	arch_spin_lock(&ftrace_max_lock);  	buffer = global_trace.buffer;  	if (buffer) @@ -943,6 +961,8 @@ void tracing_start(void)  	if (buffer)  		ring_buffer_record_enable(buffer); +	arch_spin_unlock(&ftrace_max_lock); +  	ftrace_start();   out:  	spin_unlock_irqrestore(&tracing_start_lock, flags); @@ -964,6 +984,9 @@ void tracing_stop(void)  	if (trace_stop_count++)  		goto out; +	/* Prevent the buffers from switching */ +	arch_spin_lock(&ftrace_max_lock); +  	buffer = global_trace.buffer;  	if (buffer)  		ring_buffer_record_disable(buffer); @@ -972,6 +995,8 @@ void tracing_stop(void)  	if (buffer)  		ring_buffer_record_disable(buffer); +	arch_spin_unlock(&ftrace_max_lock); +   out:  	spin_unlock_irqrestore(&tracing_start_lock, flags);  } @@ -1259,6 +1284,13 @@ ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)  	if (!(trace_flags & TRACE_ITER_USERSTACKTRACE))  		return; +	/* +	 * NMIs can not handle page faults, even with fix ups. +	 * The save user stack can (and often does) fault. +	 */ +	if (unlikely(in_nmi())) +		return; +  	event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK,  					  sizeof(*entry), flags, pc);  	if (!event) @@ -1703,6 +1735,7 @@ static void *s_start(struct seq_file *m, loff_t *pos)  		ftrace_enable_cpu(); +		iter->leftover = 0;  		for (p = iter; p && l < *pos; p = s_next(m, p, &l))  			; @@ -4248,10 +4281,10 @@ static __init int tracer_init_debugfs(void)  #ifdef CONFIG_TRACER_MAX_TRACE  	trace_create_file("tracing_max_latency", 0644, d_tracer,  			&tracing_max_latency, &tracing_max_lat_fops); +#endif  	trace_create_file("tracing_thresh", 0644, d_tracer,  			&tracing_thresh, &tracing_max_lat_fops); -#endif  	trace_create_file("README", 0444, d_tracer,  			NULL, &tracing_readme_fops); diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index fd05bcaf91b..2825ef2c0b1 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -396,9 +396,10 @@ extern int process_new_ksym_entry(char *ksymname, int op, unsigned long addr);  extern unsigned long nsecs_to_usecs(unsigned long nsecs); +extern unsigned long tracing_thresh; +  #ifdef CONFIG_TRACER_MAX_TRACE  extern unsigned long tracing_max_latency; -extern unsigned long tracing_thresh;  void update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu);  void update_max_tr_single(struct trace_array *tr, @@ -550,7 +551,7 @@ static inline int ftrace_trace_task(struct task_struct *task)   * struct trace_parser - servers for reading the user input separated by spaces   * @cont: set if the input is not complete - no final space char was found   * @buffer: holds the parsed user input - * @idx: user input lenght + * @idx: user input length   * @size: buffer size   */  struct trace_parser { diff --git a/kernel/trace/trace_clock.c b/kernel/trace/trace_clock.c index 84a3a7ba072..9d589d8dcd1 100644 --- a/kernel/trace/trace_clock.c +++ b/kernel/trace/trace_clock.c @@ -13,6 +13,7 @@   * Tracer plugins will chose a default from these clocks.   */  #include <linux/spinlock.h> +#include <linux/irqflags.h>  #include <linux/hardirq.h>  #include <linux/module.h>  #include <linux/percpu.h> @@ -83,7 +84,7 @@ u64 notrace trace_clock_global(void)  	int this_cpu;  	u64 now; -	raw_local_irq_save(flags); +	local_irq_save(flags);  	this_cpu = raw_smp_processor_id();  	now = cpu_clock(this_cpu); @@ -109,7 +110,7 @@ u64 notrace trace_clock_global(void)  	arch_spin_unlock(&trace_clock_struct.lock);   out: -	raw_local_irq_restore(flags); +	local_irq_restore(flags);  	return now;  } diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_perf.c index f0d69300507..0565bb42566 100644 --- a/kernel/trace/trace_event_profile.c +++ b/kernel/trace/trace_event_perf.c @@ -1,32 +1,41 @@  /* - * trace event based perf counter profiling + * trace event based perf event profiling/tracing   *   * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra <pzijlstr@redhat.com> - * + * Copyright (C) 2009-2010 Frederic Weisbecker <fweisbec@gmail.com>   */  #include <linux/module.h>  #include <linux/kprobes.h>  #include "trace.h" +DEFINE_PER_CPU(struct pt_regs, perf_trace_regs); +EXPORT_PER_CPU_SYMBOL_GPL(perf_trace_regs); + +EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs);  static char *perf_trace_buf;  static char *perf_trace_buf_nmi; -typedef typeof(char [FTRACE_MAX_PROFILE_SIZE]) perf_trace_t ; +/* + * Force it to be aligned to unsigned long to avoid misaligned accesses + * suprises + */ +typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)]) +	perf_trace_t;  /* Count the events in use (per event id, not per instance) */ -static int	total_profile_count; +static int	total_ref_count; -static int ftrace_profile_enable_event(struct ftrace_event_call *event) +static int perf_trace_event_enable(struct ftrace_event_call *event)  {  	char *buf;  	int ret = -ENOMEM; -	if (event->profile_count++ > 0) +	if (event->perf_refcount++ > 0)  		return 0; -	if (!total_profile_count) { +	if (!total_ref_count) {  		buf = (char *)alloc_percpu(perf_trace_t);  		if (!buf)  			goto fail_buf; @@ -40,35 +49,35 @@ static int ftrace_profile_enable_event(struct ftrace_event_call *event)  		rcu_assign_pointer(perf_trace_buf_nmi, buf);  	} -	ret = event->profile_enable(event); +	ret = event->perf_event_enable(event);  	if (!ret) { -		total_profile_count++; +		total_ref_count++;  		return 0;  	}  fail_buf_nmi: -	if (!total_profile_count) { +	if (!total_ref_count) {  		free_percpu(perf_trace_buf_nmi);  		free_percpu(perf_trace_buf);  		perf_trace_buf_nmi = NULL;  		perf_trace_buf = NULL;  	}  fail_buf: -	event->profile_count--; +	event->perf_refcount--;  	return ret;  } -int ftrace_profile_enable(int event_id) +int perf_trace_enable(int event_id)  {  	struct ftrace_event_call *event;  	int ret = -EINVAL;  	mutex_lock(&event_mutex);  	list_for_each_entry(event, &ftrace_events, list) { -		if (event->id == event_id && event->profile_enable && +		if (event->id == event_id && event->perf_event_enable &&  		    try_module_get(event->mod)) { -			ret = ftrace_profile_enable_event(event); +			ret = perf_trace_event_enable(event);  			break;  		}  	} @@ -77,16 +86,16 @@ int ftrace_profile_enable(int event_id)  	return ret;  } -static void ftrace_profile_disable_event(struct ftrace_event_call *event) +static void perf_trace_event_disable(struct ftrace_event_call *event)  {  	char *buf, *nmi_buf; -	if (--event->profile_count > 0) +	if (--event->perf_refcount > 0)  		return; -	event->profile_disable(event); +	event->perf_event_disable(event); -	if (!--total_profile_count) { +	if (!--total_ref_count) {  		buf = perf_trace_buf;  		rcu_assign_pointer(perf_trace_buf, NULL); @@ -104,14 +113,14 @@ static void ftrace_profile_disable_event(struct ftrace_event_call *event)  	}  } -void ftrace_profile_disable(int event_id) +void perf_trace_disable(int event_id)  {  	struct ftrace_event_call *event;  	mutex_lock(&event_mutex);  	list_for_each_entry(event, &ftrace_events, list) {  		if (event->id == event_id) { -			ftrace_profile_disable_event(event); +			perf_trace_event_disable(event);  			module_put(event->mod);  			break;  		} @@ -119,13 +128,15 @@ void ftrace_profile_disable(int event_id)  	mutex_unlock(&event_mutex);  } -__kprobes void *ftrace_perf_buf_prepare(int size, unsigned short type, -					int *rctxp, unsigned long *irq_flags) +__kprobes void *perf_trace_buf_prepare(int size, unsigned short type, +				       int *rctxp, unsigned long *irq_flags)  {  	struct trace_entry *entry;  	char *trace_buf, *raw_data;  	int pc, cpu; +	BUILD_BUG_ON(PERF_MAX_TRACE_SIZE % sizeof(unsigned long)); +  	pc = preempt_count();  	/* Protect the per cpu buffer, begin the rcu read side */ @@ -138,9 +149,9 @@ __kprobes void *ftrace_perf_buf_prepare(int size, unsigned short type,  	cpu = smp_processor_id();  	if (in_nmi()) -		trace_buf = rcu_dereference(perf_trace_buf_nmi); +		trace_buf = rcu_dereference_sched(perf_trace_buf_nmi);  	else -		trace_buf = rcu_dereference(perf_trace_buf); +		trace_buf = rcu_dereference_sched(perf_trace_buf);  	if (!trace_buf)  		goto err; @@ -148,7 +159,7 @@ __kprobes void *ftrace_perf_buf_prepare(int size, unsigned short type,  	raw_data = per_cpu_ptr(trace_buf, cpu);  	/* zero the dead bytes from align to not leak stack to user */ -	*(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL; +	memset(&raw_data[size - sizeof(u64)], 0, sizeof(u64));  	entry = (struct trace_entry *)raw_data;  	tracing_generic_entry_update(entry, *irq_flags, pc); @@ -161,4 +172,4 @@ err_recursion:  	local_irq_restore(*irq_flags);  	return NULL;  } -EXPORT_SYMBOL_GPL(ftrace_perf_buf_prepare); +EXPORT_SYMBOL_GPL(perf_trace_buf_prepare); diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 3f972ad98d0..c697c704334 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -15,6 +15,7 @@  #include <linux/uaccess.h>  #include <linux/module.h>  #include <linux/ctype.h> +#include <linux/slab.h>  #include <linux/delay.h>  #include <asm/setup.h> @@ -938,7 +939,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,  		trace_create_file("enable", 0644, call->dir, call,  				  enable); -	if (call->id && call->profile_enable) +	if (call->id && call->perf_event_enable)  		trace_create_file("id", 0444, call->dir, call,  		 		  id); diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 4615f62a04f..88c0b6dbd7f 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -22,6 +22,7 @@  #include <linux/ctype.h>  #include <linux/mutex.h>  #include <linux/perf_event.h> +#include <linux/slab.h>  #include "trace.h"  #include "trace_output.h" diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 3fc2a575664..9aed1a5cf55 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -9,6 +9,7 @@  #include <linux/debugfs.h>  #include <linux/uaccess.h>  #include <linux/ftrace.h> +#include <linux/slab.h>  #include <linux/fs.h>  #include "trace.h" @@ -237,6 +238,14 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)  	return ret;  } +int trace_graph_thresh_entry(struct ftrace_graph_ent *trace) +{ +	if (tracing_thresh) +		return 1; +	else +		return trace_graph_entry(trace); +} +  static void __trace_graph_return(struct trace_array *tr,  				struct ftrace_graph_ret *trace,  				unsigned long flags, @@ -290,13 +299,26 @@ void set_graph_array(struct trace_array *tr)  	smp_mb();  } +void trace_graph_thresh_return(struct ftrace_graph_ret *trace) +{ +	if (tracing_thresh && +	    (trace->rettime - trace->calltime < tracing_thresh)) +		return; +	else +		trace_graph_return(trace); +} +  static int graph_trace_init(struct trace_array *tr)  {  	int ret;  	set_graph_array(tr); -	ret = register_ftrace_graph(&trace_graph_return, -				    &trace_graph_entry); +	if (tracing_thresh) +		ret = register_ftrace_graph(&trace_graph_thresh_return, +					    &trace_graph_thresh_entry); +	else +		ret = register_ftrace_graph(&trace_graph_return, +					    &trace_graph_entry);  	if (ret)  		return ret;  	tracing_start_cmdline_record(); @@ -920,7 +942,7 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,  		if (!ret)  			return TRACE_TYPE_PARTIAL_LINE;  	} else { -		ret = trace_seq_printf(s, "} (%ps)\n", (void *)trace->func); +		ret = trace_seq_printf(s, "} /* %ps */\n", (void *)trace->func);  		if (!ret)  			return TRACE_TYPE_PARTIAL_LINE;  	} diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 505c92273b1..1251e367bae 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -1214,7 +1214,7 @@ static int set_print_fmt(struct trace_probe *tp)  #ifdef CONFIG_PERF_EVENTS  /* Kprobe profile handler */ -static __kprobes void kprobe_profile_func(struct kprobe *kp, +static __kprobes void kprobe_perf_func(struct kprobe *kp,  					 struct pt_regs *regs)  {  	struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); @@ -1227,11 +1227,11 @@ static __kprobes void kprobe_profile_func(struct kprobe *kp,  	__size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args);  	size = ALIGN(__size + sizeof(u32), sizeof(u64));  	size -= sizeof(u32); -	if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, +	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,  		     "profile buffer not large enough"))  		return; -	entry = ftrace_perf_buf_prepare(size, call->id, &rctx, &irq_flags); +	entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags);  	if (!entry)  		return; @@ -1240,11 +1240,11 @@ static __kprobes void kprobe_profile_func(struct kprobe *kp,  	for (i = 0; i < tp->nr_args; i++)  		entry->args[i] = call_fetch(&tp->args[i].fetch, regs); -	ftrace_perf_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags); +	perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs);  }  /* Kretprobe profile handler */ -static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri, +static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,  					    struct pt_regs *regs)  {  	struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); @@ -1257,11 +1257,11 @@ static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri,  	__size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args);  	size = ALIGN(__size + sizeof(u32), sizeof(u64));  	size -= sizeof(u32); -	if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, +	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,  		     "profile buffer not large enough"))  		return; -	entry = ftrace_perf_buf_prepare(size, call->id, &rctx, &irq_flags); +	entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags);  	if (!entry)  		return; @@ -1271,10 +1271,11 @@ static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri,  	for (i = 0; i < tp->nr_args; i++)  		entry->args[i] = call_fetch(&tp->args[i].fetch, regs); -	ftrace_perf_buf_submit(entry, size, rctx, entry->ret_ip, 1, irq_flags); +	perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, +			       irq_flags, regs);  } -static int probe_profile_enable(struct ftrace_event_call *call) +static int probe_perf_enable(struct ftrace_event_call *call)  {  	struct trace_probe *tp = (struct trace_probe *)call->data; @@ -1286,7 +1287,7 @@ static int probe_profile_enable(struct ftrace_event_call *call)  		return enable_kprobe(&tp->rp.kp);  } -static void probe_profile_disable(struct ftrace_event_call *call) +static void probe_perf_disable(struct ftrace_event_call *call)  {  	struct trace_probe *tp = (struct trace_probe *)call->data; @@ -1311,7 +1312,7 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)  		kprobe_trace_func(kp, regs);  #ifdef CONFIG_PERF_EVENTS  	if (tp->flags & TP_FLAG_PROFILE) -		kprobe_profile_func(kp, regs); +		kprobe_perf_func(kp, regs);  #endif  	return 0;	/* We don't tweek kernel, so just return 0 */  } @@ -1325,7 +1326,7 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)  		kretprobe_trace_func(ri, regs);  #ifdef CONFIG_PERF_EVENTS  	if (tp->flags & TP_FLAG_PROFILE) -		kretprobe_profile_func(ri, regs); +		kretprobe_perf_func(ri, regs);  #endif  	return 0;	/* We don't tweek kernel, so just return 0 */  } @@ -1358,8 +1359,8 @@ static int register_probe_event(struct trace_probe *tp)  	call->unregfunc = probe_event_disable;  #ifdef CONFIG_PERF_EVENTS -	call->profile_enable = probe_profile_enable; -	call->profile_disable = probe_profile_disable; +	call->perf_event_enable = probe_perf_enable; +	call->perf_event_disable = probe_perf_disable;  #endif  	call->data = tp;  	ret = trace_add_event_call(call); diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c index 94103cdcf9d..d59cd687947 100644 --- a/kernel/trace/trace_ksym.c +++ b/kernel/trace/trace_ksym.c @@ -23,6 +23,7 @@  #include <linux/debugfs.h>  #include <linux/ftrace.h>  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/fs.h>  #include "trace_output.h" diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c index 0acd834659e..017fa376505 100644 --- a/kernel/trace/trace_mmiotrace.c +++ b/kernel/trace/trace_mmiotrace.c @@ -9,6 +9,7 @@  #include <linux/kernel.h>  #include <linux/mmiotrace.h>  #include <linux/pci.h> +#include <linux/slab.h>  #include <linux/time.h>  #include <asm/atomic.h> diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 280fea470d6..81003b4d617 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c @@ -3,6 +3,7 @@  #include <linux/stringify.h>  #include <linux/kthread.h>  #include <linux/delay.h> +#include <linux/slab.h>  static inline int trace_valid_entry(struct trace_entry *entry)  { diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c index a4bb239eb98..96cffb269e7 100644 --- a/kernel/trace/trace_stat.c +++ b/kernel/trace/trace_stat.c @@ -10,6 +10,7 @@  #include <linux/list.h> +#include <linux/slab.h>  #include <linux/rbtree.h>  #include <linux/debugfs.h>  #include "trace_stat.h" diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index cba47d7935c..4d6d711717f 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -1,5 +1,6 @@  #include <trace/syscall.h>  #include <trace/events/syscalls.h> +#include <linux/slab.h>  #include <linux/kernel.h>  #include <linux/ftrace.h>  #include <linux/perf_event.h> @@ -428,12 +429,12 @@ core_initcall(init_ftrace_syscalls);  #ifdef CONFIG_PERF_EVENTS -static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); -static DECLARE_BITMAP(enabled_prof_exit_syscalls, NR_syscalls); -static int sys_prof_refcount_enter; -static int sys_prof_refcount_exit; +static DECLARE_BITMAP(enabled_perf_enter_syscalls, NR_syscalls); +static DECLARE_BITMAP(enabled_perf_exit_syscalls, NR_syscalls); +static int sys_perf_refcount_enter; +static int sys_perf_refcount_exit; -static void prof_syscall_enter(struct pt_regs *regs, long id) +static void perf_syscall_enter(struct pt_regs *regs, long id)  {  	struct syscall_metadata *sys_data;  	struct syscall_trace_enter *rec; @@ -443,7 +444,7 @@ static void prof_syscall_enter(struct pt_regs *regs, long id)  	int size;  	syscall_nr = syscall_get_nr(current, regs); -	if (!test_bit(syscall_nr, enabled_prof_enter_syscalls)) +	if (!test_bit(syscall_nr, enabled_perf_enter_syscalls))  		return;  	sys_data = syscall_nr_to_meta(syscall_nr); @@ -455,11 +456,11 @@ static void prof_syscall_enter(struct pt_regs *regs, long id)  	size = ALIGN(size + sizeof(u32), sizeof(u64));  	size -= sizeof(u32); -	if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, -		      "profile buffer not large enough")) +	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, +		      "perf buffer not large enough"))  		return; -	rec = (struct syscall_trace_enter *)ftrace_perf_buf_prepare(size, +	rec = (struct syscall_trace_enter *)perf_trace_buf_prepare(size,  				sys_data->enter_event->id, &rctx, &flags);  	if (!rec)  		return; @@ -467,10 +468,10 @@ static void prof_syscall_enter(struct pt_regs *regs, long id)  	rec->nr = syscall_nr;  	syscall_get_arguments(current, regs, 0, sys_data->nb_args,  			       (unsigned long *)&rec->args); -	ftrace_perf_buf_submit(rec, size, rctx, 0, 1, flags); +	perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs);  } -int prof_sysenter_enable(struct ftrace_event_call *call) +int perf_sysenter_enable(struct ftrace_event_call *call)  {  	int ret = 0;  	int num; @@ -478,34 +479,34 @@ int prof_sysenter_enable(struct ftrace_event_call *call)  	num = ((struct syscall_metadata *)call->data)->syscall_nr;  	mutex_lock(&syscall_trace_lock); -	if (!sys_prof_refcount_enter) -		ret = register_trace_sys_enter(prof_syscall_enter); +	if (!sys_perf_refcount_enter) +		ret = register_trace_sys_enter(perf_syscall_enter);  	if (ret) {  		pr_info("event trace: Could not activate"  				"syscall entry trace point");  	} else { -		set_bit(num, enabled_prof_enter_syscalls); -		sys_prof_refcount_enter++; +		set_bit(num, enabled_perf_enter_syscalls); +		sys_perf_refcount_enter++;  	}  	mutex_unlock(&syscall_trace_lock);  	return ret;  } -void prof_sysenter_disable(struct ftrace_event_call *call) +void perf_sysenter_disable(struct ftrace_event_call *call)  {  	int num;  	num = ((struct syscall_metadata *)call->data)->syscall_nr;  	mutex_lock(&syscall_trace_lock); -	sys_prof_refcount_enter--; -	clear_bit(num, enabled_prof_enter_syscalls); -	if (!sys_prof_refcount_enter) -		unregister_trace_sys_enter(prof_syscall_enter); +	sys_perf_refcount_enter--; +	clear_bit(num, enabled_perf_enter_syscalls); +	if (!sys_perf_refcount_enter) +		unregister_trace_sys_enter(perf_syscall_enter);  	mutex_unlock(&syscall_trace_lock);  } -static void prof_syscall_exit(struct pt_regs *regs, long ret) +static void perf_syscall_exit(struct pt_regs *regs, long ret)  {  	struct syscall_metadata *sys_data;  	struct syscall_trace_exit *rec; @@ -515,7 +516,7 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret)  	int size;  	syscall_nr = syscall_get_nr(current, regs); -	if (!test_bit(syscall_nr, enabled_prof_exit_syscalls)) +	if (!test_bit(syscall_nr, enabled_perf_exit_syscalls))  		return;  	sys_data = syscall_nr_to_meta(syscall_nr); @@ -530,11 +531,11 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret)  	 * Impossible, but be paranoid with the future  	 * How to put this check outside runtime?  	 */ -	if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, -		"exit event has grown above profile buffer size")) +	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, +		"exit event has grown above perf buffer size"))  		return; -	rec = (struct syscall_trace_exit *)ftrace_perf_buf_prepare(size, +	rec = (struct syscall_trace_exit *)perf_trace_buf_prepare(size,  				sys_data->exit_event->id, &rctx, &flags);  	if (!rec)  		return; @@ -542,10 +543,10 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret)  	rec->nr = syscall_nr;  	rec->ret = syscall_get_return_value(current, regs); -	ftrace_perf_buf_submit(rec, size, rctx, 0, 1, flags); +	perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs);  } -int prof_sysexit_enable(struct ftrace_event_call *call) +int perf_sysexit_enable(struct ftrace_event_call *call)  {  	int ret = 0;  	int num; @@ -553,30 +554,30 @@ int prof_sysexit_enable(struct ftrace_event_call *call)  	num = ((struct syscall_metadata *)call->data)->syscall_nr;  	mutex_lock(&syscall_trace_lock); -	if (!sys_prof_refcount_exit) -		ret = register_trace_sys_exit(prof_syscall_exit); +	if (!sys_perf_refcount_exit) +		ret = register_trace_sys_exit(perf_syscall_exit);  	if (ret) {  		pr_info("event trace: Could not activate"  				"syscall exit trace point");  	} else { -		set_bit(num, enabled_prof_exit_syscalls); -		sys_prof_refcount_exit++; +		set_bit(num, enabled_perf_exit_syscalls); +		sys_perf_refcount_exit++;  	}  	mutex_unlock(&syscall_trace_lock);  	return ret;  } -void prof_sysexit_disable(struct ftrace_event_call *call) +void perf_sysexit_disable(struct ftrace_event_call *call)  {  	int num;  	num = ((struct syscall_metadata *)call->data)->syscall_nr;  	mutex_lock(&syscall_trace_lock); -	sys_prof_refcount_exit--; -	clear_bit(num, enabled_prof_exit_syscalls); -	if (!sys_prof_refcount_exit) -		unregister_trace_sys_exit(prof_syscall_exit); +	sys_perf_refcount_exit--; +	clear_bit(num, enabled_perf_exit_syscalls); +	if (!sys_perf_refcount_exit) +		unregister_trace_sys_exit(perf_syscall_exit);  	mutex_unlock(&syscall_trace_lock);  } diff --git a/kernel/trace/trace_workqueue.c b/kernel/trace/trace_workqueue.c index 40cafb07dff..cc2d2faa7d9 100644 --- a/kernel/trace/trace_workqueue.c +++ b/kernel/trace/trace_workqueue.c @@ -9,6 +9,7 @@  #include <trace/events/workqueue.h>  #include <linux/list.h>  #include <linux/percpu.h> +#include <linux/slab.h>  #include <linux/kref.h>  #include "trace_stat.h"  #include "trace.h"  |