diff options
| author | Ingo Molnar <mingo@elte.hu> | 2010-06-09 18:55:20 +0200 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2010-06-09 18:55:57 +0200 | 
| commit | c726b61c6a5acc54c55ed7a0e7638cc4c5a100a8 (patch) | |
| tree | 3f44aa013d31d34951e9610e79ff14c1148ad6ac | |
| parent | 7be7923633a142402266d642ccebf74f556a649b (diff) | |
| parent | 018378c55b03f88ff513aba4e0e93b8d4a9cf241 (diff) | |
| download | olio-linux-3.10-c726b61c6a5acc54c55ed7a0e7638cc4c5a100a8.tar.xz olio-linux-3.10-c726b61c6a5acc54c55ed7a0e7638cc4c5a100a8.zip  | |
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing into perf/core
35 files changed, 130 insertions, 1309 deletions
diff --git a/Documentation/ABI/testing/debugfs-kmemtrace b/Documentation/ABI/testing/debugfs-kmemtrace deleted file mode 100644 index 5e6a92a02d8..00000000000 --- a/Documentation/ABI/testing/debugfs-kmemtrace +++ /dev/null @@ -1,71 +0,0 @@ -What:		/sys/kernel/debug/kmemtrace/ -Date:		July 2008 -Contact:	Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> -Description: - -In kmemtrace-enabled kernels, the following files are created: - -/sys/kernel/debug/kmemtrace/ -	cpu<n>		(0400)	Per-CPU tracing data, see below. (binary) -	total_overruns	(0400)	Total number of bytes which were dropped from -				cpu<n> files because of full buffer condition, -				non-binary. (text) -	abi_version	(0400)	Kernel's kmemtrace ABI version. (text) - -Each per-CPU file should be read according to the relay interface. That is, -the reader should set affinity to that specific CPU and, as currently done by -the userspace application (though there are other methods), use poll() with -an infinite timeout before every read(). Otherwise, erroneous data may be -read. The binary data has the following _core_ format: - -	Event ID	(1 byte)	Unsigned integer, one of: -		0 - represents an allocation (KMEMTRACE_EVENT_ALLOC) -		1 - represents a freeing of previously allocated memory -		    (KMEMTRACE_EVENT_FREE) -	Type ID		(1 byte)	Unsigned integer, one of: -		0 - this is a kmalloc() / kfree() -		1 - this is a kmem_cache_alloc() / kmem_cache_free() -		2 - this is a __get_free_pages() et al. -	Event size	(2 bytes)	Unsigned integer representing the -					size of this event. Used to extend -					kmemtrace. Discard the bytes you -					don't know about. -	Sequence number	(4 bytes)	Signed integer used to reorder data -					logged on SMP machines. Wraparound -					must be taken into account, although -					it is unlikely. -	Caller address	(8 bytes)	Return address to the caller. -	Pointer to mem	(8 bytes)	Pointer to target memory area. Can be -					NULL, but not all such calls might be -					recorded. - -In case of KMEMTRACE_EVENT_ALLOC events, the next fields follow: - -	Requested bytes	(8 bytes)	Total number of requested bytes, -					unsigned, must not be zero. -	Allocated bytes (8 bytes)	Total number of actually allocated -					bytes, unsigned, must not be lower -					than requested bytes. -	Requested flags	(4 bytes)	GFP flags supplied by the caller. -	Target CPU	(4 bytes)	Signed integer, valid for event id 1. -					If equal to -1, target CPU is the same -					as origin CPU, but the reverse might -					not be true. - -The data is made available in the same endianness the machine has. - -Other event ids and type ids may be defined and added. Other fields may be -added by increasing event size, but see below for details. -Every modification to the ABI, including new id definitions, are followed -by bumping the ABI version by one. - -Adding new data to the packet (features) is done at the end of the mandatory -data: -	Feature size	(2 byte) -	Feature ID	(1 byte) -	Feature data	(Feature size - 3 bytes) - - -Users: -	kmemtrace-user - git://repo.or.cz/kmemtrace-user.git - diff --git a/Documentation/trace/kmemtrace.txt b/Documentation/trace/kmemtrace.txt deleted file mode 100644 index 6308735e58c..00000000000 --- a/Documentation/trace/kmemtrace.txt +++ /dev/null @@ -1,126 +0,0 @@ -			kmemtrace - Kernel Memory Tracer - -			  by Eduard - Gabriel Munteanu -			     <eduard.munteanu@linux360.ro> - -I. Introduction -=============== - -kmemtrace helps kernel developers figure out two things: -1) how different allocators (SLAB, SLUB etc.) perform -2) how kernel code allocates memory and how much - -To do this, we trace every allocation and export information to the userspace -through the relay interface. We export things such as the number of requested -bytes, the number of bytes actually allocated (i.e. including internal -fragmentation), whether this is a slab allocation or a plain kmalloc() and so -on. - -The actual analysis is performed by a userspace tool (see section III for -details on where to get it from). It logs the data exported by the kernel, -processes it and (as of writing this) can provide the following information: -- the total amount of memory allocated and fragmentation per call-site -- the amount of memory allocated and fragmentation per allocation -- total memory allocated and fragmentation in the collected dataset -- number of cross-CPU allocation and frees (makes sense in NUMA environments) - -Moreover, it can potentially find inconsistent and erroneous behavior in -kernel code, such as using slab free functions on kmalloc'ed memory or -allocating less memory than requested (but not truly failed allocations). - -kmemtrace also makes provisions for tracing on some arch and analysing the -data on another. - -II. Design and goals -==================== - -kmemtrace was designed to handle rather large amounts of data. Thus, it uses -the relay interface to export whatever is logged to userspace, which then -stores it. Analysis and reporting is done asynchronously, that is, after the -data is collected and stored. By design, it allows one to log and analyse -on different machines and different arches. - -As of writing this, the ABI is not considered stable, though it might not -change much. However, no guarantees are made about compatibility yet. When -deemed stable, the ABI should still allow easy extension while maintaining -backward compatibility. This is described further in Documentation/ABI. - -Summary of design goals: -	- allow logging and analysis to be done across different machines -	- be fast and anticipate usage in high-load environments (*) -	- be reasonably extensible -	- make it possible for GNU/Linux distributions to have kmemtrace -	included in their repositories - -(*) - one of the reasons Pekka Enberg's original userspace data analysis -    tool's code was rewritten from Perl to C (although this is more than a -    simple conversion) - - -III. Quick usage guide -====================== - -1) Get a kernel that supports kmemtrace and build it accordingly (i.e. enable -CONFIG_KMEMTRACE). - -2) Get the userspace tool and build it: -$ git clone git://repo.or.cz/kmemtrace-user.git		# current repository -$ cd kmemtrace-user/ -$ ./autogen.sh -$ ./configure -$ make - -3) Boot the kmemtrace-enabled kernel if you haven't, preferably in the -'single' runlevel (so that relay buffers don't fill up easily), and run -kmemtrace: -# '$' does not mean user, but root here. -$ mount -t debugfs none /sys/kernel/debug -$ mount -t proc none /proc -$ cd path/to/kmemtrace-user/ -$ ./kmemtraced -Wait a bit, then stop it with CTRL+C. -$ cat /sys/kernel/debug/kmemtrace/total_overruns	# Check if we didn't -							# overrun, should -							# be zero. -$ (Optionally) [Run kmemtrace_check separately on each cpu[0-9]*.out file to -		check its correctness] -$ ./kmemtrace-report - -Now you should have a nice and short summary of how the allocator performs. - -IV. FAQ and known issues -======================== - -Q: 'cat /sys/kernel/debug/kmemtrace/total_overruns' is non-zero, how do I fix -this? Should I worry? -A: If it's non-zero, this affects kmemtrace's accuracy, depending on how -large the number is. You can fix it by supplying a higher -'kmemtrace.subbufs=N' kernel parameter. ---- - -Q: kmemtrace_check reports errors, how do I fix this? Should I worry? -A: This is a bug and should be reported. It can occur for a variety of -reasons: -	- possible bugs in relay code -	- possible misuse of relay by kmemtrace -	- timestamps being collected unorderly -Or you may fix it yourself and send us a patch. ---- - -Q: kmemtrace_report shows many errors, how do I fix this? Should I worry? -A: This is a known issue and I'm working on it. These might be true errors -in kernel code, which may have inconsistent behavior (e.g. allocating memory -with kmem_cache_alloc() and freeing it with kfree()). Pekka Enberg pointed -out this behavior may work with SLAB, but may fail with other allocators. - -It may also be due to lack of tracing in some unusual allocator functions. - -We don't want bug reports regarding this issue yet. ---- - -V. See also -=========== - -Documentation/kernel-parameters.txt -Documentation/ABI/testing/debugfs-kmemtrace - diff --git a/MAINTAINERS b/MAINTAINERS index 13608bd2e79..26da7313055 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3368,13 +3368,6 @@ F:	include/linux/kmemleak.h  F:	mm/kmemleak.c  F:	mm/kmemleak-test.c -KMEMTRACE -M:	Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> -S:	Maintained -F:	Documentation/trace/kmemtrace.txt -F:	include/linux/kmemtrace.h -F:	kernel/trace/kmemtrace.c -  KPROBES  M:	Ananth N Mavinakayanahalli <ananth@in.ibm.com>  M:	Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> diff --git a/arch/powerpc/include/asm/perf_event.h b/arch/powerpc/include/asm/perf_event.h index e6d4ce69b12..5c16b891d50 100644 --- a/arch/powerpc/include/asm/perf_event.h +++ b/arch/powerpc/include/asm/perf_event.h @@ -21,3 +21,15 @@  #ifdef CONFIG_FSL_EMB_PERF_EVENT  #include <asm/perf_event_fsl_emb.h>  #endif + +#ifdef CONFIG_PERF_EVENTS +#include <asm/ptrace.h> +#include <asm/reg.h> + +#define perf_arch_fetch_caller_regs(regs, __ip)			\ +	do {							\ +		(regs)->nip = __ip;				\ +		(regs)->gpr[1] = *(unsigned long *)__get_SP();	\ +		asm volatile("mfmsr %0" : "=r" ((regs)->msr));	\ +	} while (0) +#endif diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S index 22e507c8a55..2d29752cbe1 100644 --- a/arch/powerpc/kernel/misc.S +++ b/arch/powerpc/kernel/misc.S @@ -127,29 +127,3 @@ _GLOBAL(__setup_cpu_power7)  _GLOBAL(__restore_cpu_power7)  	/* place holder */  	blr - -/* - * Get a minimal set of registers for our caller's nth caller. - * r3 = regs pointer, r5 = n. - * - * We only get R1 (stack pointer), NIP (next instruction pointer) - * and LR (link register).  These are all we can get in the - * general case without doing complicated stack unwinding, but - * fortunately they are enough to do a stack backtrace, which - * is all we need them for. - */ -_GLOBAL(perf_arch_fetch_caller_regs) -	mr	r6,r1 -	cmpwi	r5,0 -	mflr	r4 -	ble	2f -	mtctr	r5 -1:	PPC_LL	r6,0(r6) -	bdnz	1b -	PPC_LL	r4,PPC_LR_STKOFF(r6) -2:	PPC_LL	r7,0(r6) -	PPC_LL	r7,PPC_LR_STKOFF(r7) -	PPC_STL	r6,GPR1-STACK_FRAME_OVERHEAD(r3) -	PPC_STL	r4,_NIP-STACK_FRAME_OVERHEAD(r3) -	PPC_STL	r7,_LINK-STACK_FRAME_OVERHEAD(r3) -	blr diff --git a/arch/sparc/include/asm/perf_event.h b/arch/sparc/include/asm/perf_event.h index 7e2669894ce..74c4e0cd889 100644 --- a/arch/sparc/include/asm/perf_event.h +++ b/arch/sparc/include/asm/perf_event.h @@ -6,7 +6,15 @@ extern void set_perf_event_pending(void);  #define	PERF_EVENT_INDEX_OFFSET	0  #ifdef CONFIG_PERF_EVENTS +#include <asm/ptrace.h> +  extern void init_hw_perf_events(void); + +extern void +__perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip); + +#define perf_arch_fetch_caller_regs(pt_regs, ip)	\ +	__perf_arch_fetch_caller_regs(pt_regs, ip, 1);  #else  static inline void init_hw_perf_events(void)	{ }  #endif diff --git a/arch/sparc/kernel/helpers.S b/arch/sparc/kernel/helpers.S index 92090cc9e82..682fee06a16 100644 --- a/arch/sparc/kernel/helpers.S +++ b/arch/sparc/kernel/helpers.S @@ -47,9 +47,9 @@ stack_trace_flush:  	.size		stack_trace_flush,.-stack_trace_flush  #ifdef CONFIG_PERF_EVENTS -	.globl		perf_arch_fetch_caller_regs -	.type		perf_arch_fetch_caller_regs,#function -perf_arch_fetch_caller_regs: +	.globl		__perf_arch_fetch_caller_regs +	.type		__perf_arch_fetch_caller_regs,#function +__perf_arch_fetch_caller_regs:  	/* We always read the %pstate into %o5 since we will use  	 * that to construct a fake %tstate to store into the regs.  	 */ diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 6ed3ae4f548..6e742cc4251 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -141,6 +141,19 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs);  extern unsigned long perf_misc_flags(struct pt_regs *regs);  #define perf_misc_flags(regs)	perf_misc_flags(regs) +#include <asm/stacktrace.h> + +/* + * We abuse bit 3 from flags to pass exact information, see perf_misc_flags + * and the comment with PERF_EFLAGS_EXACT. + */ +#define perf_arch_fetch_caller_regs(regs, __ip)		{	\ +	(regs)->ip = (__ip);					\ +	(regs)->bp = caller_frame_pointer();			\ +	(regs)->cs = __KERNEL_CS;				\ +	regs->flags = 0;					\ +} +  #else  static inline void init_hw_perf_events(void)		{ }  static inline void perf_events_lapic_init(void)	{ } diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h index 4dab78edbad..2b16a2ad23d 100644 --- a/arch/x86/include/asm/stacktrace.h +++ b/arch/x86/include/asm/stacktrace.h @@ -1,6 +1,13 @@ +/* + *  Copyright (C) 1991, 1992  Linus Torvalds + *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs + */ +  #ifndef _ASM_X86_STACKTRACE_H  #define _ASM_X86_STACKTRACE_H +#include <linux/uaccess.h> +  extern int kstack_depth_to_print;  struct thread_info; @@ -42,4 +49,46 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,  		unsigned long *stack, unsigned long bp,  		const struct stacktrace_ops *ops, void *data); +#ifdef CONFIG_X86_32 +#define STACKSLOTS_PER_LINE 8 +#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :) +#else +#define STACKSLOTS_PER_LINE 4 +#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :) +#endif + +extern void +show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, +		unsigned long *stack, unsigned long bp, char *log_lvl); + +extern void +show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, +		unsigned long *sp, unsigned long bp, char *log_lvl); + +extern unsigned int code_bytes; + +/* The form of the top of the frame on the stack */ +struct stack_frame { +	struct stack_frame *next_frame; +	unsigned long return_address; +}; + +struct stack_frame_ia32 { +    u32 next_frame; +    u32 return_address; +}; + +static inline unsigned long caller_frame_pointer(void) +{ +	struct stack_frame *frame; + +	get_bp(frame); + +#ifdef CONFIG_FRAME_POINTER +	frame = frame->next_frame; +#endif + +	return (unsigned long)frame; +} +  #endif /* _ASM_X86_STACKTRACE_H */ diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 2d0d2906927..f2da20fda02 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1613,8 +1613,6 @@ static const struct stacktrace_ops backtrace_ops = {  	.walk_stack		= print_context_stack_bp,  }; -#include "../dumpstack.h" -  static void  perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry)  { @@ -1736,22 +1734,6 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)  	return entry;  } -void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) -{ -	regs->ip = ip; -	/* -	 * perf_arch_fetch_caller_regs adds another call, we need to increment -	 * the skip level -	 */ -	regs->bp = rewind_frame_pointer(skip + 1); -	regs->cs = __KERNEL_CS; -	/* -	 * We abuse bit 3 to pass exact information, see perf_misc_flags -	 * and the comment with PERF_EFLAGS_EXACT. -	 */ -	regs->flags = 0; -} -  unsigned long perf_instruction_pointer(struct pt_regs *regs)  {  	unsigned long ip; diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index c89a386930b..6e8752c1bd5 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -18,7 +18,6 @@  #include <asm/stacktrace.h> -#include "dumpstack.h"  int panic_on_unrecovered_nmi;  int panic_on_io_nmi; diff --git a/arch/x86/kernel/dumpstack.h b/arch/x86/kernel/dumpstack.h deleted file mode 100644 index e1a93be4fd4..00000000000 --- a/arch/x86/kernel/dumpstack.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - *  Copyright (C) 1991, 1992  Linus Torvalds - *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs - */ - -#ifndef DUMPSTACK_H -#define DUMPSTACK_H - -#ifdef CONFIG_X86_32 -#define STACKSLOTS_PER_LINE 8 -#define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :) -#else -#define STACKSLOTS_PER_LINE 4 -#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :) -#endif - -#include <linux/uaccess.h> - -extern void -show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, -		unsigned long *stack, unsigned long bp, char *log_lvl); - -extern void -show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, -		unsigned long *sp, unsigned long bp, char *log_lvl); - -extern unsigned int code_bytes; - -/* The form of the top of the frame on the stack */ -struct stack_frame { -	struct stack_frame *next_frame; -	unsigned long return_address; -}; - -struct stack_frame_ia32 { -    u32 next_frame; -    u32 return_address; -}; - -static inline unsigned long rewind_frame_pointer(int n) -{ -	struct stack_frame *frame; - -	get_bp(frame); - -#ifdef CONFIG_FRAME_POINTER -	while (n--) { -		if (probe_kernel_address(&frame->next_frame, frame)) -			break; -	} -#endif - -	return (unsigned long)frame; -} - -#endif /* DUMPSTACK_H */ diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index 11540a189d9..0f6376ffa2d 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c @@ -16,8 +16,6 @@  #include <asm/stacktrace.h> -#include "dumpstack.h" -  void dump_trace(struct task_struct *task, struct pt_regs *regs,  		unsigned long *stack, unsigned long bp, diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 272c9f1f05f..57a21f11c79 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c @@ -16,7 +16,6 @@  #include <asm/stacktrace.h> -#include "dumpstack.h"  #define N_EXCEPTION_STACKS_END \  		(N_EXCEPTION_STACKS + DEBUG_STKSZ/EXCEPTION_STKSZ - 2) diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c index 922eefbb3f6..b53c525368a 100644 --- a/arch/x86/kernel/stacktrace.c +++ b/arch/x86/kernel/stacktrace.c @@ -23,11 +23,16 @@ static int save_stack_stack(void *data, char *name)  	return 0;  } -static void save_stack_address(void *data, unsigned long addr, int reliable) +static void +__save_stack_address(void *data, unsigned long addr, bool reliable, bool nosched)  {  	struct stack_trace *trace = data; +#ifdef CONFIG_FRAME_POINTER  	if (!reliable)  		return; +#endif +	if (nosched && in_sched_functions(addr)) +		return;  	if (trace->skip > 0) {  		trace->skip--;  		return; @@ -36,20 +41,15 @@ static void save_stack_address(void *data, unsigned long addr, int reliable)  		trace->entries[trace->nr_entries++] = addr;  } +static void save_stack_address(void *data, unsigned long addr, int reliable) +{ +	return __save_stack_address(data, addr, reliable, false); +} +  static void  save_stack_address_nosched(void *data, unsigned long addr, int reliable)  { -	struct stack_trace *trace = (struct stack_trace *)data; -	if (!reliable) -		return; -	if (in_sched_functions(addr)) -		return; -	if (trace->skip > 0) { -		trace->skip--; -		return; -	} -	if (trace->nr_entries < trace->max_entries) -		trace->entries[trace->nr_entries++] = addr; +	return __save_stack_address(data, addr, reliable, true);  }  static const struct stacktrace_ops save_stack_ops = { @@ -96,12 +96,13 @@ EXPORT_SYMBOL_GPL(save_stack_trace_tsk);  /* Userspace stacktrace - based on kernel/trace/trace_sysprof.c */ -struct stack_frame { +struct stack_frame_user {  	const void __user	*next_fp;  	unsigned long		ret_addr;  }; -static int copy_stack_frame(const void __user *fp, struct stack_frame *frame) +static int +copy_stack_frame(const void __user *fp, struct stack_frame_user *frame)  {  	int ret; @@ -126,7 +127,7 @@ static inline void __save_stack_trace_user(struct stack_trace *trace)  		trace->entries[trace->nr_entries++] = regs->ip;  	while (trace->nr_entries < trace->max_entries) { -		struct stack_frame frame; +		struct stack_frame_user frame;  		frame.next_fp = NULL;  		frame.ret_addr = 0; diff --git a/include/linux/kmemtrace.h b/include/linux/kmemtrace.h deleted file mode 100644 index b616d3930c3..00000000000 --- a/include/linux/kmemtrace.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2008 Eduard - Gabriel Munteanu - * - * This file is released under GPL version 2. - */ - -#ifndef _LINUX_KMEMTRACE_H -#define _LINUX_KMEMTRACE_H - -#ifdef __KERNEL__ - -#include <trace/events/kmem.h> - -#ifdef CONFIG_KMEMTRACE -extern void kmemtrace_init(void); -#else -static inline void kmemtrace_init(void) -{ -} -#endif - -#endif /* __KERNEL__ */ - -#endif /* _LINUX_KMEMTRACE_H */ - diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 1218d05728b..63b5aa5dce6 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -932,8 +932,10 @@ extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX];  extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64); -extern void -perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip); +#ifndef perf_arch_fetch_caller_regs +static inline void +perf_arch_fetch_caller_regs(struct regs *regs, unsigned long ip) { } +#endif  /*   * Take a snapshot of the regs. Skip ip and frame pointer to @@ -943,31 +945,11 @@ perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip);   * - bp for callchains   * - eflags, for future purposes, just in case   */ -static inline void perf_fetch_caller_regs(struct pt_regs *regs, int skip) +static inline void perf_fetch_caller_regs(struct pt_regs *regs)  { -	unsigned long ip; -  	memset(regs, 0, sizeof(*regs)); -	switch (skip) { -	case 1 : -		ip = CALLER_ADDR0; -		break; -	case 2 : -		ip = CALLER_ADDR1; -		break; -	case 3 : -		ip = CALLER_ADDR2; -		break; -	case 4: -		ip = CALLER_ADDR3; -		break; -	/* No need to support further for now */ -	default: -		ip = 0; -	} - -	return perf_arch_fetch_caller_regs(regs, ip, skip); +	perf_arch_fetch_caller_regs(regs, CALLER_ADDR0);  }  static inline void @@ -977,7 +959,7 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr)  		struct pt_regs hot_regs;  		if (!regs) { -			perf_fetch_caller_regs(&hot_regs, 1); +			perf_fetch_caller_regs(&hot_regs);  			regs = &hot_regs;  		}  		__perf_sw_event(event_id, nr, nmi, regs, addr); diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 1812dac8c49..1acfa73ce2a 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -14,7 +14,8 @@  #include <asm/page.h>		/* kmalloc_sizes.h needs PAGE_SIZE */  #include <asm/cache.h>		/* kmalloc_sizes.h needs L1_CACHE_BYTES */  #include <linux/compiler.h> -#include <linux/kmemtrace.h> + +#include <trace/events/kmem.h>  #ifndef ARCH_KMALLOC_MINALIGN  /* diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 4ba59cfc1f7..6447a723ecb 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -10,9 +10,10 @@  #include <linux/gfp.h>  #include <linux/workqueue.h>  #include <linux/kobject.h> -#include <linux/kmemtrace.h>  #include <linux/kmemleak.h> +#include <trace/events/kmem.h> +  enum stat_item {  	ALLOC_FASTPATH,		/* Allocation from cpu slab */  	ALLOC_SLOWPATH,		/* Allocation by getting a new cpu slab */ diff --git a/include/trace/boot.h b/include/trace/boot.h deleted file mode 100644 index 088ea089e31..00000000000 --- a/include/trace/boot.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _LINUX_TRACE_BOOT_H -#define _LINUX_TRACE_BOOT_H - -#include <linux/module.h> -#include <linux/kallsyms.h> -#include <linux/init.h> - -/* - * Structure which defines the trace of an initcall - * while it is called. - * You don't have to fill the func field since it is - * only used internally by the tracer. - */ -struct boot_trace_call { -	pid_t			caller; -	char			func[KSYM_SYMBOL_LEN]; -}; - -/* - * Structure which defines the trace of an initcall - * while it returns. - */ -struct boot_trace_ret { -	char			func[KSYM_SYMBOL_LEN]; -	int				result; -	unsigned long long	duration;		/* nsecs */ -}; - -#ifdef CONFIG_BOOT_TRACER -/* Append the traces on the ring-buffer */ -extern void trace_boot_call(struct boot_trace_call *bt, initcall_t fn); -extern void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn); - -/* Tells the tracer that smp_pre_initcall is finished. - * So we can start the tracing - */ -extern void start_boot_trace(void); - -/* Resume the tracing of other necessary events - * such as sched switches - */ -extern void enable_boot_trace(void); - -/* Suspend this tracing. Actually, only sched_switches tracing have - * to be suspended. Initcalls doesn't need it.) - */ -extern void disable_boot_trace(void); -#else -static inline -void trace_boot_call(struct boot_trace_call *bt, initcall_t fn) { } - -static inline -void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn) { } - -static inline void start_boot_trace(void) { } -static inline void enable_boot_trace(void) { } -static inline void disable_boot_trace(void) { } -#endif /* CONFIG_BOOT_TRACER */ - -#endif /* __LINUX_TRACE_BOOT_H */ diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 5a64905d727..fc013a8201e 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -705,7 +705,7 @@ perf_trace_##call(void *__data, proto)					\  	int __data_size;						\  	int rctx;							\  									\ -	perf_fetch_caller_regs(&__regs, 1);				\ +	perf_fetch_caller_regs(&__regs);				\  									\  	__data_size = ftrace_get_offsets_##call(&__data_offsets, args); \  	__entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\ diff --git a/init/main.c b/init/main.c index 3bdb152f412..e2a2bf3a169 100644 --- a/init/main.c +++ b/init/main.c @@ -66,11 +66,9 @@  #include <linux/ftrace.h>  #include <linux/async.h>  #include <linux/kmemcheck.h> -#include <linux/kmemtrace.h>  #include <linux/sfi.h>  #include <linux/shmem_fs.h>  #include <linux/slab.h> -#include <trace/boot.h>  #include <asm/io.h>  #include <asm/bugs.h> @@ -653,7 +651,6 @@ asmlinkage void __init start_kernel(void)  #endif  	page_cgroup_init();  	enable_debug_pagealloc(); -	kmemtrace_init();  	kmemleak_init();  	debug_objects_mem_init();  	idr_init_cache(); @@ -715,38 +712,33 @@ int initcall_debug;  core_param(initcall_debug, initcall_debug, bool, 0644);  static char msgbuf[64]; -static struct boot_trace_call call; -static struct boot_trace_ret ret;  int do_one_initcall(initcall_t fn)  {  	int count = preempt_count();  	ktime_t calltime, delta, rettime; +	unsigned long long duration; +	int ret;  	if (initcall_debug) { -		call.caller = task_pid_nr(current); -		printk("calling  %pF @ %i\n", fn, call.caller); +		printk("calling  %pF @ %i\n", fn, task_pid_nr(current));  		calltime = ktime_get(); -		trace_boot_call(&call, fn); -		enable_boot_trace();  	} -	ret.result = fn(); +	ret = fn();  	if (initcall_debug) { -		disable_boot_trace();  		rettime = ktime_get();  		delta = ktime_sub(rettime, calltime); -		ret.duration = (unsigned long long) ktime_to_ns(delta) >> 10; -		trace_boot_ret(&ret, fn); -		printk("initcall %pF returned %d after %Ld usecs\n", fn, -			ret.result, ret.duration); +		duration = (unsigned long long) ktime_to_ns(delta) >> 10; +		printk("initcall %pF returned %d after %lld usecs\n", fn, +			ret, duration);  	}  	msgbuf[0] = 0; -	if (ret.result && ret.result != -ENODEV && initcall_debug) -		sprintf(msgbuf, "error code %d ", ret.result); +	if (ret && ret != -ENODEV && initcall_debug) +		sprintf(msgbuf, "error code %d ", ret);  	if (preempt_count() != count) {  		strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf)); @@ -760,7 +752,7 @@ int do_one_initcall(initcall_t fn)  		printk("initcall %pF returned with %s\n", fn, msgbuf);  	} -	return ret.result; +	return ret;  } @@ -880,7 +872,6 @@ static int __init kernel_init(void * unused)  	smp_prepare_cpus(setup_max_cpus);  	do_pre_smp_initcalls(); -	start_boot_trace();  	smp_init();  	sched_init_smp(); diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 97c73018592..c772a3d4000 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -2946,11 +2946,6 @@ __weak struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)  	return NULL;  } -__weak -void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) -{ -} -  /*   * We assume there is only KVM supporting the callbacks. diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 8b1797c4545..f669092fdea 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -229,23 +229,6 @@ config FTRACE_SYSCALLS  	help  	  Basic tracer to catch the syscall entry and exit events. -config BOOT_TRACER -	bool "Trace boot initcalls" -	select GENERIC_TRACER -	select CONTEXT_SWITCH_TRACER -	help -	  This tracer helps developers to optimize boot times: it records -	  the timings of the initcalls and traces key events and the identity -	  of tasks that can cause boot delays, such as context-switches. - -	  Its aim is to be parsed by the scripts/bootgraph.pl tool to -	  produce pretty graphics about boot inefficiencies, giving a visual -	  representation of the delays during initcalls - but the raw -	  /debug/tracing/trace text output is readable too. - -	  You must pass in initcall_debug and ftrace=initcall to the kernel -	  command line to enable this on bootup. -  config TRACE_BRANCH_PROFILING  	bool  	select GENERIC_TRACER @@ -371,26 +354,6 @@ config STACK_TRACER  	  Say N if unsure. -config KMEMTRACE -	bool "Trace SLAB allocations" -	select GENERIC_TRACER -	help -	  kmemtrace provides tracing for slab allocator functions, such as -	  kmalloc, kfree, kmem_cache_alloc, kmem_cache_free, etc. Collected -	  data is then fed to the userspace application in order to analyse -	  allocation hotspots, internal fragmentation and so on, making it -	  possible to see how well an allocator performs, as well as debug -	  and profile kernel code. - -	  This requires an userspace application to use. See -	  Documentation/trace/kmemtrace.txt for more information. - -	  Saying Y will make the kernel somewhat larger and slower. However, -	  if you disable kmemtrace at run-time or boot-time, the performance -	  impact is minimal (depending on the arch the kernel is built for). - -	  If unsure, say N. -  config WORKQUEUE_TRACER  	bool "Trace workqueues"  	select GENERIC_TRACER diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index ffb1a5b0550..469a1c7555a 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -38,10 +38,8 @@ obj-$(CONFIG_SCHED_TRACER) += trace_sched_wakeup.o  obj-$(CONFIG_NOP_TRACER) += trace_nop.o  obj-$(CONFIG_STACK_TRACER) += trace_stack.o  obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o -obj-$(CONFIG_BOOT_TRACER) += trace_boot.o  obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += trace_functions_graph.o  obj-$(CONFIG_TRACE_BRANCH_PROFILING) += trace_branch.o -obj-$(CONFIG_KMEMTRACE) += kmemtrace.o  obj-$(CONFIG_WORKQUEUE_TRACER) += trace_workqueue.o  obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o  ifeq ($(CONFIG_BLOCK),y) diff --git a/kernel/trace/kmemtrace.c b/kernel/trace/kmemtrace.c deleted file mode 100644 index bbfc1bb1660..00000000000 --- a/kernel/trace/kmemtrace.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Memory allocator tracing - * - * Copyright (C) 2008 Eduard - Gabriel Munteanu - * Copyright (C) 2008 Pekka Enberg <penberg@cs.helsinki.fi> - * Copyright (C) 2008 Frederic Weisbecker <fweisbec@gmail.com> - */ - -#include <linux/tracepoint.h> -#include <linux/seq_file.h> -#include <linux/debugfs.h> -#include <linux/dcache.h> -#include <linux/fs.h> - -#include <linux/kmemtrace.h> - -#include "trace_output.h" -#include "trace.h" - -/* Select an alternative, minimalistic output than the original one */ -#define TRACE_KMEM_OPT_MINIMAL	0x1 - -static struct tracer_opt kmem_opts[] = { -	/* Default disable the minimalistic output */ -	{ TRACER_OPT(kmem_minimalistic, TRACE_KMEM_OPT_MINIMAL) }, -	{ } -}; - -static struct tracer_flags kmem_tracer_flags = { -	.val			= 0, -	.opts			= kmem_opts -}; - -static struct trace_array *kmemtrace_array; - -/* Trace allocations */ -static inline void kmemtrace_alloc(enum kmemtrace_type_id type_id, -				   unsigned long call_site, -				   const void *ptr, -				   size_t bytes_req, -				   size_t bytes_alloc, -				   gfp_t gfp_flags, -				   int node) -{ -	struct ftrace_event_call *call = &event_kmem_alloc; -	struct trace_array *tr = kmemtrace_array; -	struct kmemtrace_alloc_entry *entry; -	struct ring_buffer_event *event; - -	event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry)); -	if (!event) -		return; - -	entry = ring_buffer_event_data(event); -	tracing_generic_entry_update(&entry->ent, 0, 0); - -	entry->ent.type		= TRACE_KMEM_ALLOC; -	entry->type_id		= type_id; -	entry->call_site	= call_site; -	entry->ptr		= ptr; -	entry->bytes_req	= bytes_req; -	entry->bytes_alloc	= bytes_alloc; -	entry->gfp_flags	= gfp_flags; -	entry->node		= node; - -	if (!filter_check_discard(call, entry, tr->buffer, event)) -		ring_buffer_unlock_commit(tr->buffer, event); - -	trace_wake_up(); -} - -static inline void kmemtrace_free(enum kmemtrace_type_id type_id, -				  unsigned long call_site, -				  const void *ptr) -{ -	struct ftrace_event_call *call = &event_kmem_free; -	struct trace_array *tr = kmemtrace_array; -	struct kmemtrace_free_entry *entry; -	struct ring_buffer_event *event; - -	event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry)); -	if (!event) -		return; -	entry	= ring_buffer_event_data(event); -	tracing_generic_entry_update(&entry->ent, 0, 0); - -	entry->ent.type		= TRACE_KMEM_FREE; -	entry->type_id		= type_id; -	entry->call_site	= call_site; -	entry->ptr		= ptr; - -	if (!filter_check_discard(call, entry, tr->buffer, event)) -		ring_buffer_unlock_commit(tr->buffer, event); - -	trace_wake_up(); -} - -static void kmemtrace_kmalloc(void *ignore, -			      unsigned long call_site, -			      const void *ptr, -			      size_t bytes_req, -			      size_t bytes_alloc, -			      gfp_t gfp_flags) -{ -	kmemtrace_alloc(KMEMTRACE_TYPE_KMALLOC, call_site, ptr, -			bytes_req, bytes_alloc, gfp_flags, -1); -} - -static void kmemtrace_kmem_cache_alloc(void *ignore, -				       unsigned long call_site, -				       const void *ptr, -				       size_t bytes_req, -				       size_t bytes_alloc, -				       gfp_t gfp_flags) -{ -	kmemtrace_alloc(KMEMTRACE_TYPE_CACHE, call_site, ptr, -			bytes_req, bytes_alloc, gfp_flags, -1); -} - -static void kmemtrace_kmalloc_node(void *ignore, -				   unsigned long call_site, -				   const void *ptr, -				   size_t bytes_req, -				   size_t bytes_alloc, -				   gfp_t gfp_flags, -				   int node) -{ -	kmemtrace_alloc(KMEMTRACE_TYPE_KMALLOC, call_site, ptr, -			bytes_req, bytes_alloc, gfp_flags, node); -} - -static void kmemtrace_kmem_cache_alloc_node(void *ignore, -					    unsigned long call_site, -					    const void *ptr, -					    size_t bytes_req, -					    size_t bytes_alloc, -					    gfp_t gfp_flags, -					    int node) -{ -	kmemtrace_alloc(KMEMTRACE_TYPE_CACHE, call_site, ptr, -			bytes_req, bytes_alloc, gfp_flags, node); -} - -static void -kmemtrace_kfree(void *ignore, unsigned long call_site, const void *ptr) -{ -	kmemtrace_free(KMEMTRACE_TYPE_KMALLOC, call_site, ptr); -} - -static void kmemtrace_kmem_cache_free(void *ignore, -				      unsigned long call_site, const void *ptr) -{ -	kmemtrace_free(KMEMTRACE_TYPE_CACHE, call_site, ptr); -} - -static int kmemtrace_start_probes(void) -{ -	int err; - -	err = register_trace_kmalloc(kmemtrace_kmalloc, NULL); -	if (err) -		return err; -	err = register_trace_kmem_cache_alloc(kmemtrace_kmem_cache_alloc, NULL); -	if (err) -		return err; -	err = register_trace_kmalloc_node(kmemtrace_kmalloc_node, NULL); -	if (err) -		return err; -	err = register_trace_kmem_cache_alloc_node(kmemtrace_kmem_cache_alloc_node, NULL); -	if (err) -		return err; -	err = register_trace_kfree(kmemtrace_kfree, NULL); -	if (err) -		return err; -	err = register_trace_kmem_cache_free(kmemtrace_kmem_cache_free, NULL); - -	return err; -} - -static void kmemtrace_stop_probes(void) -{ -	unregister_trace_kmalloc(kmemtrace_kmalloc, NULL); -	unregister_trace_kmem_cache_alloc(kmemtrace_kmem_cache_alloc, NULL); -	unregister_trace_kmalloc_node(kmemtrace_kmalloc_node, NULL); -	unregister_trace_kmem_cache_alloc_node(kmemtrace_kmem_cache_alloc_node, NULL); -	unregister_trace_kfree(kmemtrace_kfree, NULL); -	unregister_trace_kmem_cache_free(kmemtrace_kmem_cache_free, NULL); -} - -static int kmem_trace_init(struct trace_array *tr) -{ -	kmemtrace_array = tr; - -	tracing_reset_online_cpus(tr); - -	kmemtrace_start_probes(); - -	return 0; -} - -static void kmem_trace_reset(struct trace_array *tr) -{ -	kmemtrace_stop_probes(); -} - -static void kmemtrace_headers(struct seq_file *s) -{ -	/* Don't need headers for the original kmemtrace output */ -	if (!(kmem_tracer_flags.val & TRACE_KMEM_OPT_MINIMAL)) -		return; - -	seq_printf(s, "#\n"); -	seq_printf(s, "# ALLOC  TYPE  REQ   GIVEN  FLAGS     " -			"      POINTER         NODE    CALLER\n"); -	seq_printf(s, "# FREE   |      |     |       |       " -			"       |   |            |        |\n"); -	seq_printf(s, "# |\n\n"); -} - -/* - * The following functions give the original output from kmemtrace, - * plus the origin CPU, since reordering occurs in-kernel now. - */ - -#define KMEMTRACE_USER_ALLOC	0 -#define KMEMTRACE_USER_FREE	1 - -struct kmemtrace_user_event { -	u8			event_id; -	u8			type_id; -	u16			event_size; -	u32			cpu; -	u64			timestamp; -	unsigned long		call_site; -	unsigned long		ptr; -}; - -struct kmemtrace_user_event_alloc { -	size_t			bytes_req; -	size_t			bytes_alloc; -	unsigned		gfp_flags; -	int			node; -}; - -static enum print_line_t -kmemtrace_print_alloc(struct trace_iterator *iter, int flags, -		      struct trace_event *event) -{ -	struct trace_seq *s = &iter->seq; -	struct kmemtrace_alloc_entry *entry; -	int ret; - -	trace_assign_type(entry, iter->ent); - -	ret = trace_seq_printf(s, "type_id %d call_site %pF ptr %lu " -	    "bytes_req %lu bytes_alloc %lu gfp_flags %lu node %d\n", -	    entry->type_id, (void *)entry->call_site, (unsigned long)entry->ptr, -	    (unsigned long)entry->bytes_req, (unsigned long)entry->bytes_alloc, -	    (unsigned long)entry->gfp_flags, entry->node); - -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; -	return TRACE_TYPE_HANDLED; -} - -static enum print_line_t -kmemtrace_print_free(struct trace_iterator *iter, int flags, -		     struct trace_event *event) -{ -	struct trace_seq *s = &iter->seq; -	struct kmemtrace_free_entry *entry; -	int ret; - -	trace_assign_type(entry, iter->ent); - -	ret = trace_seq_printf(s, "type_id %d call_site %pF ptr %lu\n", -			       entry->type_id, (void *)entry->call_site, -			       (unsigned long)entry->ptr); - -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; -	return TRACE_TYPE_HANDLED; -} - -static enum print_line_t -kmemtrace_print_alloc_user(struct trace_iterator *iter, int flags, -			   struct trace_event *event) -{ -	struct trace_seq *s = &iter->seq; -	struct kmemtrace_alloc_entry *entry; -	struct kmemtrace_user_event *ev; -	struct kmemtrace_user_event_alloc *ev_alloc; - -	trace_assign_type(entry, iter->ent); - -	ev = trace_seq_reserve(s, sizeof(*ev)); -	if (!ev) -		return TRACE_TYPE_PARTIAL_LINE; - -	ev->event_id		= KMEMTRACE_USER_ALLOC; -	ev->type_id		= entry->type_id; -	ev->event_size		= sizeof(*ev) + sizeof(*ev_alloc); -	ev->cpu			= iter->cpu; -	ev->timestamp		= iter->ts; -	ev->call_site		= entry->call_site; -	ev->ptr			= (unsigned long)entry->ptr; - -	ev_alloc = trace_seq_reserve(s, sizeof(*ev_alloc)); -	if (!ev_alloc) -		return TRACE_TYPE_PARTIAL_LINE; - -	ev_alloc->bytes_req	= entry->bytes_req; -	ev_alloc->bytes_alloc	= entry->bytes_alloc; -	ev_alloc->gfp_flags	= entry->gfp_flags; -	ev_alloc->node		= entry->node; - -	return TRACE_TYPE_HANDLED; -} - -static enum print_line_t -kmemtrace_print_free_user(struct trace_iterator *iter, int flags, -			  struct trace_event *event) -{ -	struct trace_seq *s = &iter->seq; -	struct kmemtrace_free_entry *entry; -	struct kmemtrace_user_event *ev; - -	trace_assign_type(entry, iter->ent); - -	ev = trace_seq_reserve(s, sizeof(*ev)); -	if (!ev) -		return TRACE_TYPE_PARTIAL_LINE; - -	ev->event_id		= KMEMTRACE_USER_FREE; -	ev->type_id		= entry->type_id; -	ev->event_size		= sizeof(*ev); -	ev->cpu			= iter->cpu; -	ev->timestamp		= iter->ts; -	ev->call_site		= entry->call_site; -	ev->ptr			= (unsigned long)entry->ptr; - -	return TRACE_TYPE_HANDLED; -} - -/* The two other following provide a more minimalistic output */ -static enum print_line_t -kmemtrace_print_alloc_compress(struct trace_iterator *iter) -{ -	struct kmemtrace_alloc_entry *entry; -	struct trace_seq *s = &iter->seq; -	int ret; - -	trace_assign_type(entry, iter->ent); - -	/* Alloc entry */ -	ret = trace_seq_printf(s, "  +      "); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Type */ -	switch (entry->type_id) { -	case KMEMTRACE_TYPE_KMALLOC: -		ret = trace_seq_printf(s, "K   "); -		break; -	case KMEMTRACE_TYPE_CACHE: -		ret = trace_seq_printf(s, "C   "); -		break; -	case KMEMTRACE_TYPE_PAGES: -		ret = trace_seq_printf(s, "P   "); -		break; -	default: -		ret = trace_seq_printf(s, "?   "); -	} - -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Requested */ -	ret = trace_seq_printf(s, "%4zu   ", entry->bytes_req); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Allocated */ -	ret = trace_seq_printf(s, "%4zu   ", entry->bytes_alloc); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Flags -	 * TODO: would be better to see the name of the GFP flag names -	 */ -	ret = trace_seq_printf(s, "%08x   ", entry->gfp_flags); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Pointer to allocated */ -	ret = trace_seq_printf(s, "0x%tx   ", (ptrdiff_t)entry->ptr); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Node and call site*/ -	ret = trace_seq_printf(s, "%4d   %pf\n", entry->node, -						 (void *)entry->call_site); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	return TRACE_TYPE_HANDLED; -} - -static enum print_line_t -kmemtrace_print_free_compress(struct trace_iterator *iter) -{ -	struct kmemtrace_free_entry *entry; -	struct trace_seq *s = &iter->seq; -	int ret; - -	trace_assign_type(entry, iter->ent); - -	/* Free entry */ -	ret = trace_seq_printf(s, "  -      "); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Type */ -	switch (entry->type_id) { -	case KMEMTRACE_TYPE_KMALLOC: -		ret = trace_seq_printf(s, "K     "); -		break; -	case KMEMTRACE_TYPE_CACHE: -		ret = trace_seq_printf(s, "C     "); -		break; -	case KMEMTRACE_TYPE_PAGES: -		ret = trace_seq_printf(s, "P     "); -		break; -	default: -		ret = trace_seq_printf(s, "?     "); -	} - -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Skip requested/allocated/flags */ -	ret = trace_seq_printf(s, "                       "); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Pointer to allocated */ -	ret = trace_seq_printf(s, "0x%tx   ", (ptrdiff_t)entry->ptr); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	/* Skip node and print call site*/ -	ret = trace_seq_printf(s, "       %pf\n", (void *)entry->call_site); -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; - -	return TRACE_TYPE_HANDLED; -} - -static enum print_line_t kmemtrace_print_line(struct trace_iterator *iter) -{ -	struct trace_entry *entry = iter->ent; - -	if (!(kmem_tracer_flags.val & TRACE_KMEM_OPT_MINIMAL)) -		return TRACE_TYPE_UNHANDLED; - -	switch (entry->type) { -	case TRACE_KMEM_ALLOC: -		return kmemtrace_print_alloc_compress(iter); -	case TRACE_KMEM_FREE: -		return kmemtrace_print_free_compress(iter); -	default: -		return TRACE_TYPE_UNHANDLED; -	} -} - -static struct trace_event_functions kmem_trace_alloc_funcs = { -	.trace			= kmemtrace_print_alloc, -	.binary			= kmemtrace_print_alloc_user, -}; - -static struct trace_event kmem_trace_alloc = { -	.type			= TRACE_KMEM_ALLOC, -	.funcs			= &kmem_trace_alloc_funcs, -}; - -static struct trace_event_functions kmem_trace_free_funcs = { -	.trace			= kmemtrace_print_free, -	.binary			= kmemtrace_print_free_user, -}; - -static struct trace_event kmem_trace_free = { -	.type			= TRACE_KMEM_FREE, -	.funcs			= &kmem_trace_free_funcs, -}; - -static struct tracer kmem_tracer __read_mostly = { -	.name			= "kmemtrace", -	.init			= kmem_trace_init, -	.reset			= kmem_trace_reset, -	.print_line		= kmemtrace_print_line, -	.print_header		= kmemtrace_headers, -	.flags			= &kmem_tracer_flags -}; - -void kmemtrace_init(void) -{ -	/* earliest opportunity to start kmem tracing */ -} - -static int __init init_kmem_tracer(void) -{ -	if (!register_ftrace_event(&kmem_trace_alloc)) { -		pr_warning("Warning: could not register kmem events\n"); -		return 1; -	} - -	if (!register_ftrace_event(&kmem_trace_free)) { -		pr_warning("Warning: could not register kmem events\n"); -		return 1; -	} - -	if (register_tracer(&kmem_tracer) != 0) { -		pr_warning("Warning: could not register the kmem tracer\n"); -		return 1; -	} - -	return 0; -} -device_initcall(init_kmem_tracer); diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 644ab744e75..8683dec6946 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -4596,9 +4596,6 @@ __init static int tracer_alloc_buffers(void)  	register_tracer(&nop_trace);  	current_trace = &nop_trace; -#ifdef CONFIG_BOOT_TRACER -	register_tracer(&boot_tracer); -#endif  	/* All seems OK, enable tracing */  	tracing_disabled = 0; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 6c45e55097c..01ce088c1cd 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -9,10 +9,7 @@  #include <linux/mmiotrace.h>  #include <linux/tracepoint.h>  #include <linux/ftrace.h> -#include <trace/boot.h> -#include <linux/kmemtrace.h>  #include <linux/hw_breakpoint.h> -  #include <linux/trace_seq.h>  #include <linux/ftrace_event.h> @@ -29,26 +26,15 @@ enum trace_type {  	TRACE_MMIO_RW,  	TRACE_MMIO_MAP,  	TRACE_BRANCH, -	TRACE_BOOT_CALL, -	TRACE_BOOT_RET,  	TRACE_GRAPH_RET,  	TRACE_GRAPH_ENT,  	TRACE_USER_STACK, -	TRACE_KMEM_ALLOC, -	TRACE_KMEM_FREE,  	TRACE_BLK,  	TRACE_KSYM,  	__TRACE_LAST_TYPE,  }; -enum kmemtrace_type_id { -	KMEMTRACE_TYPE_KMALLOC = 0,	/* kmalloc() or kfree(). */ -	KMEMTRACE_TYPE_CACHE,		/* kmem_cache_*(). */ -	KMEMTRACE_TYPE_PAGES,		/* __get_free_pages() and friends. */ -}; - -extern struct tracer boot_tracer;  #undef __field  #define __field(type, item)		type	item; @@ -209,17 +195,11 @@ extern void __ftrace_bad_type(void);  			  TRACE_MMIO_RW);				\  		IF_ASSIGN(var, ent, struct trace_mmiotrace_map,		\  			  TRACE_MMIO_MAP);				\ -		IF_ASSIGN(var, ent, struct trace_boot_call, TRACE_BOOT_CALL);\ -		IF_ASSIGN(var, ent, struct trace_boot_ret, TRACE_BOOT_RET);\  		IF_ASSIGN(var, ent, struct trace_branch, TRACE_BRANCH); \  		IF_ASSIGN(var, ent, struct ftrace_graph_ent_entry,	\  			  TRACE_GRAPH_ENT);		\  		IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry,	\  			  TRACE_GRAPH_RET);		\ -		IF_ASSIGN(var, ent, struct kmemtrace_alloc_entry,	\ -			  TRACE_KMEM_ALLOC);	\ -		IF_ASSIGN(var, ent, struct kmemtrace_free_entry,	\ -			  TRACE_KMEM_FREE);	\  		IF_ASSIGN(var, ent, struct ksym_trace_entry, TRACE_KSYM);\  		__ftrace_bad_type();					\  	} while (0) diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c deleted file mode 100644 index c21d5f3956a..00000000000 --- a/kernel/trace/trace_boot.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * ring buffer based initcalls tracer - * - * Copyright (C) 2008 Frederic Weisbecker <fweisbec@gmail.com> - * - */ - -#include <linux/init.h> -#include <linux/debugfs.h> -#include <linux/ftrace.h> -#include <linux/kallsyms.h> -#include <linux/time.h> - -#include "trace.h" -#include "trace_output.h" - -static struct trace_array *boot_trace; -static bool pre_initcalls_finished; - -/* Tells the boot tracer that the pre_smp_initcalls are finished. - * So we are ready . - * It doesn't enable sched events tracing however. - * You have to call enable_boot_trace to do so. - */ -void start_boot_trace(void) -{ -	pre_initcalls_finished = true; -} - -void enable_boot_trace(void) -{ -	if (boot_trace && pre_initcalls_finished) -		tracing_start_sched_switch_record(); -} - -void disable_boot_trace(void) -{ -	if (boot_trace && pre_initcalls_finished) -		tracing_stop_sched_switch_record(); -} - -static int boot_trace_init(struct trace_array *tr) -{ -	boot_trace = tr; - -	if (!tr) -		return 0; - -	tracing_reset_online_cpus(tr); - -	tracing_sched_switch_assign_trace(tr); -	return 0; -} - -static enum print_line_t -initcall_call_print_line(struct trace_iterator *iter) -{ -	struct trace_entry *entry = iter->ent; -	struct trace_seq *s = &iter->seq; -	struct trace_boot_call *field; -	struct boot_trace_call *call; -	u64 ts; -	unsigned long nsec_rem; -	int ret; - -	trace_assign_type(field, entry); -	call = &field->boot_call; -	ts = iter->ts; -	nsec_rem = do_div(ts, NSEC_PER_SEC); - -	ret = trace_seq_printf(s, "[%5ld.%09ld] calling  %s @ %i\n", -			(unsigned long)ts, nsec_rem, call->func, call->caller); - -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; -	else -		return TRACE_TYPE_HANDLED; -} - -static enum print_line_t -initcall_ret_print_line(struct trace_iterator *iter) -{ -	struct trace_entry *entry = iter->ent; -	struct trace_seq *s = &iter->seq; -	struct trace_boot_ret *field; -	struct boot_trace_ret *init_ret; -	u64 ts; -	unsigned long nsec_rem; -	int ret; - -	trace_assign_type(field, entry); -	init_ret = &field->boot_ret; -	ts = iter->ts; -	nsec_rem = do_div(ts, NSEC_PER_SEC); - -	ret = trace_seq_printf(s, "[%5ld.%09ld] initcall %s " -			"returned %d after %llu msecs\n", -			(unsigned long) ts, -			nsec_rem, -			init_ret->func, init_ret->result, init_ret->duration); - -	if (!ret) -		return TRACE_TYPE_PARTIAL_LINE; -	else -		return TRACE_TYPE_HANDLED; -} - -static enum print_line_t initcall_print_line(struct trace_iterator *iter) -{ -	struct trace_entry *entry = iter->ent; - -	switch (entry->type) { -	case TRACE_BOOT_CALL: -		return initcall_call_print_line(iter); -	case TRACE_BOOT_RET: -		return initcall_ret_print_line(iter); -	default: -		return TRACE_TYPE_UNHANDLED; -	} -} - -struct tracer boot_tracer __read_mostly = -{ -	.name		= "initcall", -	.init		= boot_trace_init, -	.reset		= tracing_reset_online_cpus, -	.print_line	= initcall_print_line, -}; - -void trace_boot_call(struct boot_trace_call *bt, initcall_t fn) -{ -	struct ftrace_event_call *call = &event_boot_call; -	struct ring_buffer_event *event; -	struct ring_buffer *buffer; -	struct trace_boot_call *entry; -	struct trace_array *tr = boot_trace; - -	if (!tr || !pre_initcalls_finished) -		return; - -	/* Get its name now since this function could -	 * disappear because it is in the .init section. -	 */ -	sprint_symbol(bt->func, (unsigned long)fn); -	preempt_disable(); - -	buffer = tr->buffer; -	event = trace_buffer_lock_reserve(buffer, TRACE_BOOT_CALL, -					  sizeof(*entry), 0, 0); -	if (!event) -		goto out; -	entry	= ring_buffer_event_data(event); -	entry->boot_call = *bt; -	if (!filter_check_discard(call, entry, buffer, event)) -		trace_buffer_unlock_commit(buffer, event, 0, 0); - out: -	preempt_enable(); -} - -void trace_boot_ret(struct boot_trace_ret *bt, initcall_t fn) -{ -	struct ftrace_event_call *call = &event_boot_ret; -	struct ring_buffer_event *event; -	struct ring_buffer *buffer; -	struct trace_boot_ret *entry; -	struct trace_array *tr = boot_trace; - -	if (!tr || !pre_initcalls_finished) -		return; - -	sprint_symbol(bt->func, (unsigned long)fn); -	preempt_disable(); - -	buffer = tr->buffer; -	event = trace_buffer_lock_reserve(buffer, TRACE_BOOT_RET, -					  sizeof(*entry), 0, 0); -	if (!event) -		goto out; -	entry	= ring_buffer_event_data(event); -	entry->boot_ret = *bt; -	if (!filter_check_discard(call, entry, buffer, event)) -		trace_buffer_unlock_commit(buffer, event, 0, 0); - out: -	preempt_enable(); -} diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index dc008c1240d..13abc157dba 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h @@ -271,33 +271,6 @@ FTRACE_ENTRY(mmiotrace_map, trace_mmiotrace_map,  		 __entry->map_id, __entry->opcode)  ); -FTRACE_ENTRY(boot_call, trace_boot_call, - -	TRACE_BOOT_CALL, - -	F_STRUCT( -		__field_struct(	struct boot_trace_call,	boot_call	) -		__field_desc(	pid_t,	boot_call,	caller		) -		__array_desc(	char,	boot_call,	func,	KSYM_SYMBOL_LEN) -	), - -	F_printk("%d  %s", __entry->caller, __entry->func) -); - -FTRACE_ENTRY(boot_ret, trace_boot_ret, - -	TRACE_BOOT_RET, - -	F_STRUCT( -		__field_struct(	struct boot_trace_ret,	boot_ret	) -		__array_desc(	char,	boot_ret,	func,	KSYM_SYMBOL_LEN) -		__field_desc(	int,	boot_ret,	result		) -		__field_desc(	unsigned long, boot_ret, duration	) -	), - -	F_printk("%s %d %lx", -		 __entry->func, __entry->result, __entry->duration) -);  #define TRACE_FUNC_SIZE 30  #define TRACE_FILE_SIZE 20 @@ -318,41 +291,6 @@ FTRACE_ENTRY(branch, trace_branch,  		 __entry->func, __entry->file, __entry->correct)  ); -FTRACE_ENTRY(kmem_alloc, kmemtrace_alloc_entry, - -	TRACE_KMEM_ALLOC, - -	F_STRUCT( -		__field(	enum kmemtrace_type_id,	type_id		) -		__field(	unsigned long,		call_site	) -		__field(	const void *,		ptr		) -		__field(	size_t,			bytes_req	) -		__field(	size_t,			bytes_alloc	) -		__field(	gfp_t,			gfp_flags	) -		__field(	int,			node		) -	), - -	F_printk("type:%u call_site:%lx ptr:%p req:%zi alloc:%zi" -		 " flags:%x node:%d", -		 __entry->type_id, __entry->call_site, __entry->ptr, -		 __entry->bytes_req, __entry->bytes_alloc, -		 __entry->gfp_flags, __entry->node) -); - -FTRACE_ENTRY(kmem_free, kmemtrace_free_entry, - -	TRACE_KMEM_FREE, - -	F_STRUCT( -		__field(	enum kmemtrace_type_id,	type_id		) -		__field(	unsigned long,		call_site	) -		__field(	const void *,		ptr		) -	), - -	F_printk("type:%u call_site:%lx ptr:%p", -		 __entry->type_id, __entry->call_site, __entry->ptr) -); -  FTRACE_ENTRY(ksym_trace, ksym_trace_entry,  	TRACE_KSYM, diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index e6f65887842..4799d7047eb 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -9,8 +9,6 @@  #include <linux/kprobes.h>  #include "trace.h" -EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs); -  static char *perf_trace_buf[4];  /* diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c index a7974a552ca..c080956f4d8 100644 --- a/kernel/trace/trace_sysprof.c +++ b/kernel/trace/trace_sysprof.c @@ -33,12 +33,13 @@ static DEFINE_MUTEX(sample_timer_lock);   */  static DEFINE_PER_CPU(struct hrtimer, stack_trace_hrtimer); -struct stack_frame { +struct stack_frame_user {  	const void __user	*next_fp;  	unsigned long		return_address;  }; -static int copy_stack_frame(const void __user *fp, struct stack_frame *frame) +static int +copy_stack_frame(const void __user *fp, struct stack_frame_user *frame)  {  	int ret; @@ -125,7 +126,7 @@ trace_kernel(struct pt_regs *regs, struct trace_array *tr,  static void timer_notify(struct pt_regs *regs, int cpu)  {  	struct trace_array_cpu *data; -	struct stack_frame frame; +	struct stack_frame_user frame;  	struct trace_array *tr;  	const void __user *fp;  	int is_user; diff --git a/mm/slab.c b/mm/slab.c index e49f8f46f46..47360c3e5ab 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -102,7 +102,6 @@  #include	<linux/cpu.h>  #include	<linux/sysctl.h>  #include	<linux/module.h> -#include	<linux/kmemtrace.h>  #include	<linux/rcupdate.h>  #include	<linux/string.h>  #include	<linux/uaccess.h> diff --git a/mm/slob.c b/mm/slob.c index 23631e2bb57..a82ab5811bd 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -66,8 +66,10 @@  #include <linux/module.h>  #include <linux/rcupdate.h>  #include <linux/list.h> -#include <linux/kmemtrace.h>  #include <linux/kmemleak.h> + +#include <trace/events/kmem.h> +  #include <asm/atomic.h>  /* diff --git a/mm/slub.c b/mm/slub.c index 578f68f3c51..7bb7940f4ee 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -17,7 +17,6 @@  #include <linux/slab.h>  #include <linux/proc_fs.h>  #include <linux/seq_file.h> -#include <linux/kmemtrace.h>  #include <linux/kmemcheck.h>  #include <linux/cpu.h>  #include <linux/cpuset.h>  |