From 670c021bfa1a2d3e2877e40b3a147900ea06ca3e Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Sun, 16 Nov 2008 16:07:58 +0530 Subject: [PATCH] --- yaml --- r: 121151 b: refs/heads/master c: 0c726da983de0704254250ef6495ca152e7abcca h: refs/heads/master i: 121149: 1e1415ca73e7849fbd2b9baf3ff680560467d151 121147: 0856a0080b51fbedc6f2e1a482bd9e7615ca2c8e 121143: aae4241e15050fb2371612bb55f763b22409eafe 121135: 45a1491b36ebbfea7c701e808b751001ab263885 121119: b0b545d439ec6bc265bf4aa8a41f10e3cd2d27eb 121087: 0d6bdd5e98018ec494cbf84dbca1ca52a2828932 v: v3 --- [refs] | 2 +- trunk/Documentation/markers.txt | 14 - trunk/Documentation/tracepoints.txt | 92 +++--- trunk/arch/x86/include/asm/ftrace.h | 8 - trunk/arch/x86/kernel/entry_32.S | 18 +- trunk/arch/x86/kernel/ftrace.c | 286 ++++++++-------- trunk/include/asm-generic/vmlinux.lds.h | 1 - trunk/include/linux/ftrace.h | 69 +--- trunk/include/linux/marker.h | 67 +--- trunk/include/linux/rcupdate.h | 2 - trunk/include/linux/tracepoint.h | 53 ++- trunk/include/trace/sched.h | 24 +- trunk/init/Kconfig | 1 - trunk/kernel/exit.c | 4 - trunk/kernel/fork.c | 2 - trunk/kernel/kthread.c | 3 - trunk/kernel/marker.c | 114 +------ trunk/kernel/module.c | 11 +- trunk/kernel/sched.c | 6 - trunk/kernel/signal.c | 2 - trunk/kernel/trace/Kconfig | 1 + trunk/kernel/trace/ftrace.c | 304 ++++++++---------- trunk/kernel/trace/trace.c | 25 +- trunk/kernel/trace/trace.h | 5 +- trunk/kernel/trace/trace_boot.c | 3 +- trunk/kernel/trace/trace_branch.c | 3 +- trunk/kernel/trace/trace_functions.c | 3 +- trunk/kernel/trace/trace_functions_return.c | 16 +- trunk/kernel/trace/trace_irqsoff.c | 9 +- trunk/kernel/trace/trace_mmiotrace.c | 3 +- trunk/kernel/trace/trace_nop.c | 3 +- trunk/kernel/trace/trace_sched_switch.c | 3 +- trunk/kernel/trace/trace_sched_wakeup.c | 3 +- trunk/kernel/trace/trace_selftest.c | 70 +--- trunk/kernel/trace/trace_sysprof.c | 3 +- trunk/kernel/tracepoint.c | 34 -- trunk/samples/tracepoints/tp-samples-trace.h | 4 +- .../tracepoints/tracepoint-probe-sample.c | 1 - .../tracepoints/tracepoint-probe-sample2.c | 1 - trunk/samples/tracepoints/tracepoint-sample.c | 3 - 40 files changed, 430 insertions(+), 846 deletions(-) diff --git a/[refs] b/[refs] index 2dd0f2d84629..1a05dc38a7fc 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3f8e402f34ecc7d1d00b54703d3baa401b8bdd78 +refs/heads/master: 0c726da983de0704254250ef6495ca152e7abcca diff --git a/trunk/Documentation/markers.txt b/trunk/Documentation/markers.txt index 6d275e4ef385..089f6138fcd9 100644 --- a/trunk/Documentation/markers.txt +++ b/trunk/Documentation/markers.txt @@ -70,20 +70,6 @@ a printk warning which identifies the inconsistency: "Format mismatch for probe probe_name (format), marker (format)" -Another way to use markers is to simply define the marker without generating any -function call to actually call into the marker. This is useful in combination -with tracepoint probes in a scheme like this : - -void probe_tracepoint_name(unsigned int arg1, struct task_struct *tsk); - -DEFINE_MARKER_TP(marker_eventname, tracepoint_name, probe_tracepoint_name, - "arg1 %u pid %d"); - -notrace void probe_tracepoint_name(unsigned int arg1, struct task_struct *tsk) -{ - struct marker *marker = &GET_MARKER(kernel_irq_entry); - /* write data to trace buffers ... */ -} * Probe / marker example diff --git a/trunk/Documentation/tracepoints.txt b/trunk/Documentation/tracepoints.txt index 2d42241a25c3..5d354e167494 100644 --- a/trunk/Documentation/tracepoints.txt +++ b/trunk/Documentation/tracepoints.txt @@ -3,30 +3,28 @@ Mathieu Desnoyers -This document introduces Linux Kernel Tracepoints and their use. It -provides examples of how to insert tracepoints in the kernel and -connect probe functions to them and provides some examples of probe -functions. +This document introduces Linux Kernel Tracepoints and their use. It provides +examples of how to insert tracepoints in the kernel and connect probe functions +to them and provides some examples of probe functions. * Purpose of tracepoints -A tracepoint placed in code provides a hook to call a function (probe) -that you can provide at runtime. A tracepoint can be "on" (a probe is -connected to it) or "off" (no probe is attached). When a tracepoint is -"off" it has no effect, except for adding a tiny time penalty -(checking a condition for a branch) and space penalty (adding a few -bytes for the function call at the end of the instrumented function -and adds a data structure in a separate section). When a tracepoint -is "on", the function you provide is called each time the tracepoint -is executed, in the execution context of the caller. When the function -provided ends its execution, it returns to the caller (continuing from -the tracepoint site). +A tracepoint placed in code provides a hook to call a function (probe) that you +can provide at runtime. A tracepoint can be "on" (a probe is connected to it) or +"off" (no probe is attached). When a tracepoint is "off" it has no effect, +except for adding a tiny time penalty (checking a condition for a branch) and +space penalty (adding a few bytes for the function call at the end of the +instrumented function and adds a data structure in a separate section). When a +tracepoint is "on", the function you provide is called each time the tracepoint +is executed, in the execution context of the caller. When the function provided +ends its execution, it returns to the caller (continuing from the tracepoint +site). You can put tracepoints at important locations in the code. They are lightweight hooks that can pass an arbitrary number of parameters, -which prototypes are described in a tracepoint declaration placed in a -header file. +which prototypes are described in a tracepoint declaration placed in a header +file. They can be used for tracing and performance accounting. @@ -44,7 +42,7 @@ In include/trace/subsys.h : #include -DECLARE_TRACE(subsys_eventname, +DEFINE_TRACE(subsys_eventname, TPPTOTO(int firstarg, struct task_struct *p), TPARGS(firstarg, p)); @@ -52,8 +50,6 @@ In subsys/file.c (where the tracing statement must be added) : #include -DEFINE_TRACE(subsys_eventname); - void somefct(void) { ... @@ -65,41 +61,31 @@ Where : - subsys_eventname is an identifier unique to your event - subsys is the name of your subsystem. - eventname is the name of the event to trace. +- TPPTOTO(int firstarg, struct task_struct *p) is the prototype of the function + called by this tracepoint. +- TPARGS(firstarg, p) are the parameters names, same as found in the prototype. -- TPPTOTO(int firstarg, struct task_struct *p) is the prototype of the - function called by this tracepoint. - -- TPARGS(firstarg, p) are the parameters names, same as found in the - prototype. - -Connecting a function (probe) to a tracepoint is done by providing a -probe (function to call) for the specific tracepoint through +Connecting a function (probe) to a tracepoint is done by providing a probe +(function to call) for the specific tracepoint through register_trace_subsys_eventname(). Removing a probe is done through -unregister_trace_subsys_eventname(); it will remove the probe. - -tracepoint_synchronize_unregister() must be called before the end of -the module exit function to make sure there is no caller left using -the probe. This, and the fact that preemption is disabled around the -probe call, make sure that probe removal and module unload are safe. -See the "Probe example" section below for a sample probe module. - -The tracepoint mechanism supports inserting multiple instances of the -same tracepoint, but a single definition must be made of a given -tracepoint name over all the kernel to make sure no type conflict will -occur. Name mangling of the tracepoints is done using the prototypes -to make sure typing is correct. Verification of probe type correctness -is done at the registration site by the compiler. Tracepoints can be -put in inline functions, inlined static functions, and unrolled loops -as well as regular functions. - -The naming scheme "subsys_event" is suggested here as a convention -intended to limit collisions. Tracepoint names are global to the -kernel: they are considered as being the same whether they are in the -core kernel image or in modules. - -If the tracepoint has to be used in kernel modules, an -EXPORT_TRACEPOINT_SYMBOL_GPL() or EXPORT_TRACEPOINT_SYMBOL() can be -used to export the defined tracepoints. +unregister_trace_subsys_eventname(); it will remove the probe sure there is no +caller left using the probe when it returns. Probe removal is preempt-safe +because preemption is disabled around the probe call. See the "Probe example" +section below for a sample probe module. + +The tracepoint mechanism supports inserting multiple instances of the same +tracepoint, but a single definition must be made of a given tracepoint name over +all the kernel to make sure no type conflict will occur. Name mangling of the +tracepoints is done using the prototypes to make sure typing is correct. +Verification of probe type correctness is done at the registration site by the +compiler. Tracepoints can be put in inline functions, inlined static functions, +and unrolled loops as well as regular functions. + +The naming scheme "subsys_event" is suggested here as a convention intended +to limit collisions. Tracepoint names are global to the kernel: they are +considered as being the same whether they are in the core kernel image or in +modules. + * Probe / tracepoint example diff --git a/trunk/arch/x86/include/asm/ftrace.h b/trunk/arch/x86/include/asm/ftrace.h index 2bb43b433e07..9b6a1fa19e70 100644 --- a/trunk/arch/x86/include/asm/ftrace.h +++ b/trunk/arch/x86/include/asm/ftrace.h @@ -17,14 +17,6 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) */ return addr - 1; } - -#ifdef CONFIG_DYNAMIC_FTRACE - -struct dyn_arch_ftrace { - /* No extra data needed for x86 */ -}; - -#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* __ASSEMBLY__ */ #endif /* CONFIG_FUNCTION_TRACER */ diff --git a/trunk/arch/x86/kernel/entry_32.S b/trunk/arch/x86/kernel/entry_32.S index 74defe21ba42..f97621149839 100644 --- a/trunk/arch/x86/kernel/entry_32.S +++ b/trunk/arch/x86/kernel/entry_32.S @@ -1190,7 +1190,7 @@ ENTRY(mcount) jnz trace #ifdef CONFIG_FUNCTION_RET_TRACER cmpl $ftrace_stub, ftrace_function_return - jnz ftrace_return_caller + jnz trace_return #endif .globl ftrace_stub ftrace_stub: @@ -1211,15 +1211,9 @@ trace: popl %ecx popl %eax jmp ftrace_stub -END(mcount) -#endif /* CONFIG_DYNAMIC_FTRACE */ -#endif /* CONFIG_FUNCTION_TRACER */ #ifdef CONFIG_FUNCTION_RET_TRACER -ENTRY(ftrace_return_caller) - cmpl $0, function_trace_stop - jne ftrace_stub - +trace_return: pushl %eax pushl %ecx pushl %edx @@ -1229,8 +1223,7 @@ ENTRY(ftrace_return_caller) popl %edx popl %ecx popl %eax - ret -END(ftrace_return_caller) + jmp ftrace_stub .globl return_to_handler return_to_handler: @@ -1244,7 +1237,10 @@ return_to_handler: popl %ecx popl %eax ret -#endif +#endif /* CONFIG_FUNCTION_RET_TRACER */ +END(mcount) +#endif /* CONFIG_DYNAMIC_FTRACE */ +#endif /* CONFIG_FUNCTION_TRACER */ .section .rodata,"a" #include "syscall_table_32.S" diff --git a/trunk/arch/x86/kernel/ftrace.c b/trunk/arch/x86/kernel/ftrace.c index 924153edd973..fe832738e1e2 100644 --- a/trunk/arch/x86/kernel/ftrace.c +++ b/trunk/arch/x86/kernel/ftrace.c @@ -24,6 +24,133 @@ #include + +#ifdef CONFIG_FUNCTION_RET_TRACER + +/* + * These functions are picked from those used on + * this page for dynamic ftrace. They have been + * simplified to ignore all traces in NMI context. + */ +static atomic_t in_nmi; + +void ftrace_nmi_enter(void) +{ + atomic_inc(&in_nmi); +} + +void ftrace_nmi_exit(void) +{ + atomic_dec(&in_nmi); +} + +/* Add a function return address to the trace stack on thread info.*/ +static int push_return_trace(unsigned long ret, unsigned long long time, + unsigned long func) +{ + int index; + struct thread_info *ti = current_thread_info(); + + /* The return trace stack is full */ + if (ti->curr_ret_stack == FTRACE_RET_STACK_SIZE - 1) + return -EBUSY; + + index = ++ti->curr_ret_stack; + ti->ret_stack[index].ret = ret; + ti->ret_stack[index].func = func; + ti->ret_stack[index].calltime = time; + + return 0; +} + +/* Retrieve a function return address to the trace stack on thread info.*/ +static void pop_return_trace(unsigned long *ret, unsigned long long *time, + unsigned long *func) +{ + int index; + + struct thread_info *ti = current_thread_info(); + index = ti->curr_ret_stack; + *ret = ti->ret_stack[index].ret; + *func = ti->ret_stack[index].func; + *time = ti->ret_stack[index].calltime; + ti->curr_ret_stack--; +} + +/* + * Send the trace to the ring-buffer. + * @return the original return address. + */ +unsigned long ftrace_return_to_handler(void) +{ + struct ftrace_retfunc trace; + pop_return_trace(&trace.ret, &trace.calltime, &trace.func); + trace.rettime = cpu_clock(raw_smp_processor_id()); + ftrace_function_return(&trace); + + return trace.ret; +} + +/* + * Hook the return address and push it in the stack of return addrs + * in current thread info. + */ +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) +{ + unsigned long old; + unsigned long long calltime; + int faulted; + unsigned long return_hooker = (unsigned long) + &return_to_handler; + + /* Nmi's are currently unsupported */ + if (atomic_read(&in_nmi)) + return; + + /* + * Protect against fault, even if it shouldn't + * happen. This tool is too much intrusive to + * ignore such a protection. + */ + asm volatile( + "1: movl (%[parent_old]), %[old]\n" + "2: movl %[return_hooker], (%[parent_replaced])\n" + " movl $0, %[faulted]\n" + + ".section .fixup, \"ax\"\n" + "3: movl $1, %[faulted]\n" + ".previous\n" + + ".section __ex_table, \"a\"\n" + " .long 1b, 3b\n" + " .long 2b, 3b\n" + ".previous\n" + + : [parent_replaced] "=r" (parent), [old] "=r" (old), + [faulted] "=r" (faulted) + : [parent_old] "0" (parent), [return_hooker] "r" (return_hooker) + : "memory" + ); + + if (WARN_ON(faulted)) { + unregister_ftrace_return(); + return; + } + + if (WARN_ON(!__kernel_text_address(old))) { + unregister_ftrace_return(); + *parent = old; + return; + } + + calltime = cpu_clock(raw_smp_processor_id()); + + if (push_return_trace(old, calltime, self_addr) == -EBUSY) + *parent = old; +} + +#endif + #ifdef CONFIG_DYNAMIC_FTRACE union ftrace_code_union { @@ -39,7 +166,7 @@ static int ftrace_calc_offset(long ip, long addr) return (int)(addr - ip); } -static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) +unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) { static union ftrace_code_union calc; @@ -184,12 +311,12 @@ do_ftrace_mod_code(unsigned long ip, void *new_code) static unsigned char ftrace_nop[MCOUNT_INSN_SIZE]; -static unsigned char *ftrace_nop_replace(void) +unsigned char *ftrace_nop_replace(void) { return ftrace_nop; } -static int +int ftrace_modify_code(unsigned long ip, unsigned char *old_code, unsigned char *new_code) { @@ -222,29 +349,6 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code, return 0; } -int ftrace_make_nop(struct module *mod, - struct dyn_ftrace *rec, unsigned long addr) -{ - unsigned char *new, *old; - unsigned long ip = rec->ip; - - old = ftrace_call_replace(ip, addr); - new = ftrace_nop_replace(); - - return ftrace_modify_code(rec->ip, old, new); -} - -int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) -{ - unsigned char *new, *old; - unsigned long ip = rec->ip; - - old = ftrace_nop_replace(); - new = ftrace_call_replace(ip, addr); - - return ftrace_modify_code(rec->ip, old, new); -} - int ftrace_update_ftrace_func(ftrace_func_t func) { unsigned long ip = (unsigned long)(&ftrace_call); @@ -322,133 +426,3 @@ int __init ftrace_dyn_arch_init(void *data) return 0; } #endif - -#ifdef CONFIG_FUNCTION_RET_TRACER - -#ifndef CONFIG_DYNAMIC_FTRACE - -/* - * These functions are picked from those used on - * this page for dynamic ftrace. They have been - * simplified to ignore all traces in NMI context. - */ -static atomic_t in_nmi; - -void ftrace_nmi_enter(void) -{ - atomic_inc(&in_nmi); -} - -void ftrace_nmi_exit(void) -{ - atomic_dec(&in_nmi); -} -#endif /* !CONFIG_DYNAMIC_FTRACE */ - -/* Add a function return address to the trace stack on thread info.*/ -static int push_return_trace(unsigned long ret, unsigned long long time, - unsigned long func) -{ - int index; - struct thread_info *ti = current_thread_info(); - - /* The return trace stack is full */ - if (ti->curr_ret_stack == FTRACE_RET_STACK_SIZE - 1) - return -EBUSY; - - index = ++ti->curr_ret_stack; - barrier(); - ti->ret_stack[index].ret = ret; - ti->ret_stack[index].func = func; - ti->ret_stack[index].calltime = time; - - return 0; -} - -/* Retrieve a function return address to the trace stack on thread info.*/ -static void pop_return_trace(unsigned long *ret, unsigned long long *time, - unsigned long *func) -{ - int index; - - struct thread_info *ti = current_thread_info(); - index = ti->curr_ret_stack; - *ret = ti->ret_stack[index].ret; - *func = ti->ret_stack[index].func; - *time = ti->ret_stack[index].calltime; - ti->curr_ret_stack--; -} - -/* - * Send the trace to the ring-buffer. - * @return the original return address. - */ -unsigned long ftrace_return_to_handler(void) -{ - struct ftrace_retfunc trace; - pop_return_trace(&trace.ret, &trace.calltime, &trace.func); - trace.rettime = cpu_clock(raw_smp_processor_id()); - ftrace_function_return(&trace); - - return trace.ret; -} - -/* - * Hook the return address and push it in the stack of return addrs - * in current thread info. - */ -void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) -{ - unsigned long old; - unsigned long long calltime; - int faulted; - unsigned long return_hooker = (unsigned long) - &return_to_handler; - - /* Nmi's are currently unsupported */ - if (atomic_read(&in_nmi)) - return; - - /* - * Protect against fault, even if it shouldn't - * happen. This tool is too much intrusive to - * ignore such a protection. - */ - asm volatile( - "1: movl (%[parent_old]), %[old]\n" - "2: movl %[return_hooker], (%[parent_replaced])\n" - " movl $0, %[faulted]\n" - - ".section .fixup, \"ax\"\n" - "3: movl $1, %[faulted]\n" - ".previous\n" - - ".section __ex_table, \"a\"\n" - " .long 1b, 3b\n" - " .long 2b, 3b\n" - ".previous\n" - - : [parent_replaced] "=r" (parent), [old] "=r" (old), - [faulted] "=r" (faulted) - : [parent_old] "0" (parent), [return_hooker] "r" (return_hooker) - : "memory" - ); - - if (WARN_ON(faulted)) { - unregister_ftrace_return(); - return; - } - - if (WARN_ON(!__kernel_text_address(old))) { - unregister_ftrace_return(); - *parent = old; - return; - } - - calltime = cpu_clock(raw_smp_processor_id()); - - if (push_return_trace(old, calltime, self_addr) == -EBUSY) - *parent = old; -} - -#endif /* CONFIG_FUNCTION_RET_TRACER */ diff --git a/trunk/include/asm-generic/vmlinux.lds.h b/trunk/include/asm-generic/vmlinux.lds.h index 3b46ae464933..a5e4ed9baec8 100644 --- a/trunk/include/asm-generic/vmlinux.lds.h +++ b/trunk/include/asm-generic/vmlinux.lds.h @@ -71,7 +71,6 @@ VMLINUX_SYMBOL(__start___markers) = .; \ *(__markers) \ VMLINUX_SYMBOL(__stop___markers) = .; \ - . = ALIGN(32); \ VMLINUX_SYMBOL(__start___tracepoints) = .; \ *(__tracepoints) \ VMLINUX_SYMBOL(__stop___tracepoints) = .; \ diff --git a/trunk/include/linux/ftrace.h b/trunk/include/linux/ftrace.h index f1af1aab00e6..4fbc4a8b86a5 100644 --- a/trunk/include/linux/ftrace.h +++ b/trunk/include/linux/ftrace.h @@ -25,17 +25,6 @@ struct ftrace_ops { extern int function_trace_stop; -/* - * Type of the current tracing. - */ -enum ftrace_tracing_type_t { - FTRACE_TYPE_ENTER = 0, /* Hook the call of the function */ - FTRACE_TYPE_RETURN, /* Hook the return of the function */ -}; - -/* Current tracing type, default is FTRACE_TYPE_ENTER */ -extern enum ftrace_tracing_type_t ftrace_tracing_type; - /** * ftrace_stop - stop function tracer. * @@ -85,9 +74,6 @@ static inline void ftrace_start(void) { } #endif /* CONFIG_FUNCTION_TRACER */ #ifdef CONFIG_DYNAMIC_FTRACE -/* asm/ftrace.h must be defined for archs supporting dynamic ftrace */ -#include - enum { FTRACE_FL_FREE = (1 << 0), FTRACE_FL_FAILED = (1 << 1), @@ -102,7 +88,6 @@ struct dyn_ftrace { struct list_head list; unsigned long ip; /* address of mcount call-site */ unsigned long flags; - struct dyn_arch_ftrace arch; }; int ftrace_force_update(void); @@ -110,43 +95,22 @@ void ftrace_set_filter(unsigned char *buf, int len, int reset); /* defined in arch */ extern int ftrace_ip_converted(unsigned long ip); +extern unsigned char *ftrace_nop_replace(void); +extern unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr); extern int ftrace_dyn_arch_init(void *data); extern int ftrace_update_ftrace_func(ftrace_func_t func); extern void ftrace_caller(void); extern void ftrace_call(void); extern void mcount_call(void); -#ifdef CONFIG_FUNCTION_RET_TRACER -extern void ftrace_return_caller(void); -#endif -/** - * ftrace_make_nop - convert code into top - * @mod: module structure if called by module load initialization - * @rec: the mcount call site record - * @addr: the address that the call site should be calling - * - * This is a very sensitive operation and great care needs - * to be taken by the arch. The operation should carefully - * read the location, check to see if what is read is indeed - * what we expect it to be, and then on success of the compare, - * it should write to the location. - * - * The code segment at @rec->ip should be a caller to @addr - * - * Return must be: - * 0 on success - * -EFAULT on error reading the location - * -EINVAL on a failed compare of the contents - * -EPERM on error writing to the location - * Any other value will be considered a failure. - */ -extern int ftrace_make_nop(struct module *mod, - struct dyn_ftrace *rec, unsigned long addr); +/* May be defined in arch */ +extern int ftrace_arch_read_dyn_info(char *buf, int size); /** - * ftrace_make_call - convert a nop call site into a call to addr - * @rec: the mcount call site record - * @addr: the address that the call site should call + * ftrace_modify_code - modify code segment + * @ip: the address of the code segment + * @old_code: the contents of what is expected to be there + * @new_code: the code to patch in * * This is a very sensitive operation and great care needs * to be taken by the arch. The operation should carefully @@ -154,8 +118,6 @@ extern int ftrace_make_nop(struct module *mod, * what we expect it to be, and then on success of the compare, * it should write to the location. * - * The code segment at @rec->ip should be a nop - * * Return must be: * 0 on success * -EFAULT on error reading the location @@ -163,11 +125,8 @@ extern int ftrace_make_nop(struct module *mod, * -EPERM on error writing to the location * Any other value will be considered a failure. */ -extern int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr); - - -/* May be defined in arch */ -extern int ftrace_arch_read_dyn_info(char *buf, int size); +extern int ftrace_modify_code(unsigned long ip, unsigned char *old_code, + unsigned char *new_code); extern int skip_trace(unsigned long ip); @@ -300,13 +259,11 @@ static inline void ftrace_dump(void) { } #ifdef CONFIG_FTRACE_MCOUNT_RECORD extern void ftrace_init(void); -extern void ftrace_init_module(struct module *mod, - unsigned long *start, unsigned long *end); +extern void ftrace_init_module(unsigned long *start, unsigned long *end); #else static inline void ftrace_init(void) { } static inline void -ftrace_init_module(struct module *mod, - unsigned long *start, unsigned long *end) { } +ftrace_init_module(unsigned long *start, unsigned long *end) { } #endif @@ -324,7 +281,7 @@ struct ftrace_retfunc { /* Type of a callback handler of tracing return function */ typedef void (*trace_function_return_t)(struct ftrace_retfunc *); -extern int register_ftrace_return(trace_function_return_t func); +extern void register_ftrace_return(trace_function_return_t func); /* The current handler in use */ extern trace_function_return_t ftrace_function_return; extern void unregister_ftrace_return(void); diff --git a/trunk/include/linux/marker.h b/trunk/include/linux/marker.h index 34c14bc957f5..4cf45472d9f5 100644 --- a/trunk/include/linux/marker.h +++ b/trunk/include/linux/marker.h @@ -12,7 +12,6 @@ * See the file COPYING for more details. */ -#include #include struct module; @@ -49,28 +48,10 @@ struct marker { void (*call)(const struct marker *mdata, void *call_private, ...); struct marker_probe_closure single; struct marker_probe_closure *multi; - const char *tp_name; /* Optional tracepoint name */ - void *tp_cb; /* Optional tracepoint callback */ } __attribute__((aligned(8))); #ifdef CONFIG_MARKERS -#define _DEFINE_MARKER(name, tp_name_str, tp_cb, format) \ - static const char __mstrtab_##name[] \ - __attribute__((section("__markers_strings"))) \ - = #name "\0" format; \ - static struct marker __mark_##name \ - __attribute__((section("__markers"), aligned(8))) = \ - { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \ - 0, 0, marker_probe_cb, { __mark_empty_function, NULL},\ - NULL, tp_name_str, tp_cb } - -#define DEFINE_MARKER(name, format) \ - _DEFINE_MARKER(name, NULL, NULL, format) - -#define DEFINE_MARKER_TP(name, tp_name, tp_cb, format) \ - _DEFINE_MARKER(name, #tp_name, tp_cb, format) - /* * Note : the empty asm volatile with read constraint is used here instead of a * "used" attribute to fix a gcc 4.1.x bug. @@ -84,7 +65,14 @@ struct marker { */ #define __trace_mark(generic, name, call_private, format, args...) \ do { \ - DEFINE_MARKER(name, format); \ + static const char __mstrtab_##name[] \ + __attribute__((section("__markers_strings"))) \ + = #name "\0" format; \ + static struct marker __mark_##name \ + __attribute__((section("__markers"), aligned(8))) = \ + { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \ + 0, 0, marker_probe_cb, \ + { __mark_empty_function, NULL}, NULL }; \ __mark_check_format(format, ## args); \ if (unlikely(__mark_##name.state)) { \ (*__mark_##name.call) \ @@ -92,39 +80,14 @@ struct marker { } \ } while (0) -#define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \ - do { \ - void __check_tp_type(void) \ - { \ - register_trace_##tp_name(tp_cb); \ - } \ - DEFINE_MARKER_TP(name, tp_name, tp_cb, format); \ - __mark_check_format(format, ## args); \ - (*__mark_##name.call)(&__mark_##name, call_private, \ - ## args); \ - } while (0) - extern void marker_update_probe_range(struct marker *begin, struct marker *end); - -#define GET_MARKER(name) (__mark_##name) - #else /* !CONFIG_MARKERS */ -#define DEFINE_MARKER(name, tp_name, tp_cb, format) #define __trace_mark(generic, name, call_private, format, args...) \ __mark_check_format(format, ## args) -#define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \ - do { \ - void __check_tp_type(void) \ - { \ - register_trace_##tp_name(tp_cb); \ - } \ - __mark_check_format(format, ## args); \ - } while (0) static inline void marker_update_probe_range(struct marker *begin, struct marker *end) { } -#define GET_MARKER(name) #endif /* CONFIG_MARKERS */ /** @@ -153,20 +116,6 @@ static inline void marker_update_probe_range(struct marker *begin, #define _trace_mark(name, format, args...) \ __trace_mark(1, name, NULL, format, ## args) -/** - * trace_mark_tp - Marker in a tracepoint callback - * @name: marker name, not quoted. - * @tp_name: tracepoint name, not quoted. - * @tp_cb: tracepoint callback. Should have an associated global symbol so it - * is not optimized away by the compiler (should not be static). - * @format: format string - * @args...: variable argument list - * - * Places a marker in a tracepoint callback. - */ -#define trace_mark_tp(name, tp_name, tp_cb, format, args...) \ - __trace_mark_tp(name, NULL, tp_name, tp_cb, format, ## args) - /** * MARK_NOARGS - Format string for a marker with no argument. */ diff --git a/trunk/include/linux/rcupdate.h b/trunk/include/linux/rcupdate.h index 895dc9c1088c..86f1f5e43e33 100644 --- a/trunk/include/linux/rcupdate.h +++ b/trunk/include/linux/rcupdate.h @@ -142,7 +142,6 @@ struct rcu_head { * on the write-side to insure proper synchronization. */ #define rcu_read_lock_sched() preempt_disable() -#define rcu_read_lock_sched_notrace() preempt_disable_notrace() /* * rcu_read_unlock_sched - marks the end of a RCU-classic critical section @@ -150,7 +149,6 @@ struct rcu_head { * See rcu_read_lock_sched for more information. */ #define rcu_read_unlock_sched() preempt_enable() -#define rcu_read_unlock_sched_notrace() preempt_enable_notrace() diff --git a/trunk/include/linux/tracepoint.h b/trunk/include/linux/tracepoint.h index 757005458366..63064e9403f2 100644 --- a/trunk/include/linux/tracepoint.h +++ b/trunk/include/linux/tracepoint.h @@ -24,12 +24,8 @@ struct tracepoint { const char *name; /* Tracepoint name */ int state; /* State. */ void **funcs; -} __attribute__((aligned(32))); /* - * Aligned on 32 bytes because it is - * globally visible and gcc happily - * align these on the structure size. - * Keep in sync with vmlinux.lds.h. - */ +} __attribute__((aligned(8))); + #define TPPROTO(args...) args #define TPARGS(args...) args @@ -44,14 +40,14 @@ struct tracepoint { do { \ void **it_func; \ \ - rcu_read_lock_sched_notrace(); \ + rcu_read_lock_sched(); \ it_func = rcu_dereference((tp)->funcs); \ if (it_func) { \ do { \ ((void(*)(proto))(*it_func))(args); \ } while (*(++it_func)); \ } \ - rcu_read_unlock_sched_notrace(); \ + rcu_read_unlock_sched(); \ } while (0) /* @@ -59,40 +55,35 @@ struct tracepoint { * not add unwanted padding between the beginning of the section and the * structure. Force alignment to the same alignment as the section start. */ -#define DECLARE_TRACE(name, proto, args) \ - extern struct tracepoint __tracepoint_##name; \ +#define DEFINE_TRACE(name, proto, args) \ static inline void trace_##name(proto) \ { \ + static const char __tpstrtab_##name[] \ + __attribute__((section("__tracepoints_strings"))) \ + = #name ":" #proto; \ + static struct tracepoint __tracepoint_##name \ + __attribute__((section("__tracepoints"), aligned(8))) = \ + { __tpstrtab_##name, 0, NULL }; \ if (unlikely(__tracepoint_##name.state)) \ __DO_TRACE(&__tracepoint_##name, \ TPPROTO(proto), TPARGS(args)); \ } \ static inline int register_trace_##name(void (*probe)(proto)) \ { \ - return tracepoint_probe_register(#name, (void *)probe); \ + return tracepoint_probe_register(#name ":" #proto, \ + (void *)probe); \ } \ - static inline int unregister_trace_##name(void (*probe)(proto)) \ + static inline void unregister_trace_##name(void (*probe)(proto))\ { \ - return tracepoint_probe_unregister(#name, (void *)probe);\ + tracepoint_probe_unregister(#name ":" #proto, \ + (void *)probe); \ } -#define DEFINE_TRACE(name) \ - static const char __tpstrtab_##name[] \ - __attribute__((section("__tracepoints_strings"))) = #name; \ - struct tracepoint __tracepoint_##name \ - __attribute__((section("__tracepoints"), aligned(32))) = \ - { __tpstrtab_##name, 0, NULL } - -#define EXPORT_TRACEPOINT_SYMBOL_GPL(name) \ - EXPORT_SYMBOL_GPL(__tracepoint_##name) -#define EXPORT_TRACEPOINT_SYMBOL(name) \ - EXPORT_SYMBOL(__tracepoint_##name) - extern void tracepoint_update_probe_range(struct tracepoint *begin, struct tracepoint *end); #else /* !CONFIG_TRACEPOINTS */ -#define DECLARE_TRACE(name, proto, args) \ +#define DEFINE_TRACE(name, proto, args) \ static inline void _do_trace_##name(struct tracepoint *tp, proto) \ { } \ static inline void trace_##name(proto) \ @@ -101,14 +92,8 @@ extern void tracepoint_update_probe_range(struct tracepoint *begin, { \ return -ENOSYS; \ } \ - static inline int unregister_trace_##name(void (*probe)(proto)) \ - { \ - return -ENOSYS; \ - } - -#define DEFINE_TRACE(name) -#define EXPORT_TRACEPOINT_SYMBOL_GPL(name) -#define EXPORT_TRACEPOINT_SYMBOL(name) + static inline void unregister_trace_##name(void (*probe)(proto))\ + { } static inline void tracepoint_update_probe_range(struct tracepoint *begin, struct tracepoint *end) diff --git a/trunk/include/trace/sched.h b/trunk/include/trace/sched.h index 9b2854abf7e2..ad47369d01b5 100644 --- a/trunk/include/trace/sched.h +++ b/trunk/include/trace/sched.h @@ -4,52 +4,52 @@ #include #include -DECLARE_TRACE(sched_kthread_stop, +DEFINE_TRACE(sched_kthread_stop, TPPROTO(struct task_struct *t), TPARGS(t)); -DECLARE_TRACE(sched_kthread_stop_ret, +DEFINE_TRACE(sched_kthread_stop_ret, TPPROTO(int ret), TPARGS(ret)); -DECLARE_TRACE(sched_wait_task, +DEFINE_TRACE(sched_wait_task, TPPROTO(struct rq *rq, struct task_struct *p), TPARGS(rq, p)); -DECLARE_TRACE(sched_wakeup, +DEFINE_TRACE(sched_wakeup, TPPROTO(struct rq *rq, struct task_struct *p), TPARGS(rq, p)); -DECLARE_TRACE(sched_wakeup_new, +DEFINE_TRACE(sched_wakeup_new, TPPROTO(struct rq *rq, struct task_struct *p), TPARGS(rq, p)); -DECLARE_TRACE(sched_switch, +DEFINE_TRACE(sched_switch, TPPROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next), TPARGS(rq, prev, next)); -DECLARE_TRACE(sched_migrate_task, +DEFINE_TRACE(sched_migrate_task, TPPROTO(struct rq *rq, struct task_struct *p, int dest_cpu), TPARGS(rq, p, dest_cpu)); -DECLARE_TRACE(sched_process_free, +DEFINE_TRACE(sched_process_free, TPPROTO(struct task_struct *p), TPARGS(p)); -DECLARE_TRACE(sched_process_exit, +DEFINE_TRACE(sched_process_exit, TPPROTO(struct task_struct *p), TPARGS(p)); -DECLARE_TRACE(sched_process_wait, +DEFINE_TRACE(sched_process_wait, TPPROTO(struct pid *pid), TPARGS(pid)); -DECLARE_TRACE(sched_process_fork, +DEFINE_TRACE(sched_process_fork, TPPROTO(struct task_struct *parent, struct task_struct *child), TPARGS(parent, child)); -DECLARE_TRACE(sched_signal_send, +DEFINE_TRACE(sched_signal_send, TPPROTO(int sig, struct task_struct *p), TPARGS(sig, p)); diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index f5bacb438711..86b00c53fade 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -808,7 +808,6 @@ config TRACEPOINTS config MARKERS bool "Activate markers" - depends on TRACEPOINTS help Place an empty function call at each marker site. Can be dynamically changed for a probe function. diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index f995d2418668..ae2b92be5fae 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -54,10 +54,6 @@ #include #include -DEFINE_TRACE(sched_process_free); -DEFINE_TRACE(sched_process_exit); -DEFINE_TRACE(sched_process_wait); - static void exit_mm(struct task_struct * tsk); static inline int task_detached(struct task_struct *p) diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 0837d0deee5f..f6083561dfe0 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -79,8 +79,6 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0; __cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ -DEFINE_TRACE(sched_process_fork); - int nr_processes(void) { int cpu; diff --git a/trunk/kernel/kthread.c b/trunk/kernel/kthread.c index 4fbc456f393d..8e7a7ce3ed0a 100644 --- a/trunk/kernel/kthread.c +++ b/trunk/kernel/kthread.c @@ -21,9 +21,6 @@ static DEFINE_SPINLOCK(kthread_create_lock); static LIST_HEAD(kthread_create_list); struct task_struct *kthreadd_task; -DEFINE_TRACE(sched_kthread_stop); -DEFINE_TRACE(sched_kthread_stop_ret); - struct kthread_create_info { /* Information passed to kthread() from kthreadd. */ diff --git a/trunk/kernel/marker.c b/trunk/kernel/marker.c index ea54f2647868..2898b647d415 100644 --- a/trunk/kernel/marker.c +++ b/trunk/kernel/marker.c @@ -81,7 +81,7 @@ struct marker_entry { * though the function pointer change and the marker enabling are two distinct * operations that modifies the execution flow of preemptible code. */ -notrace void __mark_empty_function(void *probe_private, void *call_private, +void __mark_empty_function(void *probe_private, void *call_private, const char *fmt, va_list *args) { } @@ -97,8 +97,7 @@ EXPORT_SYMBOL_GPL(__mark_empty_function); * need to put a full smp_rmb() in this branch. This is why we do not use * rcu_dereference() for the pointer read. */ -notrace void marker_probe_cb(const struct marker *mdata, - void *call_private, ...) +void marker_probe_cb(const struct marker *mdata, void *call_private, ...) { va_list args; char ptype; @@ -108,7 +107,7 @@ notrace void marker_probe_cb(const struct marker *mdata, * sure the teardown of the callbacks can be done correctly when they * are in modules and they insure RCU read coherency. */ - rcu_read_lock_sched_notrace(); + rcu_read_lock_sched(); ptype = mdata->ptype; if (likely(!ptype)) { marker_probe_func *func; @@ -146,7 +145,7 @@ notrace void marker_probe_cb(const struct marker *mdata, va_end(args); } } - rcu_read_unlock_sched_notrace(); + rcu_read_unlock_sched(); } EXPORT_SYMBOL_GPL(marker_probe_cb); @@ -158,13 +157,12 @@ EXPORT_SYMBOL_GPL(marker_probe_cb); * * Should be connected to markers "MARK_NOARGS". */ -static notrace void marker_probe_cb_noarg(const struct marker *mdata, - void *call_private, ...) +static void marker_probe_cb_noarg(const struct marker *mdata, void *call_private, ...) { va_list args; /* not initialized */ char ptype; - rcu_read_lock_sched_notrace(); + rcu_read_lock_sched(); ptype = mdata->ptype; if (likely(!ptype)) { marker_probe_func *func; @@ -197,7 +195,7 @@ static notrace void marker_probe_cb_noarg(const struct marker *mdata, multi[i].func(multi[i].probe_private, call_private, mdata->format, &args); } - rcu_read_unlock_sched_notrace(); + rcu_read_unlock_sched(); } static void free_old_closure(struct rcu_head *head) @@ -479,7 +477,7 @@ static int marker_set_format(struct marker_entry *entry, const char *format) static int set_marker(struct marker_entry *entry, struct marker *elem, int active) { - int ret = 0; + int ret; WARN_ON(strcmp(entry->name, elem->name) != 0); if (entry->format) { @@ -531,40 +529,9 @@ static int set_marker(struct marker_entry *entry, struct marker *elem, */ smp_wmb(); elem->ptype = entry->ptype; - - if (elem->tp_name && (active ^ elem->state)) { - WARN_ON(!elem->tp_cb); - /* - * It is ok to directly call the probe registration because type - * checking has been done in the __trace_mark_tp() macro. - */ - - if (active) { - /* - * try_module_get should always succeed because we hold - * lock_module() to get the tp_cb address. - */ - ret = try_module_get(__module_text_address( - (unsigned long)elem->tp_cb)); - BUG_ON(!ret); - ret = tracepoint_probe_register_noupdate( - elem->tp_name, - elem->tp_cb); - } else { - ret = tracepoint_probe_unregister_noupdate( - elem->tp_name, - elem->tp_cb); - /* - * tracepoint_probe_update_all() must be called - * before the module containing tp_cb is unloaded. - */ - module_put(__module_text_address( - (unsigned long)elem->tp_cb)); - } - } elem->state = active; - return ret; + return 0; } /* @@ -575,24 +542,7 @@ static int set_marker(struct marker_entry *entry, struct marker *elem, */ static void disable_marker(struct marker *elem) { - int ret; - /* leave "call" as is. It is known statically. */ - if (elem->tp_name && elem->state) { - WARN_ON(!elem->tp_cb); - /* - * It is ok to directly call the probe registration because type - * checking has been done in the __trace_mark_tp() macro. - */ - ret = tracepoint_probe_unregister_noupdate(elem->tp_name, - elem->tp_cb); - WARN_ON(ret); - /* - * tracepoint_probe_update_all() must be called - * before the module containing tp_cb is unloaded. - */ - module_put(__module_text_address((unsigned long)elem->tp_cb)); - } elem->state = 0; elem->single.func = __mark_empty_function; /* Update the function before setting the ptype */ @@ -656,7 +606,6 @@ static void marker_update_probes(void) marker_update_probe_range(__start___markers, __stop___markers); /* Markers in modules. */ module_update_markers(); - tracepoint_probe_update_all(); } /** @@ -704,11 +653,10 @@ int marker_probe_register(const char *name, const char *format, goto end; } mutex_unlock(&markers_mutex); - marker_update_probes(); + marker_update_probes(); /* may update entry */ mutex_lock(&markers_mutex); entry = get_marker(name); - if (!entry) - goto end; + WARN_ON(!entry); if (entry->rcu_pending) rcu_barrier_sched(); entry->oldptr = old; @@ -749,7 +697,7 @@ int marker_probe_unregister(const char *name, rcu_barrier_sched(); old = marker_entry_remove_probe(entry, probe, probe_private); mutex_unlock(&markers_mutex); - marker_update_probes(); + marker_update_probes(); /* may update entry */ mutex_lock(&markers_mutex); entry = get_marker(name); if (!entry) @@ -830,11 +778,10 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, rcu_barrier_sched(); old = marker_entry_remove_probe(entry, NULL, probe_private); mutex_unlock(&markers_mutex); - marker_update_probes(); + marker_update_probes(); /* may update entry */ mutex_lock(&markers_mutex); entry = get_marker_from_private_data(probe, probe_private); - if (!entry) - goto end; + WARN_ON(!entry); if (entry->rcu_pending) rcu_barrier_sched(); entry->oldptr = old; @@ -895,36 +842,3 @@ void *marker_get_private_data(const char *name, marker_probe_func *probe, return ERR_PTR(-ENOENT); } EXPORT_SYMBOL_GPL(marker_get_private_data); - -#ifdef CONFIG_MODULES - -int marker_module_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - struct module *mod = data; - - switch (val) { - case MODULE_STATE_COMING: - marker_update_probe_range(mod->markers, - mod->markers + mod->num_markers); - break; - case MODULE_STATE_GOING: - marker_update_probe_range(mod->markers, - mod->markers + mod->num_markers); - break; - } - return 0; -} - -struct notifier_block marker_module_nb = { - .notifier_call = marker_module_notify, - .priority = 0, -}; - -static int init_markers(void) -{ - return register_module_notifier(&marker_module_nb); -} -__initcall(init_markers); - -#endif /* CONFIG_MODULES */ diff --git a/trunk/kernel/module.c b/trunk/kernel/module.c index 89bcf7c1327d..1f4cc00e0c20 100644 --- a/trunk/kernel/module.c +++ b/trunk/kernel/module.c @@ -2184,15 +2184,24 @@ static noinline struct module *load_module(void __user *umod, struct mod_debug *debug; unsigned int num_debug; +#ifdef CONFIG_MARKERS + marker_update_probe_range(mod->markers, + mod->markers + mod->num_markers); +#endif debug = section_objs(hdr, sechdrs, secstrings, "__verbose", sizeof(*debug), &num_debug); dynamic_printk_setup(debug, num_debug); + +#ifdef CONFIG_TRACEPOINTS + tracepoint_update_probe_range(mod->tracepoints, + mod->tracepoints + mod->num_tracepoints); +#endif } /* sechdrs[0].sh_size is always zero */ mseg = section_objs(hdr, sechdrs, secstrings, "__mcount_loc", sizeof(*mseg), &num_mcount); - ftrace_init_module(mod, mseg, mseg + num_mcount); + ftrace_init_module(mseg, mseg + num_mcount); err = module_finalize(hdr, sechdrs, mod); if (err < 0) diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 327f91c63c99..50a21f964679 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -118,12 +118,6 @@ */ #define RUNTIME_INF ((u64)~0ULL) -DEFINE_TRACE(sched_wait_task); -DEFINE_TRACE(sched_wakeup); -DEFINE_TRACE(sched_wakeup_new); -DEFINE_TRACE(sched_switch); -DEFINE_TRACE(sched_migrate_task); - #ifdef CONFIG_SMP /* * Divide a load by a sched group cpu_power : (load / sg->__cpu_power) diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index e9afe63da24b..4530fc654455 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -41,8 +41,6 @@ static struct kmem_cache *sigqueue_cachep; -DEFINE_TRACE(sched_signal_send); - static void __user *sig_handler(struct task_struct *t, int sig) { return t->sighand->action[sig - 1].sa.sa_handler; diff --git a/trunk/kernel/trace/Kconfig b/trunk/kernel/trace/Kconfig index b8378fad29a3..9c89526b6b7c 100644 --- a/trunk/kernel/trace/Kconfig +++ b/trunk/kernel/trace/Kconfig @@ -59,6 +59,7 @@ config FUNCTION_TRACER config FUNCTION_RET_TRACER bool "Kernel Function return Tracer" + depends on !DYNAMIC_FTRACE depends on HAVE_FUNCTION_RET_TRACER depends on FUNCTION_TRACER help diff --git a/trunk/kernel/trace/ftrace.c b/trunk/kernel/trace/ftrace.c index f212da486689..54cb9a7d15e5 100644 --- a/trunk/kernel/trace/ftrace.c +++ b/trunk/kernel/trace/ftrace.c @@ -50,9 +50,6 @@ static int last_ftrace_enabled; /* Quick disabling of function tracer. */ int function_trace_stop; -/* By default, current tracing type is normal tracing. */ -enum ftrace_tracing_type_t ftrace_tracing_type = FTRACE_TYPE_ENTER; - /* * ftrace_disabled is set when an anomaly is discovered. * ftrace_disabled is much stronger than ftrace_enabled. @@ -337,7 +334,7 @@ ftrace_record_ip(unsigned long ip) { struct dyn_ftrace *rec; - if (ftrace_disabled) + if (!ftrace_enabled || ftrace_disabled) return NULL; rec = ftrace_alloc_dyn_node(ip); @@ -351,138 +348,107 @@ ftrace_record_ip(unsigned long ip) return rec; } -static void print_ip_ins(const char *fmt, unsigned char *p) -{ - int i; - - printk(KERN_CONT "%s", fmt); - - for (i = 0; i < MCOUNT_INSN_SIZE; i++) - printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]); -} - -static void ftrace_bug(int failed, unsigned long ip) -{ - switch (failed) { - case -EFAULT: - FTRACE_WARN_ON_ONCE(1); - pr_info("ftrace faulted on modifying "); - print_ip_sym(ip); - break; - case -EINVAL: - FTRACE_WARN_ON_ONCE(1); - pr_info("ftrace failed to modify "); - print_ip_sym(ip); - print_ip_ins(" actual: ", (unsigned char *)ip); - printk(KERN_CONT "\n"); - break; - case -EPERM: - FTRACE_WARN_ON_ONCE(1); - pr_info("ftrace faulted on writing "); - print_ip_sym(ip); - break; - default: - FTRACE_WARN_ON_ONCE(1); - pr_info("ftrace faulted on unknown error "); - print_ip_sym(ip); - } -} - +#define FTRACE_ADDR ((long)(ftrace_caller)) static int -__ftrace_replace_code(struct dyn_ftrace *rec, int enable) +__ftrace_replace_code(struct dyn_ftrace *rec, + unsigned char *old, unsigned char *new, int enable) { unsigned long ip, fl; - unsigned long ftrace_addr; - -#ifdef CONFIG_FUNCTION_RET_TRACER - if (ftrace_tracing_type == FTRACE_TYPE_ENTER) - ftrace_addr = (unsigned long)ftrace_caller; - else - ftrace_addr = (unsigned long)ftrace_return_caller; -#else - ftrace_addr = (unsigned long)ftrace_caller; -#endif ip = rec->ip; - /* - * If this record is not to be traced and - * it is not enabled then do nothing. - * - * If this record is not to be traced and - * it is enabled then disabled it. - * - */ - if (rec->flags & FTRACE_FL_NOTRACE) { - if (rec->flags & FTRACE_FL_ENABLED) - rec->flags &= ~FTRACE_FL_ENABLED; - else - return 0; - - } else if (ftrace_filtered && enable) { + if (ftrace_filtered && enable) { /* - * Filtering is on: + * If filtering is on: + * + * If this record is set to be filtered and + * is enabled then do nothing. + * + * If this record is set to be filtered and + * it is not enabled, enable it. + * + * If this record is not set to be filtered + * and it is not enabled do nothing. + * + * If this record is set not to trace then + * do nothing. + * + * If this record is set not to trace and + * it is enabled then disable it. + * + * If this record is not set to be filtered and + * it is enabled, disable it. */ - fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED); + fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE | + FTRACE_FL_ENABLED); - /* Record is filtered and enabled, do nothing */ - if (fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) + if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) || + (fl == (FTRACE_FL_FILTER | FTRACE_FL_NOTRACE)) || + !fl || (fl == FTRACE_FL_NOTRACE)) return 0; - /* Record is not filtered and is not enabled do nothing */ - if (!fl) - return 0; - - /* Record is not filtered but enabled, disable it */ - if (fl == FTRACE_FL_ENABLED) + /* + * If it is enabled disable it, + * otherwise enable it! + */ + if (fl & FTRACE_FL_ENABLED) { + /* swap new and old */ + new = old; + old = ftrace_call_replace(ip, FTRACE_ADDR); rec->flags &= ~FTRACE_FL_ENABLED; - else - /* Otherwise record is filtered but not enabled, enable it */ + } else { + new = ftrace_call_replace(ip, FTRACE_ADDR); rec->flags |= FTRACE_FL_ENABLED; + } } else { - /* Disable or not filtered */ if (enable) { - /* if record is enabled, do nothing */ - if (rec->flags & FTRACE_FL_ENABLED) + /* + * If this record is set not to trace and is + * not enabled, do nothing. + */ + fl = rec->flags & (FTRACE_FL_NOTRACE | FTRACE_FL_ENABLED); + if (fl == FTRACE_FL_NOTRACE) return 0; - rec->flags |= FTRACE_FL_ENABLED; + new = ftrace_call_replace(ip, FTRACE_ADDR); + } else + old = ftrace_call_replace(ip, FTRACE_ADDR); + if (enable) { + if (rec->flags & FTRACE_FL_ENABLED) + return 0; + rec->flags |= FTRACE_FL_ENABLED; } else { - - /* if record is not enabled do nothing */ if (!(rec->flags & FTRACE_FL_ENABLED)) return 0; - rec->flags &= ~FTRACE_FL_ENABLED; } } - if (rec->flags & FTRACE_FL_ENABLED) - return ftrace_make_call(rec, ftrace_addr); - else - return ftrace_make_nop(NULL, rec, ftrace_addr); + return ftrace_modify_code(ip, old, new); } static void ftrace_replace_code(int enable) { int i, failed; + unsigned char *new = NULL, *old = NULL; struct dyn_ftrace *rec; struct ftrace_page *pg; + if (enable) + old = ftrace_nop_replace(); + else + new = ftrace_nop_replace(); + for (pg = ftrace_pages_start; pg; pg = pg->next) { for (i = 0; i < pg->index; i++) { rec = &pg->records[i]; - /* - * Skip over free records and records that have - * failed. - */ - if (rec->flags & FTRACE_FL_FREE || - rec->flags & FTRACE_FL_FAILED) + /* don't modify code that has already faulted */ + if (rec->flags & FTRACE_FL_FAILED) continue; /* ignore updates to this record's mcount site */ @@ -493,30 +459,68 @@ static void ftrace_replace_code(int enable) unfreeze_record(rec); } - failed = __ftrace_replace_code(rec, enable); + failed = __ftrace_replace_code(rec, old, new, enable); if (failed && (rec->flags & FTRACE_FL_CONVERTED)) { rec->flags |= FTRACE_FL_FAILED; if ((system_state == SYSTEM_BOOTING) || !core_kernel_text(rec->ip)) { ftrace_free_rec(rec); - } else - ftrace_bug(failed, rec->ip); + } } } } } +static void print_ip_ins(const char *fmt, unsigned char *p) +{ + int i; + + printk(KERN_CONT "%s", fmt); + + for (i = 0; i < MCOUNT_INSN_SIZE; i++) + printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]); +} + static int -ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec) +ftrace_code_disable(struct dyn_ftrace *rec) { unsigned long ip; + unsigned char *nop, *call; int ret; ip = rec->ip; - ret = ftrace_make_nop(mod, rec, mcount_addr); + nop = ftrace_nop_replace(); + call = ftrace_call_replace(ip, mcount_addr); + + ret = ftrace_modify_code(ip, call, nop); if (ret) { - ftrace_bug(ret, ip); + switch (ret) { + case -EFAULT: + FTRACE_WARN_ON_ONCE(1); + pr_info("ftrace faulted on modifying "); + print_ip_sym(ip); + break; + case -EINVAL: + FTRACE_WARN_ON_ONCE(1); + pr_info("ftrace failed to modify "); + print_ip_sym(ip); + print_ip_ins(" expected: ", call); + print_ip_ins(" actual: ", (unsigned char *)ip); + print_ip_ins(" replace: ", nop); + printk(KERN_CONT "\n"); + break; + case -EPERM: + FTRACE_WARN_ON_ONCE(1); + pr_info("ftrace faulted on writing "); + print_ip_sym(ip); + break; + default: + FTRACE_WARN_ON_ONCE(1); + pr_info("ftrace faulted on unknown error "); + print_ip_sym(ip); + } + rec->flags |= FTRACE_FL_FAILED; return 0; } @@ -556,7 +560,8 @@ static void ftrace_startup(void) mutex_lock(&ftrace_start_lock); ftrace_start_up++; - command |= FTRACE_ENABLE_CALLS; + if (ftrace_start_up == 1) + command |= FTRACE_ENABLE_CALLS; if (saved_ftrace_func != ftrace_trace_function) { saved_ftrace_func = ftrace_trace_function; @@ -634,7 +639,7 @@ static cycle_t ftrace_update_time; static unsigned long ftrace_update_cnt; unsigned long ftrace_update_tot_cnt; -static int ftrace_update_code(struct module *mod) +static int ftrace_update_code(void) { struct dyn_ftrace *p, *t; cycle_t start, stop; @@ -651,7 +656,7 @@ static int ftrace_update_code(struct module *mod) list_del_init(&p->list); /* convert record (i.e, patch mcount-call with NOP) */ - if (ftrace_code_disable(mod, p)) { + if (ftrace_code_disable(p)) { p->flags |= FTRACE_FL_CONVERTED; ftrace_update_cnt++; } else @@ -694,7 +699,7 @@ static int __init ftrace_dyn_table_alloc(unsigned long num_to_init) cnt = num_to_init / ENTRIES_PER_PAGE; pr_info("ftrace: allocating %ld entries in %d pages\n", - num_to_init, cnt + 1); + num_to_init, cnt); for (i = 0; i < cnt; i++) { pg->next = (void *)get_zeroed_page(GFP_KERNEL); @@ -777,11 +782,13 @@ static void *t_start(struct seq_file *m, loff_t *pos) void *p = NULL; loff_t l = -1; - if (*pos > iter->pos) - *pos = iter->pos; - - l = *pos; - p = t_next(m, p, &l); + if (*pos != iter->pos) { + for (p = t_next(m, p, &l); p && l < *pos; p = t_next(m, p, &l)) + ; + } else { + l = *pos; + p = t_next(m, p, &l); + } return p; } @@ -792,21 +799,15 @@ static void t_stop(struct seq_file *m, void *p) static int t_show(struct seq_file *m, void *v) { - struct ftrace_iterator *iter = m->private; struct dyn_ftrace *rec = v; char str[KSYM_SYMBOL_LEN]; - int ret = 0; if (!rec) return 0; kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); - ret = seq_printf(m, "%s\n", str); - if (ret < 0) { - iter->pos--; - iter->idx--; - } + seq_printf(m, "%s\n", str); return 0; } @@ -832,7 +833,7 @@ ftrace_avail_open(struct inode *inode, struct file *file) return -ENOMEM; iter->pg = ftrace_pages_start; - iter->pos = 0; + iter->pos = -1; ret = seq_open(file, &show_ftrace_seq_ops); if (!ret) { @@ -919,7 +920,7 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable) if (file->f_mode & FMODE_READ) { iter->pg = ftrace_pages_start; - iter->pos = 0; + iter->pos = -1; iter->flags = enable ? FTRACE_ITER_FILTER : FTRACE_ITER_NOTRACE; @@ -1210,7 +1211,7 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable) mutex_lock(&ftrace_sysctl_lock); mutex_lock(&ftrace_start_lock); - if (ftrace_start_up && ftrace_enabled) + if (iter->filtered && ftrace_start_up && ftrace_enabled) ftrace_run_update_code(FTRACE_ENABLE_CALLS); mutex_unlock(&ftrace_start_lock); mutex_unlock(&ftrace_sysctl_lock); @@ -1297,8 +1298,7 @@ static __init int ftrace_init_debugfs(void) fs_initcall(ftrace_init_debugfs); -static int ftrace_convert_nops(struct module *mod, - unsigned long *start, +static int ftrace_convert_nops(unsigned long *start, unsigned long *end) { unsigned long *p; @@ -1309,32 +1309,23 @@ static int ftrace_convert_nops(struct module *mod, p = start; while (p < end) { addr = ftrace_call_adjust(*p++); - /* - * Some architecture linkers will pad between - * the different mcount_loc sections of different - * object files to satisfy alignments. - * Skip any NULL pointers. - */ - if (!addr) - continue; ftrace_record_ip(addr); } /* disable interrupts to prevent kstop machine */ local_irq_save(flags); - ftrace_update_code(mod); + ftrace_update_code(); local_irq_restore(flags); mutex_unlock(&ftrace_start_lock); return 0; } -void ftrace_init_module(struct module *mod, - unsigned long *start, unsigned long *end) +void ftrace_init_module(unsigned long *start, unsigned long *end) { if (ftrace_disabled || start == end) return; - ftrace_convert_nops(mod, start, end); + ftrace_convert_nops(start, end); } extern unsigned long __start_mcount_loc[]; @@ -1364,8 +1355,7 @@ void __init ftrace_init(void) last_ftrace_enabled = ftrace_enabled = 1; - ret = ftrace_convert_nops(NULL, - __start_mcount_loc, + ret = ftrace_convert_nops(__start_mcount_loc, __stop_mcount_loc); return; @@ -1421,17 +1411,10 @@ int register_ftrace_function(struct ftrace_ops *ops) return -1; mutex_lock(&ftrace_sysctl_lock); - - if (ftrace_tracing_type == FTRACE_TYPE_RETURN) { - ret = -EBUSY; - goto out; - } - ret = __register_ftrace_function(ops); ftrace_startup(); - -out: mutex_unlock(&ftrace_sysctl_lock); + return ret; } @@ -1497,45 +1480,16 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, } #ifdef CONFIG_FUNCTION_RET_TRACER - -/* The callback that hooks the return of a function */ trace_function_return_t ftrace_function_return = (trace_function_return_t)ftrace_stub; - -int register_ftrace_return(trace_function_return_t func) +void register_ftrace_return(trace_function_return_t func) { - int ret = 0; - - mutex_lock(&ftrace_sysctl_lock); - - /* - * Don't launch return tracing if normal function - * tracing is already running. - */ - if (ftrace_trace_function != ftrace_stub) { - ret = -EBUSY; - goto out; - } - - ftrace_tracing_type = FTRACE_TYPE_RETURN; ftrace_function_return = func; - ftrace_startup(); - -out: - mutex_unlock(&ftrace_sysctl_lock); - return ret; } void unregister_ftrace_return(void) { - mutex_lock(&ftrace_sysctl_lock); - ftrace_function_return = (trace_function_return_t)ftrace_stub; - ftrace_shutdown(); - /* Restore normal tracing type */ - ftrace_tracing_type = FTRACE_TYPE_ENTER; - - mutex_unlock(&ftrace_sysctl_lock); } #endif diff --git a/trunk/kernel/trace/trace.c b/trunk/kernel/trace/trace.c index 396fda034e3f..b04923b72ce0 100644 --- a/trunk/kernel/trace/trace.c +++ b/trunk/kernel/trace/trace.c @@ -259,9 +259,7 @@ static const char *trace_options[] = { "sched-tree", "ftrace_printk", "ftrace_preempt", -#ifdef CONFIG_BRANCH_TRACER "branch", -#endif "annotate", NULL }; @@ -1051,7 +1049,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip) * Need to use raw, since this must be called before the * recursive protection is performed. */ - local_irq_save(flags); + raw_local_irq_save(flags); cpu = raw_smp_processor_id(); data = tr->data[cpu]; disabled = atomic_inc_return(&data->disabled); @@ -1062,7 +1060,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip) } atomic_dec(&data->disabled); - local_irq_restore(flags); + raw_local_irq_restore(flags); } #ifdef CONFIG_FUNCTION_RET_TRACER @@ -2638,11 +2636,8 @@ static int tracing_set_tracer(char *buf) current_trace->reset(tr); current_trace = t; - if (t->init) { - ret = t->init(tr); - if (ret) - goto out; - } + if (t->init) + t->init(tr); trace_branch_enable(tr); out: @@ -2658,9 +2653,6 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf, char buf[max_tracer_type_len+1]; int i; size_t ret; - int err; - - ret = cnt; if (cnt > max_tracer_type_len) cnt = max_tracer_type_len; @@ -2674,11 +2666,12 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf, for (i = cnt - 1; i > 0 && isspace(buf[i]); i--) buf[i] = 0; - err = tracing_set_tracer(buf); - if (err) - return err; + ret = tracing_set_tracer(buf); + if (!ret) + ret = cnt; - filp->f_pos += ret; + if (ret > 0) + filp->f_pos += ret; return ret; } diff --git a/trunk/kernel/trace/trace.h b/trunk/kernel/trace/trace.h index cdbd5cc22be8..b41d7b4c2cae 100644 --- a/trunk/kernel/trace/trace.h +++ b/trunk/kernel/trace/trace.h @@ -264,8 +264,7 @@ enum print_line_t { */ struct tracer { const char *name; - /* Your tracer should raise a warning if init fails */ - int (*init)(struct trace_array *tr); + void (*init)(struct trace_array *tr); void (*reset)(struct trace_array *tr); void (*start)(struct trace_array *tr); void (*stop)(struct trace_array *tr); @@ -471,9 +470,7 @@ enum trace_iterator_flags { TRACE_ITER_SCHED_TREE = 0x200, TRACE_ITER_PRINTK = 0x400, TRACE_ITER_PREEMPTONLY = 0x800, -#ifdef CONFIG_BRANCH_TRACER TRACE_ITER_BRANCH = 0x1000, -#endif TRACE_ITER_ANNOTATE = 0x2000, }; diff --git a/trunk/kernel/trace/trace_boot.c b/trunk/kernel/trace/trace_boot.c index a4fa2c57e34e..cb333b7fd113 100644 --- a/trunk/kernel/trace/trace_boot.c +++ b/trunk/kernel/trace/trace_boot.c @@ -47,7 +47,7 @@ static void reset_boot_trace(struct trace_array *tr) tracing_reset(tr, cpu); } -static int boot_trace_init(struct trace_array *tr) +static void boot_trace_init(struct trace_array *tr) { int cpu; boot_trace = tr; @@ -56,7 +56,6 @@ static int boot_trace_init(struct trace_array *tr) tracing_reset(tr, cpu); tracing_sched_switch_assign_trace(tr); - return 0; } static enum print_line_t diff --git a/trunk/kernel/trace/trace_branch.c b/trunk/kernel/trace/trace_branch.c index 23f9b02ce967..2511e32572ca 100644 --- a/trunk/kernel/trace/trace_branch.c +++ b/trunk/kernel/trace/trace_branch.c @@ -125,7 +125,7 @@ static void stop_branch_trace(struct trace_array *tr) disable_branch_tracing(); } -static int branch_trace_init(struct trace_array *tr) +static void branch_trace_init(struct trace_array *tr) { int cpu; @@ -133,7 +133,6 @@ static int branch_trace_init(struct trace_array *tr) tracing_reset(tr, cpu); start_branch_trace(tr); - return 0; } static void branch_trace_reset(struct trace_array *tr) diff --git a/trunk/kernel/trace/trace_functions.c b/trunk/kernel/trace/trace_functions.c index e74f6d0a3216..8693b7a0a5b2 100644 --- a/trunk/kernel/trace/trace_functions.c +++ b/trunk/kernel/trace/trace_functions.c @@ -42,10 +42,9 @@ static void stop_function_trace(struct trace_array *tr) tracing_stop_cmdline_record(); } -static int function_trace_init(struct trace_array *tr) +static void function_trace_init(struct trace_array *tr) { start_function_trace(tr); - return 0; } static void function_trace_reset(struct trace_array *tr) diff --git a/trunk/kernel/trace/trace_functions_return.c b/trunk/kernel/trace/trace_functions_return.c index a68564af022b..7680b21537dd 100644 --- a/trunk/kernel/trace/trace_functions_return.c +++ b/trunk/kernel/trace/trace_functions_return.c @@ -14,18 +14,28 @@ #include "trace.h" -static int return_trace_init(struct trace_array *tr) +static void start_return_trace(struct trace_array *tr) +{ + register_ftrace_return(&trace_function_return); +} + +static void stop_return_trace(struct trace_array *tr) +{ + unregister_ftrace_return(); +} + +static void return_trace_init(struct trace_array *tr) { int cpu; for_each_online_cpu(cpu) tracing_reset(tr, cpu); - return register_ftrace_return(&trace_function_return); + start_return_trace(tr); } static void return_trace_reset(struct trace_array *tr) { - unregister_ftrace_return(); + stop_return_trace(tr); } diff --git a/trunk/kernel/trace/trace_irqsoff.c b/trunk/kernel/trace/trace_irqsoff.c index 7c2e326bbc8b..d919d4eaa7cc 100644 --- a/trunk/kernel/trace/trace_irqsoff.c +++ b/trunk/kernel/trace/trace_irqsoff.c @@ -416,12 +416,11 @@ static void irqsoff_tracer_close(struct trace_iterator *iter) } #ifdef CONFIG_IRQSOFF_TRACER -static int irqsoff_tracer_init(struct trace_array *tr) +static void irqsoff_tracer_init(struct trace_array *tr) { trace_type = TRACER_IRQS_OFF; __irqsoff_tracer_init(tr); - return 0; } static struct tracer irqsoff_tracer __read_mostly = { @@ -443,12 +442,11 @@ static struct tracer irqsoff_tracer __read_mostly = #endif #ifdef CONFIG_PREEMPT_TRACER -static int preemptoff_tracer_init(struct trace_array *tr) +static void preemptoff_tracer_init(struct trace_array *tr) { trace_type = TRACER_PREEMPT_OFF; __irqsoff_tracer_init(tr); - return 0; } static struct tracer preemptoff_tracer __read_mostly = @@ -473,12 +471,11 @@ static struct tracer preemptoff_tracer __read_mostly = #if defined(CONFIG_IRQSOFF_TRACER) && \ defined(CONFIG_PREEMPT_TRACER) -static int preemptirqsoff_tracer_init(struct trace_array *tr) +static void preemptirqsoff_tracer_init(struct trace_array *tr) { trace_type = TRACER_IRQS_OFF | TRACER_PREEMPT_OFF; __irqsoff_tracer_init(tr); - return 0; } static struct tracer preemptirqsoff_tracer __read_mostly = diff --git a/trunk/kernel/trace/trace_mmiotrace.c b/trunk/kernel/trace/trace_mmiotrace.c index 433d650eda9f..51bcf370215e 100644 --- a/trunk/kernel/trace/trace_mmiotrace.c +++ b/trunk/kernel/trace/trace_mmiotrace.c @@ -30,14 +30,13 @@ static void mmio_reset_data(struct trace_array *tr) tracing_reset(tr, cpu); } -static int mmio_trace_init(struct trace_array *tr) +static void mmio_trace_init(struct trace_array *tr) { pr_debug("in %s\n", __func__); mmio_trace_array = tr; mmio_reset_data(tr); enable_mmiotrace(); - return 0; } static void mmio_trace_reset(struct trace_array *tr) diff --git a/trunk/kernel/trace/trace_nop.c b/trunk/kernel/trace/trace_nop.c index 0e77415caed3..2ef1d227e7d8 100644 --- a/trunk/kernel/trace/trace_nop.c +++ b/trunk/kernel/trace/trace_nop.c @@ -24,7 +24,7 @@ static void stop_nop_trace(struct trace_array *tr) /* Nothing to do! */ } -static int nop_trace_init(struct trace_array *tr) +static void nop_trace_init(struct trace_array *tr) { int cpu; ctx_trace = tr; @@ -33,7 +33,6 @@ static int nop_trace_init(struct trace_array *tr) tracing_reset(tr, cpu); start_nop_trace(tr); - return 0; } static void nop_trace_reset(struct trace_array *tr) diff --git a/trunk/kernel/trace/trace_sched_switch.c b/trunk/kernel/trace/trace_sched_switch.c index 863390557b44..be35bdfe2e38 100644 --- a/trunk/kernel/trace/trace_sched_switch.c +++ b/trunk/kernel/trace/trace_sched_switch.c @@ -206,11 +206,10 @@ static void stop_sched_trace(struct trace_array *tr) tracing_stop_sched_switch_record(); } -static int sched_switch_trace_init(struct trace_array *tr) +static void sched_switch_trace_init(struct trace_array *tr) { ctx_trace = tr; start_sched_trace(tr); - return 0; } static void sched_switch_trace_reset(struct trace_array *tr) diff --git a/trunk/kernel/trace/trace_sched_wakeup.c b/trunk/kernel/trace/trace_sched_wakeup.c index 0067b49746c1..983f2b1478c9 100644 --- a/trunk/kernel/trace/trace_sched_wakeup.c +++ b/trunk/kernel/trace/trace_sched_wakeup.c @@ -331,11 +331,10 @@ static void stop_wakeup_tracer(struct trace_array *tr) unregister_trace_sched_wakeup(probe_wakeup); } -static int wakeup_tracer_init(struct trace_array *tr) +static void wakeup_tracer_init(struct trace_array *tr) { wakeup_trace = tr; start_wakeup_tracer(tr); - return 0; } static void wakeup_tracer_reset(struct trace_array *tr) diff --git a/trunk/kernel/trace/trace_selftest.c b/trunk/kernel/trace/trace_selftest.c index 88c8eb70f54a..24e6e075e6d6 100644 --- a/trunk/kernel/trace/trace_selftest.c +++ b/trunk/kernel/trace/trace_selftest.c @@ -52,7 +52,7 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count) int cpu, ret = 0; /* Don't allow flipping of max traces now */ - local_irq_save(flags); + raw_local_irq_save(flags); __raw_spin_lock(&ftrace_max_lock); cnt = ring_buffer_entries(tr->buffer); @@ -63,7 +63,7 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count) break; } __raw_spin_unlock(&ftrace_max_lock); - local_irq_restore(flags); + raw_local_irq_restore(flags); if (count) *count = cnt; @@ -71,11 +71,6 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count) return ret; } -static inline void warn_failed_init_tracer(struct tracer *trace, int init_ret) -{ - printk(KERN_WARNING "Failed to init %s tracer, init returned %d\n", - trace->name, init_ret); -} #ifdef CONFIG_FUNCTION_TRACER #ifdef CONFIG_DYNAMIC_FTRACE @@ -116,11 +111,7 @@ int trace_selftest_startup_dynamic_tracing(struct tracer *trace, ftrace_set_filter(func_name, strlen(func_name), 1); /* enable tracing */ - ret = trace->init(tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - goto out; - } + trace->init(tr); /* Sleep for a 1/10 of a second */ msleep(100); @@ -190,12 +181,7 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr) ftrace_enabled = 1; tracer_enabled = 1; - ret = trace->init(tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - goto out; - } - + trace->init(tr); /* Sleep for a 1/10 of a second */ msleep(100); /* stop the tracing. */ @@ -237,12 +223,7 @@ trace_selftest_startup_irqsoff(struct tracer *trace, struct trace_array *tr) int ret; /* start the tracing */ - ret = trace->init(tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - return ret; - } - + trace->init(tr); /* reset the max latency */ tracing_max_latency = 0; /* disable interrupts for a bit */ @@ -291,12 +272,7 @@ trace_selftest_startup_preemptoff(struct tracer *trace, struct trace_array *tr) } /* start the tracing */ - ret = trace->init(tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - return ret; - } - + trace->init(tr); /* reset the max latency */ tracing_max_latency = 0; /* disable preemption for a bit */ @@ -345,11 +321,7 @@ trace_selftest_startup_preemptirqsoff(struct tracer *trace, struct trace_array * } /* start the tracing */ - ret = trace->init(tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - goto out; - } + trace->init(tr); /* reset the max latency */ tracing_max_latency = 0; @@ -477,12 +449,7 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr) wait_for_completion(&isrt); /* start the tracing */ - ret = trace->init(tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - return ret; - } - + trace->init(tr); /* reset the max latency */ tracing_max_latency = 0; @@ -538,12 +505,7 @@ trace_selftest_startup_sched_switch(struct tracer *trace, struct trace_array *tr int ret; /* start the tracing */ - ret = trace->init(tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - return ret; - } - + trace->init(tr); /* Sleep for a 1/10 of a second */ msleep(100); /* stop the tracing. */ @@ -570,12 +532,7 @@ trace_selftest_startup_sysprof(struct tracer *trace, struct trace_array *tr) int ret; /* start the tracing */ - ret = trace->init(tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - return 0; - } - + trace->init(tr); /* Sleep for a 1/10 of a second */ msleep(100); /* stop the tracing. */ @@ -597,12 +554,7 @@ trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr) int ret; /* start the tracing */ - ret = trace->init(tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - return ret; - } - + trace->init(tr); /* Sleep for a 1/10 of a second */ msleep(100); /* stop the tracing. */ diff --git a/trunk/kernel/trace/trace_sysprof.c b/trunk/kernel/trace/trace_sysprof.c index 54960edb96d0..05f753422aea 100644 --- a/trunk/kernel/trace/trace_sysprof.c +++ b/trunk/kernel/trace/trace_sysprof.c @@ -261,12 +261,11 @@ static void stop_stack_trace(struct trace_array *tr) mutex_unlock(&sample_timer_lock); } -static int stack_trace_init(struct trace_array *tr) +static void stack_trace_init(struct trace_array *tr) { sysprof_trace = tr; start_stack_trace(tr); - return 0; } static void stack_trace_reset(struct trace_array *tr) diff --git a/trunk/kernel/tracepoint.c b/trunk/kernel/tracepoint.c index 79602740bbb5..e96590f17de1 100644 --- a/trunk/kernel/tracepoint.c +++ b/trunk/kernel/tracepoint.c @@ -262,7 +262,6 @@ static void set_tracepoint(struct tracepoint_entry **entry, static void disable_tracepoint(struct tracepoint *elem) { elem->state = 0; - rcu_assign_pointer(elem->funcs, NULL); } /** @@ -541,36 +540,3 @@ void tracepoint_iter_reset(struct tracepoint_iter *iter) iter->tracepoint = NULL; } EXPORT_SYMBOL_GPL(tracepoint_iter_reset); - -#ifdef CONFIG_MODULES - -int tracepoint_module_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - struct module *mod = data; - - switch (val) { - case MODULE_STATE_COMING: - tracepoint_update_probe_range(mod->tracepoints, - mod->tracepoints + mod->num_tracepoints); - break; - case MODULE_STATE_GOING: - tracepoint_update_probe_range(mod->tracepoints, - mod->tracepoints + mod->num_tracepoints); - break; - } - return 0; -} - -struct notifier_block tracepoint_module_nb = { - .notifier_call = tracepoint_module_notify, - .priority = 0, -}; - -static int init_tracepoints(void) -{ - return register_module_notifier(&tracepoint_module_nb); -} -__initcall(init_tracepoints); - -#endif /* CONFIG_MODULES */ diff --git a/trunk/samples/tracepoints/tp-samples-trace.h b/trunk/samples/tracepoints/tp-samples-trace.h index 01724e04c556..0216b55bd640 100644 --- a/trunk/samples/tracepoints/tp-samples-trace.h +++ b/trunk/samples/tracepoints/tp-samples-trace.h @@ -4,10 +4,10 @@ #include /* for struct inode and struct file */ #include -DECLARE_TRACE(subsys_event, +DEFINE_TRACE(subsys_event, TPPROTO(struct inode *inode, struct file *file), TPARGS(inode, file)); -DECLARE_TRACE(subsys_eventb, +DEFINE_TRACE(subsys_eventb, TPPROTO(void), TPARGS()); #endif diff --git a/trunk/samples/tracepoints/tracepoint-probe-sample.c b/trunk/samples/tracepoints/tracepoint-probe-sample.c index e3a964889dc7..55abfdda4bd4 100644 --- a/trunk/samples/tracepoints/tracepoint-probe-sample.c +++ b/trunk/samples/tracepoints/tracepoint-probe-sample.c @@ -46,7 +46,6 @@ void __exit tp_sample_trace_exit(void) { unregister_trace_subsys_eventb(probe_subsys_eventb); unregister_trace_subsys_event(probe_subsys_event); - tracepoint_synchronize_unregister(); } module_exit(tp_sample_trace_exit); diff --git a/trunk/samples/tracepoints/tracepoint-probe-sample2.c b/trunk/samples/tracepoints/tracepoint-probe-sample2.c index 685a5acb4562..5e9fcf4afffe 100644 --- a/trunk/samples/tracepoints/tracepoint-probe-sample2.c +++ b/trunk/samples/tracepoints/tracepoint-probe-sample2.c @@ -33,7 +33,6 @@ module_init(tp_sample_trace_init); void __exit tp_sample_trace_exit(void) { unregister_trace_subsys_event(probe_subsys_event); - tracepoint_synchronize_unregister(); } module_exit(tp_sample_trace_exit); diff --git a/trunk/samples/tracepoints/tracepoint-sample.c b/trunk/samples/tracepoints/tracepoint-sample.c index 00d169792a3e..4ae4b7fcc043 100644 --- a/trunk/samples/tracepoints/tracepoint-sample.c +++ b/trunk/samples/tracepoints/tracepoint-sample.c @@ -13,9 +13,6 @@ #include #include "tp-samples-trace.h" -DEFINE_TRACE(subsys_event); -DEFINE_TRACE(subsys_eventb); - struct proc_dir_entry *pentry_example; static int my_open(struct inode *inode, struct file *file)