tracing: Updates for 3.17
Subsystems (7)
Steven Rostedt
maintainercover tracing: Updates for 3.17
This is my current 3.17 queue. I'm still waiting on acks from various arch maintainers to add the ftrace_stop/start() removal code that I also want to add to this.
This includes various clean ups and enhancements, but the big feature is the "trampoline" field added to the ftrace_ops. The only user of that currently is the function_graph tracer. This is because the function graph tracer normally jumps to the function tracer mcount trampoline, saves and restores regs without doing anything before it gets to the function graph code that also saves and restores regs (slightly differently mind you), and runs its code. Now, if function graph tracer is the only callback of a function, its code will be called directly, skipping the function trampoline entirely.
The trace_seq code was also cleaned up. This opens up the possibility that the trace_seq can be converted to "seq_buf" and used for printing in NMI context.
I'm still waiting on a Acked-by from the SCSI folks for a change to the trace_seq code that removes some open access of the trace_seq buffer. I wont push this to my next branch until I hear back from them.
The way to push will also let people give me feedback before this becomes solidified in stone, as I don't like to rebase my for-next branch.
-- Steve
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
for-next
Head SHA1: d048a8c7b509f35dd351e1415fe49fa99e4cb7ef
Fabian Frederick (2):
tracing: Remove unnecessary null test before debugfs_remove()
tracing: Convert pr_warning() to pr_warn() in trace_events.c
Masami Hiramatsu (1):
ftrace: Simplify ftrace_hash_disable/enable path in ftrace_hash_move
Namhyung Kim (7):
ftrace: Get rid of obsolete global_start_up variable
ftrace: Fix memory leak on failure path in ftrace_allocate_pages()
ftrace: Do not copy hash if O_TRUNC is set
tracing: Add ftrace_graph_notrace boot parameter
tracing: Improve message of empty set_graph_notrace file
tracing: Improve message of empty set_ftrace_notrace file
tracing: Add description of set_graph_notrace to tracing/README
Steven Rostedt (Red Hat) (10):
ftrace: Allow no regs if no more callbacks require it
ftrace: Use macros for numbers in ftrace rec shift bits
ftrace: Add ftrace_rec_counter() macro to simplify the code
ftrace: Optimize function graph to be called directly
ftrace: Add trampolines to enabled_functions debug file
tracing: Move the trace_seq_* functions into its own trace_seq.c file
tracing: Clean up trace_seq.c
tracing: Make trace_seq_putmem_hex() more robust
tracing: Remove trace_seq_reserve()
tracing: Add trace_seq_buffer_ptr() helper function
Zhao Hongjiang (1):
tracing: Change trace event sample to use strlcpy instead of strncpy
----
Documentation/kernel-parameters.txt | 6 + arch/x86/kernel/mcount_64.S | 5 + arch/x86/kvm/mmutrace.h | 2 +- drivers/scsi/scsi_trace.c | 16 +- include/linux/ftrace.h | 24 +- include/linux/trace_seq.h | 36 ++- kernel/trace/Makefile | 1 + kernel/trace/ftrace.c | 394 ++++++++++++++++++++++---- kernel/trace/trace.c | 31 +-- kernel/trace/trace_events.c | 56 ++-- kernel/trace/trace_output.c | 282 +------------------ kernel/trace/trace_output.h | 4 - kernel/trace/trace_seq.c | 428 +++++++++++++++++++++++++++++ samples/trace_events/trace-events-sample.h | 2 +- 14 files changed, 870 insertions(+), 417 deletions(-)
Steven Rostedt
maintainerPATCH 1/21 ftrace: Allow no regs if no more callbacks require it
From: "Steven Rostedt (Red Hat)" <[email protected]>
When registering a function callback for the function tracer, the ops can specify if it wants to save full regs (like an interrupt would) for each function that it traces, or if it does not care about regs and just wants to have the fastest return possible.
Once a ops has registered a function, if other ops register that function they all will receive the regs too. That's because it does the work once, it does it for everyone.
Now if the ops wanting regs unregisters the function so that there's only ops left that do not care about regs, those ops will still continue getting regs and going through the work for it on that function. This is because the disabling of the rec counter only sees the ops registered, and does not see the ops that are still attached, and does not know if the current ops that are still attached want regs or not. To play it safe, it just keeps regs being processed until no function is registered anymore.
Instead of doing that, check the ops that are still registered for that function and if none want regs for it anymore, then disable the processing of regs.
--- kernel/trace/ftrace.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
kernel/trace/ftrace.c +32 -0
@@ -1492,6 +1492,26 @@ int ftrace_text_reserved(const void *start, const void *end)return (int )!!ret; } +/* Test if ops registered to this rec needs regs */ +static bool test_rec_ops_needs_regs (struct dyn_ftrace *rec) +{ +struct ftrace_ops *ops; +bool keep_regs = false; + +for (ops = ftrace_ops_list; + ops != &ftrace_list_end; ops = ops->next) { +/* pass rec in as regs to have non-NULL val */ +if (ftrace_ops_test (ops, rec->ip, rec)) { +if (ops->flags &FTRACE_OPS_FL_SAVE_REGS ) { + keep_regs = true; +break ; + } + } + } + +return keep_regs; +} +static void __ftrace_hash_rec_update (struct ftrace_ops *ops,int filter_hash,bool inc)
@@ -1584,6 +1604,18 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,if (FTRACE_WARN_ON ((rec->flags & ~FTRACE_FL_MASK ) ==0 ))return ; rec->flags--; +/* +* If the rec had REGS enabled and the ops that is +* being removed had REGS set, then see if there is +* still any ops for this record that wants regs. +* If not, we can stop recording them. +*/ +if ((rec->flags & ~FTRACE_FL_MASK ) >0 && + rec->flags &FTRACE_FL_REGS && + ops->flags &FTRACE_OPS_FL_SAVE_REGS ) { +if (!test_rec_ops_needs_regs (rec)) + rec->flags &= ~FTRACE_FL_REGS ; + } } count++;/* Shortcut, if we handled all records, we are done. */
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 2/21 ftrace: Use macros for numbers in ftrace rec shift bits
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
As new flags will be added to the ftrace dynamic record, and since the flags field is also a counter, converting the numbers used to do the shifting and masking into a set of macros where we only need to deal with the max bit count of the counter and the number of bits for the flags will prevent mistakes in the future.
Dealing with only two numbers is much easier than updating all the macros that deal with shifting and masking.
--- include/linux/ftrace.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
include/linux/ftrace.h +5 -2
@@ -322,8 +322,11 @@ enum {FTRACE_FL_REGS_EN = (1UL <<31 ) }; -#define FTRACE_FL_MASK (0x7UL << 29) -#define FTRACE_REF_MAX ((1UL << 29) - 1) +#define FTRACE_REF_MAX_SHIFT 29 +#define FTRACE_FL_BITS 3 +#define FTRACE_FL_MASKED_BITS ((1UL << FTRACE_FL_BITS) - 1) +#define FTRACE_FL_MASK (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT) +#define FTRACE_REF_MAX ((1UL << FTRACE_REF_MAX_SHIFT) - 1)struct dyn_ftrace {unsigned long ip;/* address of mcount call-site */
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 3/21 ftrace: Add ftrace_rec_counter() macro to simplify the code
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
The ftrace dynamic record has a flags element that also has a counter. Instead of hard coding "rec->flags & ~FTRACE_FL_MASK" all over the place. Use a macro instead.
--- include/linux/ftrace.h | 2 ++ kernel/trace/ftrace.c | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-)
include/linux/ftrace.h +2 -0
@@ -328,6 +328,8 @@ enum {#define FTRACE_FL_MASK (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)#define FTRACE_REF_MAX ((1UL << FTRACE_REF_MAX_SHIFT) - 1) +#define ftrace_rec_count (rec) ((rec)->flags & ~FTRACE_FL_MASK) +struct dyn_ftrace {unsigned long ip;/* address of mcount call-site */ unsigned long flags;
kernel/trace/ftrace.c +6 -6
@@ -1592,7 +1592,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,if (inc) { rec->flags++; -if (FTRACE_WARN_ON ((rec->flags & ~FTRACE_FL_MASK ) ==FTRACE_REF_MAX )) +if (FTRACE_WARN_ON (ftrace_rec_count (rec) ==FTRACE_REF_MAX ))return ;/* * If any ops wants regs saved for this function
@@ -1601,7 +1601,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,if (ops->flags &FTRACE_OPS_FL_SAVE_REGS ) rec->flags |=FTRACE_FL_REGS ; }else { -if (FTRACE_WARN_ON ((rec->flags & ~FTRACE_FL_MASK ) ==0 )) +if (FTRACE_WARN_ON (ftrace_rec_count (rec) ==0 ))return ; rec->flags--;/*
@@ -1610,7 +1610,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,* still any ops for this record that wants regs. * If not, we can stop recording them. */ -if ((rec->flags & ~FTRACE_FL_MASK ) >0 && +if (ftrace_rec_count (rec) >0 && rec->flags &FTRACE_FL_REGS && ops->flags &FTRACE_OPS_FL_SAVE_REGS ) {if (!test_rec_ops_needs_regs (rec))
@@ -1700,7 +1700,7 @@ static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)* If we are disabling calls, then disable all records that * are enabled. */ -if (enable && (rec->flags & ~FTRACE_FL_MASK )) +if (enable &&ftrace_rec_count (rec)) flag =FTRACE_FL_ENABLED ;/*
@@ -1746,7 +1746,7 @@ static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)if (update) {/* If there's no more users, clear all flags */ -if (!(rec->flags & ~FTRACE_FL_MASK )) +if (!ftrace_rec_count (rec)) rec->flags =0 ;else /* Just disable the record (keep REGS state) */
@@ -2685,7 +2685,7 @@ static int t_show(struct seq_file *m, void *v)seq_printf (m,"%ps" , (void *)rec->ip);if (iter->flags &FTRACE_ITER_ENABLED )seq_printf (m," (%ld)%s" , - rec->flags & ~FTRACE_FL_MASK , +ftrace_rec_count (rec), rec->flags &FTRACE_FL_REGS ?" R" :"" );seq_printf (m,"\n" );
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 4/21 ftrace: Optimize function graph to be called directly
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
Function graph tracing is a bit different than the function tracers, as it is processed after either the ftrace_caller or ftrace_regs_caller and we only have one place to modify the jump to ftrace_graph_caller, the jump needs to happen after the restore of registeres.
The function graph tracer is dependent on the function tracer, where even if the function graph tracing is going on by itself, the save and restore of registers is still done for function tracing regardless of if function tracing is happening, before it calls the function graph code.
If there's no function tracing happening, it is possible to just call the function graph tracer directly, and avoid the wasted effort to save and restore regs for function tracing.
This requires adding new flags to the dyn_ftrace records:
FTRACE_FL_TRAMP
FTRACE_FL_TRAMP_EN
The first is set if the count for the record is one, and the ftrace_ops associated to that record has its own trampoline. That way the mcount code can call that trampoline directly.
In the future, trampolines can be added to arbitrary ftrace_ops, where you can have two or more ftrace_ops registered to ftrace (like kprobes and perf) and if they are not tracing the same functions, then instead of doing a loop to check all registered ftrace_ops against their hashes, just call the ftrace_ops trampoline directly, which would call the registered ftrace_ops function directly.
Without this patch perf showed:
0.05% hackbench [kernel.kallsyms] [k] ftrace_caller 0.05% hackbench [kernel.kallsyms] [k] arch_local_irq_save 0.05% hackbench [kernel.kallsyms] [k] native_sched_clock 0.04% hackbench [kernel.kallsyms] [k] __buffer_unlock_commit 0.04% hackbench [kernel.kallsyms] [k] preempt_trace 0.04% hackbench [kernel.kallsyms] [k] prepare_ftrace_return 0.04% hackbench [kernel.kallsyms] [k] __this_cpu_preempt_check 0.04% hackbench [kernel.kallsyms] [k] ftrace_graph_caller
See that the ftrace_caller took up more time than the ftrace_graph_caller did.
With this patch:
0.05% hackbench [kernel.kallsyms] [k] __buffer_unlock_commit 0.04% hackbench [kernel.kallsyms] [k] call_filter_check_discard 0.04% hackbench [kernel.kallsyms] [k] ftrace_graph_caller 0.04% hackbench [kernel.kallsyms] [k] sched_clock
The ftrace_caller is no where to be found and ftrace_graph_caller still takes up the same percentage.
--- arch/x86/kernel/mcount_64.S | 5 + include/linux/ftrace.h | 19 +++- kernel/trace/ftrace.c | 242 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 254 insertions(+), 12 deletions(-)
arch/x86/kernel/mcount_64.S +5 -0
@@ -182,6 +182,10 @@ END(function_hook) ENTRY(ftrace_graph_caller) MCOUNT_SAVE_FRAME + /* Check if tracing was disabled (quick check) */ + cmpl $0, function_trace_stop + jne fgraph_skip + #ifdef CC_USING_FENTRY leaq SS+16(%rsp), %rdi movq $0, %rdx /* No framepointers needed */
@@ -194,6 +198,7 @@ ENTRY(ftrace_graph_caller) call prepare_ftrace_return +fgraph_skip: MCOUNT_RESTORE_FRAME retq
include/linux/ftrace.h +14 -5
@@ -118,12 +118,15 @@ struct ftrace_ops {ftrace_func_t func;struct ftrace_ops *next;unsigned long flags; -int __percpu *disabled;void *private; +int __percpu *disabled;#ifdef CONFIG_DYNAMIC_FTRACE +int trampolines;struct ftrace_hash *notrace_hash;struct ftrace_hash *filter_hash; +struct ftrace_hash *tramp_hash;struct mutex regex_lock; +unsigned long trampoline;#endif };
@@ -317,13 +320,15 @@ extern int ftrace_nr_registered_ops(void);* from tracing that function. */ enum { -FTRACE_FL_ENABLED = (1UL <<29 ), +FTRACE_FL_ENABLED = (1UL <<31 ),FTRACE_FL_REGS = (1UL <<30 ), -FTRACE_FL_REGS_EN = (1UL <<31 ) +FTRACE_FL_REGS_EN = (1UL <<29 ), +FTRACE_FL_TRAMP = (1UL <<28 ), +FTRACE_FL_TRAMP_EN = (1UL <<27 ), }; -#define FTRACE_REF_MAX_SHIFT 29 -#define FTRACE_FL_BITS 3 +#define FTRACE_REF_MAX_SHIFT 27 +#define FTRACE_FL_BITS 5#define FTRACE_FL_MASKED_BITS ((1UL << FTRACE_FL_BITS) - 1)#define FTRACE_FL_MASK (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)#define FTRACE_REF_MAX ((1UL << FTRACE_REF_MAX_SHIFT) - 1)
@@ -436,6 +441,10 @@ void ftrace_modify_all_code(int command);#define FTRACE_ADDR ((unsigned long)ftrace_caller)#endif +#ifndef FTRACE_GRAPH_ADDR +#define FTRACE_GRAPH_ADDR ((unsigned long)ftrace_graph_caller) +#endif +#ifndef FTRACE_REGS_ADDR #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS # define FTRACE_REGS_ADDR ((unsigned long)ftrace_regs_caller)
kernel/trace/ftrace.c +235 -7
341 lines not on this page · raw message
Signature · 1 line
2.0.0
Re: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly
Quoted 57 lines · Steven Rostedt
From: "Steven Rostedt (Red Hat)"<[email protected]>
Function graph tracing is a bit different than the function tracers, as it is processed after either the
ftrace_callerorftrace_regs_callerand we only have one place to modify the jump toftrace_graph_caller, the jump needs to happen after the restore of registeres.The function graph tracer is dependent on the function tracer, where even if the function graph tracing is going on by itself, the save and restore of registers is still done for function tracing regardless of if function tracing is happening, before it calls the function graph code.
If there's no function tracing happening, it is possible to just call the function graph tracer directly, and avoid the wasted effort to save and restore regs for function tracing.
This requires adding new flags to the
dyn_ftracerecords:
FTRACE_FL_TRAMP
FTRACE_FL_TRAMP_ENThe first is set if the count for the record is one, and the
ftrace_opsassociated to that record has its own trampoline. That way the mcount code can call that trampoline directly.In the future, trampolines can be added to arbitrary
ftrace_ops, where you can have two or moreftrace_opsregistered to ftrace (like kprobes and perf) and if they are not tracing the same functions, then instead of doing a loop to check all registeredftrace_opsagainst their hashes, just call theftrace_opstrampoline directly, which would call the registeredftrace_opsfunction directly.Without this patch perf showed:
0.05% hackbench [kernel.kallsyms] [k] ftrace_caller 0.05% hackbench [kernel.kallsyms] [k] arch_local_irq_save 0.05% hackbench [kernel.kallsyms] [k] native_sched_clock 0.04% hackbench [kernel.kallsyms] [k] __buffer_unlock_commit 0.04% hackbench [kernel.kallsyms] [k] preempt_trace 0.04% hackbench [kernel.kallsyms] [k] prepare_ftrace_return 0.04% hackbench [kernel.kallsyms] [k] __this_cpu_preempt_check 0.04% hackbench [kernel.kallsyms] [k] ftrace_graph_callerSee that the
ftrace_callertook up more time than theftrace_graph_callerdid.With this patch:
0.05% hackbench [kernel.kallsyms] [k] __buffer_unlock_commit 0.04% hackbench [kernel.kallsyms] [k] call_filter_check_discard 0.04% hackbench [kernel.kallsyms] [k] ftrace_graph_caller 0.04% hackbench [kernel.kallsyms] [k] sched_clockThe
ftrace_calleris no where to be found andftrace_graph_callerstill takes up the same percentage.
Quoted 7 lines
Signed-off-by Steven Rostedt<[email protected]>--- arch/x86/kernel/mcount_64.S | 5 + include/linux/ftrace.h | 19 +++- kernel/trace/ftrace.c | 242 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 254 insertions(+), 12 deletions(-)
This commit (79922b8) breaks the function graph tracer on today's -next. This is on an ARM Tegra board.
I'm using ftrace with this script:
#!/bin/sh
echo function_graph > /d/tracing/current_tracer
echo clear > /d/tracing/trace
echo $$ > /d/tracing/set_ftrace_pid
exec "$@"
...and a simple './trace.sh ls' crashes with no console output. SysRq is not responsive either.
Steven Rostedt
maintainerRe: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly
Quoted 5 lines · On Thu, 10 Jul 2014 20:45:57 +0300 Tuomas Tynkkynen <[email protected]>…
This commit (79922b8) breaks the function graph tracer on today's -next. This is on an ARM Tegra board.
I'm using ftrace with this script:
Quoted 8 lines
#!/bin/sh
echofunction_graph> /d/tracing/current_tracer
echo clear > /d/tracing/trace
echo $$ > /d/tracing/set_ftrace_pid
exec "$@"...and a simple './trace.sh ls' crashes with no console output. SysRq is not responsive either.
Thanks for the report. I'll boot up one of my arm boards and see if I can reproduce it. I'll try to get to it either this week or next.
-- Steve
Steven Rostedt
maintainerRe: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly
In reply to Tuomas TynkkynenQuoted 4 lines · On Thu, 10 Jul 2014 20:45:57 +0300 Tuomas Tynkkynen <[email protected]>…
Quoted 1 line
This commit (79922b8) breaks the function graph tracer on today's -next. This is on an ARM Tegra board.
Can you test this patch. It makes the default operation of calling the function graph tracer trampoline directly being disabled. It is now up to the arch to define FTRACE_GRAPH_TRAMP_ADDR that can be used to call directly. If it is not set, the old method of calling the function tracer first is used.
I'll worked on getting arm to be called directly too. Can you test that patch as well? I'll reply to this email with that one.
Thanks!
-- Steve
Quoted 1 line
From
641e0d82e5be65adac6449f62d68d83012b780d9Mon Sep 17 00:00:00 2001
From: "Steven Rostedt (Red Hat)" <[email protected]>
Date: Fri, 11 Jul 2014 14:39:10 -0400
Subject: [PATCH] ftrace: Allow archs to specify if they need a separate
function graph trampoline
Currently if an arch supports function graph tracing, the core code will just assign the function graph trampoline to the function graph addr that gets called.
But as the old method for function graph tracing always calls the function trampoline first and that calls the function graph trampoline, some archs may have the function graph trampoline dependent on operations that were done in the function trampoline. This causes function graph tracer to break on those archs.
Instead of having the default be to set the function graph ftrace_ops to the function graph trampoline, have it instead just set it to zero which will keep it from jumping to a trampoline that is not set up to be jumped directly too.
--- include/linux/ftrace.h | 10 ++++++++++ kernel/trace/ftrace.c | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-)
include/linux/ftrace.h +10 -0
@@ -453,6 +453,16 @@ void ftrace_modify_all_code(int command);#endif #endif +/* +* If an arch would like functions that are only traced +* by the function graph tracer to jump directly to its own +* trampoline, then they can define FTRACE_GRAPH_TRAMP_ADDR +* to be that address to jump to. +*/ +#ifndef FTRACE_GRAPH_TRAMP_ADDR +#define FTRACE_GRAPH_TRAMP_ADDR ((unsigned long) 0) +#endif +#ifdef CONFIG_FUNCTION_GRAPH_TRACER extern void ftrace_graph_caller (void );extern int ftrace_enable_ftrace_graph_caller (void );
kernel/trace/ftrace.c +4 -2
@@ -5366,7 +5366,8 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,#ifdef CONFIG_DYNAMIC_FTRACE /* Optimize function graph calling (if implemented by arch) */ - global_ops.trampoline =FTRACE_GRAPH_ADDR ; +if (FTRACE_GRAPH_TRAMP_ADDR ) + global_ops.trampoline =FTRACE_GRAPH_TRAMP_ADDR ;#endif ret =ftrace_startup (&global_ops,FTRACE_START_FUNC_RET );
@@ -5390,7 +5391,8 @@ void unregister_ftrace_graph(void)ftrace_shutdown (&global_ops,FTRACE_STOP_FUNC_RET ); global_ops.flags &= ~FTRACE_OPS_FL_STUB ;#ifdef CONFIG_DYNAMIC_FTRACE - global_ops.trampoline =0 ; +if (FTRACE_GRAPH_TRAMP_ADDR ) + global_ops.trampoline =0 ;#endif unregister_pm_notifier (&ftrace_suspend_notifier);unregister_trace_sched_switch (ftrace_graph_probe_sched_switch,NULL );
Signature · 1 line
1.8.1.4
Steven Rostedt
maintainerRe: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly
Quoted 2 lines · On Fri, 11 Jul 2014 23:36:10 -0400 Steven Rostedt <[email protected]> wrote:
I'll worked on getting arm to be called directly too. Can you test that patch as well? I'll reply to this email with that one.
Here's that patch:
-- Steve
Quoted 1 line
From
ff9ee792640d802415eaedf0e8d41992c898d2a9Mon Sep 17 00:00:00 2001
From: "Steven Rostedt (Red Hat)" <[email protected]>
Date: Fri, 11 Jul 2014 23:28:11 -0400
Subject: [PATCH] ARM: ftrace: Allow function graph tracer to have its own
trampoline
The ftrace infrastructure now allows the function graph tracer trampoline to be called directly instead of having to first go through the function tracer trampoline. But in order for this to work, the function graph tracer must be dependent from the function tracer trampoline. Currently in ARM, the function graph tracer does not save registers as it depends on the function tracer trampoline to do so.
By adding a ftrace_graph_tramp_caller function that saves the regs then does the function graph tracing work, this can be used as the trampoline for function graph tracing.
--- arch/arm/include/asm/ftrace.h | 5 +++++ arch/arm/kernel/entry-common.S | 7 +++++++ 2 files changed, 12 insertions(+)
arch/arm/include/asm/ftrace.h +5 -0
@@ -54,6 +54,11 @@ extern inline void *return_address(unsigned int level)#define ftrace_return_address (n) return_address(n) +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +extern void ftrace_graph_tramp_caller (void ); +#define FTRACE_GRAPH_TRAMP_ADDR ((unsigned long)ftrace_graph_tramp_caller) +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +#endif /* ifndef __ASSEMBLY__ */ #endif /* _ASM_ARM_FTRACE */
arch/arm/kernel/entry-common.S +7 -0
@@ -314,6 +314,13 @@ ENDPROC(ftrace_caller) #endif #ifdef CONFIG_FUNCTION_GRAPH_TRACER +ENTRY(ftrace_graph_tramp_caller) +UNWIND(.fnstart) + mcount_enter + __ftrace_graph_caller +UNWIND(.fnend) +ENDPROC(ftrace_graph_tramp_caller) + ENTRY(ftrace_graph_caller) UNWIND(.fnstart) __ftrace_graph_caller
Signature · 1 line
1.8.1.4
Tuomas Tynkkynen
Tested-byRe: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly
Quoted 28 lines · Steven Rostedt
Quoted 2 lines · On Fri, 11 Jul 2014 23:36:10 -0400 Steven Rostedt <[email protected]> wrote:
I'll worked on getting arm to be called directly too. Can you test that patch as well? I'll reply to this email with that one.
Here's that patch:
-- Steve
From
ff9ee792640d802415eaedf0e8d41992c898d2a9Mon Sep 17 00:00:00 2001
From: "Steven Rostedt (Red Hat)" <[email protected]>
Date: Fri, 11 Jul 2014 23:28:11 -0400
Subject: [PATCH] ARM: ftrace: Allow function graph tracer to have its own
trampolineThe ftrace infrastructure now allows the function graph tracer trampoline to be called directly instead of having to first go through the function tracer trampoline. But in order for this to work, the function graph tracer must be dependent from the function tracer trampoline. Currently in ARM, the function graph tracer does not save registers as it depends on the function tracer trampoline to do so.
By adding a
ftrace_graph_tramp_callerfunction that saves the regs then does the function graph tracing work, this can be used as the trampoline for function graph tracing.
Quoted 9 lines
Reported-by Tuomas Tynkkynen <[email protected]>Signed-off-by Steven Rostedt <[email protected]>--- arch/arm/include/asm/ftrace.h | 5 +++++ arch/arm/kernel/entry-common.S | 7 +++++++ 2 files changed, 12 insertions(+)
[...]
Thanks, both of these patches work for me.
- Tuomas
Signature · 1 line
nvpublic
Steven Rostedt
maintainerRe: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly
Quoted 3 lines · On Mon, 14 Jul 2014 16:46:40 +0300 Tuomas Tynkkynen <[email protected]>…
Thanks, both of these patches work for me.
Tested-by Tuomas Tynkkynen <[email protected]>
Thanks for testing.
I'll pull the first one if for my for-next, and the second one I'll send to the arm folks for 3.18, after the first one is in mainline.
Hopefully I remember to do that :-)
-- Steve
Steven Rostedt
maintainerPATCH 5/21 ftrace: Add trampolines to enabled_functions debug file
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
The enabled_functions is used to help debug the dynamic function tracing. Adding what trampolines are attached to files is useful for debugging.
--- kernel/trace/ftrace.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
kernel/trace/ftrace.c +14 -2
@@ -2903,10 +2903,22 @@ static int t_show(struct seq_file *m, void *v)return 0 ;seq_printf (m,"%ps" , (void *)rec->ip); -if (iter->flags &FTRACE_ITER_ENABLED ) +if (iter->flags &FTRACE_ITER_ENABLED ) {seq_printf (m," (%ld)%s" ,ftrace_rec_count (rec), - rec->flags &FTRACE_FL_REGS ?" R" :"" ); + rec->flags &FTRACE_FL_REGS ?" R" :" " ); +if (rec->flags &FTRACE_FL_TRAMP_EN ) { +struct ftrace_ops *ops; + + ops =ftrace_find_tramp_ops_curr (rec); +if (ops && ops->trampoline) +seq_printf (m,"\ttramp: %pS" , + (void *)ops->trampoline); +else +seq_printf (m,"\ttramp: ERROR!" ); + } + } +seq_printf (m,"\n" );return 0 ;
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 6/21 tracing: Change trace event sample to use strlcpy instead of strncpy
In reply to Steven RostedtFrom: Zhao Hongjiang <[email protected]>
Strings should be copied with strlcpy instead of strncpy when they will later be printed via %s. This guarantees that they terminate with a NUL '\0' character and do not run pass the end of the allocated string.
This is only for sample code, but it should stil represent a good role model.
--- samples/trace_events/trace-events-sample.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
samples/trace_events/trace-events-sample.h +1 -1
@@ -87,7 +87,7 @@ TRACE_EVENT(foo_bar, ), TP_fast_assign( - strncpy(__entry->foo, foo, 10); + strlcpy(__entry->foo, foo, 10); __entry->bar = bar; ),
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 7/21 ftrace: Simplify ftrace_hash_disable/enable path in ftrace_hash_move
In reply to Steven RostedtFrom: Masami Hiramatsu <[email protected]>
Simplify ftrace_hash_disable/enable path in ftrace_hash_move for hardening the process if the memory allocation failed.
--- kernel/trace/ftrace.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-)
kernel/trace/ftrace.c +11 -22
@@ -1306,25 +1306,15 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,struct ftrace_hash *new_hash;int size = src->count;int bits =0 ; -int ret;int i;/* -* Remove the current set, update the hash and add -* them back. -*/ -ftrace_hash_rec_disable (ops, enable); - -/* * If the new source is empty, just free dst and assign it * the empty_hash. */ if (!src->count) { -free_ftrace_hash_rcu (*dst); -rcu_assign_pointer (*dst,EMPTY_HASH ); -/* still need to update the function records */ - ret =0 ; - goto out; + new_hash =EMPTY_HASH ; + goto update; }/*
@@ -1337,10 +1327,9 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,if (bits >FTRACE_HASH_MAX_BITS ) bits =FTRACE_HASH_MAX_BITS ; - ret = -ENOMEM ; new_hash =alloc_ftrace_hash (bits);if (!new_hash) - goto out; +return -ENOMEM ; size =1 << src->size_bits;for (i =0 ; i < size; i++) {
@@ -1351,20 +1340,20 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable, } } +update: +/* +* Remove the current set, update the hash and add +* them back. +*/ +ftrace_hash_rec_disable (ops, enable); + old_hash = *dst;rcu_assign_pointer (*dst, new_hash);free_ftrace_hash_rcu (old_hash); - ret =0 ; - out: -/* -* Enable regardless of ret: -* On success, we enable the new hash. -* On failure, we re-enable the original hash. -*/ ftrace_hash_rec_enable (ops, enable); -return ret; +return 0 ; }/*
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 8/21 tracing: Move the trace_seq_* functions into its own trace_seq.c file
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
The trace_seq_*() functions are a nice utility that allows users to manipulate buffers with printf() like formats. It has its own trace_seq.h header in include/linux and should be in its own file. Being tied with trace_output.c is rather awkward.
--- include/linux/trace_seq.h | 2 + kernel/trace/Makefile | 1 + kernel/trace/trace.c | 24 ---- kernel/trace/trace_output.c | 268 --------------------------------------- kernel/trace/trace_output.h | 3 - kernel/trace/trace_seq.c | 303 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 306 insertions(+), 295 deletions(-) create mode 100644 kernel/trace/trace_seq.c
include/linux/trace_seq.h +2 -0
@@ -25,6 +25,8 @@ trace_seq_init(struct trace_seq *s) s->full =0 ; } +#define MAX_MEMHEX_BYTES 8 +/* * Currently only defined when tracing is enabled. */
kernel/trace/Makefile +1 -0
@@ -28,6 +28,7 @@ obj-$(CONFIG_RING_BUFFER_BENCHMARK) += ring_buffer_benchmark.o obj-$(CONFIG_TRACING) += trace.o obj-$(CONFIG_TRACING) += trace_output.o +obj-$(CONFIG_TRACING) += trace_seq.o obj-$(CONFIG_TRACING) += trace_stat.o obj-$(CONFIG_TRACING) += trace_printk.o obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
kernel/trace/trace.c +0 -24
@@ -923,30 +923,6 @@ out:return ret; } -ssize_t trace_seq_to_user (struct trace_seq *s,char __user *ubuf,size_t cnt) -{ -int len; -int ret; - -if (!cnt) -return 0 ; - -if (s->len <= s->readpos) -return -EBUSY ; - - len = s->len - s->readpos; -if (cnt > len) - cnt = len; - ret =copy_to_user (ubuf, s->buffer + s->readpos, cnt); -if (ret == cnt) -return -EFAULT ; - - cnt -= ret; - - s->readpos += cnt; -return cnt; -} -static ssize_t trace_seq_to_buffer (struct trace_seq *s,void *buf,size_t cnt) {int len;
kernel/trace/trace_output.c +0 -268
280 lines not on this page · raw message
kernel/trace/trace_output.h +0 -3
@@ -35,9 +35,6 @@ trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry);extern int __unregister_ftrace_event (struct trace_event *event);extern struct rw_semaphore trace_event_sem; -#define MAX_MEMHEX_BYTES 8 -#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1) -#define SEQ_PUT_FIELD_RET (s, x) \ do { \ if (!trace_seq_putmem(s, &(x), sizeof(x))) \
kernel/trace/trace_seq.c new file +303 -0
303 lines not on this page · raw message
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 9/21 tracing: Clean up trace_seq.c
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
For using trace_seq_*() functions in NMI context, I posted a patch to move it to the lib/ directory. This caused Andrew Morton to take a look at the code. He went through and gave a lot of comments about missing kernel doc, inconsistent types for the save variable, mix match of EXPORT_SYMBOL_GPL() and EXPORT_SYMBOL() as well as missing EXPORT_SYMBOL*()s. There were a few comments about the way variables were being compared (int vs uint).
All these were good review comments and should be implemented regardless of if trace_seq.c should be moved to lib/ or not.
--- include/linux/trace_seq.h | 20 ++--- kernel/trace/trace_seq.c | 207 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 185 insertions(+), 42 deletions(-)
include/linux/trace_seq.h +10 -10
@@ -38,14 +38,14 @@ int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args);extern int trace_seq_bprintf (struct trace_seq *s,const char *fmt,const u32 *binary);extern int trace_print_seq (struct seq_file *m,struct trace_seq *s); -extern ssize_t trace_seq_to_user (struct trace_seq *s,char __user *ubuf, -size_t cnt); +extern int trace_seq_to_user (struct trace_seq *s,char __user *ubuf, +int cnt);extern int trace_seq_puts (struct trace_seq *s,const char *str);extern int trace_seq_putc (struct trace_seq *s,unsigned char c); -extern int trace_seq_putmem (struct trace_seq *s,const void *mem,size_t len); +extern int trace_seq_putmem (struct trace_seq *s,const void *mem,unsigned int len);extern int trace_seq_putmem_hex (struct trace_seq *s,const void *mem, -size_t len); -extern void *trace_seq_reserve (struct trace_seq *s,size_t len); +unsigned int len); +extern void *trace_seq_reserve (struct trace_seq *s,unsigned int len);extern int trace_seq_path (struct trace_seq *s,const struct path *path); extern int trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
@@ -73,8 +73,8 @@ static inline int trace_print_seq(struct seq_file *m, struct trace_seq *s) {return 0 ; } -static inline ssize_t trace_seq_to_user (struct trace_seq *s,char __user *ubuf, -size_t cnt) +static inline int trace_seq_to_user (struct trace_seq *s,char __user *ubuf, +int cnt) {return 0 ; }
@@ -87,16 +87,16 @@ static inline int trace_seq_putc(struct trace_seq *s, unsigned char c)return 0 ; }static inline int -trace_seq_putmem (struct trace_seq *s,const void *mem,size_t len) +trace_seq_putmem (struct trace_seq *s,const void *mem,unsigned int len) {return 0 ; }static inline int trace_seq_putmem_hex (struct trace_seq *s,const void *mem, -size_t len) +unsigned int len) {return 0 ; } -static inline void *trace_seq_reserve (struct trace_seq *s,size_t len) +static inline void *trace_seq_reserve (struct trace_seq *s,unsigned int len) {return NULL ; }
kernel/trace/trace_seq.c +175 -32
354 lines not on this page · raw message
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 10/21 tracing: Make trace_seq_putmem_hex() more robust
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
Currently trace_seq_putmem_hex() can only take as a parameter a pointer to something that is 8 bytes or less, otherwise it will overflow the buffer. This is protected by a macro that encompasses the call to trace_seq_putmem_hex() that has a BUILD_BUG_ON() for the variable before it is passed in. This is not very robust and if trace_seq_putmem_hex() ever gets used outside that macro it will cause issues.
Instead of only being able to produce a hex output of memory that is for a single word, change it to be more robust and allow any size input.
--- include/linux/trace_seq.h | 2 -- kernel/trace/trace_output.h | 1 - kernel/trace/trace_seq.c | 26 +++++++++++++++++++------- 3 files changed, 19 insertions(+), 10 deletions(-)
include/linux/trace_seq.h +0 -2
@@ -25,8 +25,6 @@ trace_seq_init(struct trace_seq *s) s->full =0 ; } -#define MAX_MEMHEX_BYTES 8 -/* * Currently only defined when tracing is enabled. */
kernel/trace/trace_output.h +0 -1
@@ -43,7 +43,6 @@ do { \#define SEQ_PUT_HEX_FIELD_RET (s, x) \ do { \ - BUILD_BUG_ON(sizeof(x) > MAX_MEMHEX_BYTES); \ if (!trace_seq_putmem_hex(s, &(x), sizeof(x))) \ return TRACE_TYPE_PARTIAL_LINE; \ } while (0)
kernel/trace/trace_seq.c +19 -7
@@ -291,6 +291,7 @@ int trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len) }EXPORT_SYMBOL_GPL (trace_seq_putmem); +#define MAX_MEMHEX_BYTES 8U#define HEX_CHARS (MAX_MEMHEX_BYTES*2 + 1)/**
@@ -310,22 +311,33 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem, {unsigned char hex[HEX_CHARS ];const unsigned char *data = mem; +unsigned int start_len;int i, j; +int cnt =0 ;if (s->full)return 0 ; +while (len) { + start_len =min (len,HEX_CHARS -1 );#ifdef __BIG_ENDIAN -for (i =0 , j =0 ; i < len; i++) { +for (i =0 , j =0 ; i < start_len; i++) {#else -for (i = len-1 , j =0 ; i >=0 ; i--) { +for (i = start_len-1 , j =0 ; i >=0 ; i--) {#endif - hex[j++] =hex_asc_hi (data[i]); - hex[j++] =hex_asc_lo (data[i]); - } - hex[j++] =' ' ; + hex[j++] =hex_asc_hi (data[i]); + hex[j++] =hex_asc_lo (data[i]); + } +if (WARN_ON_ONCE (j ==0 || j/2 > len)) +break ; + +/* j increments twice per loop */ + len -= j /2 ; + hex[j++] =' ' ; -return trace_seq_putmem (s, hex, j); + cnt +=trace_seq_putmem (s, hex, j); + } + return cnt; }EXPORT_SYMBOL_GPL (trace_seq_putmem_hex);
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 11/21 tracing: Remove trace_seq_reserve()
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
trace_seq_reserve() has no users in the kernel, it just wastes space. Remove it.
--- include/linux/trace_seq.h | 5 ----- kernel/trace/trace_seq.c | 30 ------------------------------ 2 files changed, 35 deletions(-)
include/linux/trace_seq.h +0 -5
@@ -43,7 +43,6 @@ extern int trace_seq_putc(struct trace_seq *s, unsigned char c);extern int trace_seq_putmem (struct trace_seq *s,const void *mem,unsigned int len);extern int trace_seq_putmem_hex (struct trace_seq *s,const void *mem,unsigned int len); -extern void *trace_seq_reserve (struct trace_seq *s,unsigned int len);extern int trace_seq_path (struct trace_seq *s,const struct path *path); extern int trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
@@ -94,10 +93,6 @@ static inline int trace_seq_putmem_hex(struct trace_seq *s, const void *mem, {return 0 ; } -static inline void *trace_seq_reserve (struct trace_seq *s,unsigned int len) -{ -return NULL ; -}static inline int trace_seq_path (struct trace_seq *s,const struct path *path) {return 0 ;
kernel/trace/trace_seq.c +0 -30
@@ -342,36 +342,6 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,EXPORT_SYMBOL_GPL (trace_seq_putmem_hex);/** -* trace_seq_reserve - reserve space on the sequence buffer -* @s: trace sequence descriptor -* @len: The amount to reserver. -* -* If for some reason there is a need to save some space on the -* buffer to fill in later, this function is used for that purpose. -* The given length will be reserved and the pointer to that -* location on the buffer is returned, unless there is not enough -* buffer left to hold the given length then NULL is returned. -*/ -void *trace_seq_reserve (struct trace_seq *s,unsigned int len) -{ -void *ret; - -if (s->full) -return NULL ; - -if (len >TRACE_SEQ_BUF_LEFT (s)) { - s->full =1 ; -return NULL ; - } - - ret = s->buffer + s->len; - s->len += len; - -return ret; -} -EXPORT_SYMBOL_GPL (trace_seq_reserve); - -/** * trace_seq_path - copy a path into the sequence buffer * @s: trace sequence descriptor * @path: path to write into the sequence buffer.
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 12/21 tracing: Remove unnecessary null test before debugfs_remove()
In reply to Steven RostedtFrom: Fabian Frederick <[email protected]>
This fixes checkpatch warning:
"WARNING: debugfs_remove(NULL) is safe this check is probably not required"
--- kernel/trace/trace.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
kernel/trace/trace.c +2 -4
@@ -6071,10 +6071,8 @@ destroy_trace_option_files(struct trace_option_dentry *topts)if (!topts)return ; -for (cnt =0 ; topts[cnt].opt; cnt++) { -if (topts[cnt].entry) -debugfs_remove (topts[cnt].entry); - } +for (cnt =0 ; topts[cnt].opt; cnt++) +debugfs_remove (topts[cnt].entry);kfree (topts); }
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 13/21 tracing: Add trace_seq_buffer_ptr() helper function
In reply to Steven RostedtFrom: "Steven Rostedt (Red Hat)" <[email protected]>
There's several locations in the kernel that open code the calculation of the next location in the trace_seq buffer. This is usually done with
p->buffer + p->len
Instead of having this open coded, supply a helper function in the header to do it for them. This function is called trace_seq_buffer_ptr().
--- arch/x86/kvm/mmutrace.h | 2 +- drivers/scsi/scsi_trace.c | 16 ++++++++-------- include/linux/trace_seq.h | 15 +++++++++++++++ kernel/trace/trace_output.c | 14 +++++++------- 4 files changed, 31 insertions(+), 16 deletions(-)
arch/x86/kvm/mmutrace.h +1 -1
@@ -22,7 +22,7 @@ __entry->unsync = sp->unsync;#define KVM_MMU_PAGE_PRINTK () ({ \ - const char *ret = p->buffer + p->len; \ + const char *ret = trace_seq_buffer_ptr(p); \ static const char *access_str[] = { \ "---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux" \ }; \
drivers/scsi/scsi_trace.c +8 -8
@@ -28,7 +28,7 @@ scsi_trace_misc(struct trace_seq *, unsigned char *, int);static const char *scsi_trace_rw6 (struct trace_seq *p,unsigned char *cdb,int len) { -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);sector_t lba =0 , txlen =0 ; lba |= ((cdb[1 ] &0x1F ) <<16 );
@@ -46,7 +46,7 @@ scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)static const char *scsi_trace_rw10 (struct trace_seq *p,unsigned char *cdb,int len) { -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);sector_t lba =0 , txlen =0 ; lba |= (cdb[2 ] <<24 );
@@ -71,7 +71,7 @@ scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)static const char *scsi_trace_rw12 (struct trace_seq *p,unsigned char *cdb,int len) { -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);sector_t lba =0 , txlen =0 ; lba |= (cdb[2 ] <<24 );
@@ -94,7 +94,7 @@ scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)static const char *scsi_trace_rw16 (struct trace_seq *p,unsigned char *cdb,int len) { -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);sector_t lba =0 , txlen =0 ; lba |= ((u64 )cdb[2 ] <<56 );
@@ -125,7 +125,7 @@ scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)static const char *scsi_trace_rw32 (struct trace_seq *p,unsigned char *cdb,int len) { -const char *ret = p->buffer + p->len, *cmd; +const char *ret =trace_seq_buffer_ptr (p), *cmd;sector_t lba =0 , txlen =0 ;u32 ei_lbrt =0 ;
@@ -180,7 +180,7 @@ out:static const char *scsi_trace_unmap (struct trace_seq *p,unsigned char *cdb,int len) { -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);unsigned int regions = cdb[7 ] <<8 | cdb[8 ];trace_seq_printf (p,"regions=%u" , (regions -8 ) /16 );
@@ -192,7 +192,7 @@ scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)static const char *scsi_trace_service_action_in (struct trace_seq *p,unsigned char *cdb,int len) { -const char *ret = p->buffer + p->len, *cmd; +const char *ret =trace_seq_buffer_ptr (p), *cmd;sector_t lba =0 ;u32 alloc_len =0 ;
@@ -247,7 +247,7 @@ scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)static const char *scsi_trace_misc (struct trace_seq *p,unsigned char *cdb,int len) { -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);trace_seq_printf (p,"-" );trace_seq_putc (p,0 );
include/linux/trace_seq.h +15 -0
@@ -25,6 +25,21 @@ trace_seq_init(struct trace_seq *s) s->full =0 ; } +/** +* trace_seq_buffer_ptr - return pointer to next location in buffer +* @s: trace sequence descriptor +* +* Returns the pointer to the buffer where the next write to +* the buffer will happen. This is useful to save the location +* that is about to be written to and then return the result +* of that write. +*/ +static inline unsigned char * +trace_seq_buffer_ptr (struct trace_seq *s) +{ +return s->buffer + s->len; +} +/* * Currently only defined when tracing is enabled. */
kernel/trace/trace_output.c +7 -7
@@ -75,7 +75,7 @@ ftrace_print_flags_seq(struct trace_seq *p, const char *delim, {unsigned long mask;const char *str; -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);int i, first =1 ;for (i =0 ; flag_array[i].name && flags; i++) {
@@ -111,7 +111,7 @@ ftrace_print_symbols_seq(struct trace_seq *p, unsigned long val, const struct trace_print_flags *symbol_array) {int i; -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);for (i =0 ; symbol_array[i].name; i++) {
@@ -122,7 +122,7 @@ ftrace_print_symbols_seq(struct trace_seq *p, unsigned long val,break ; } -if (ret == (const char *)(p->buffer + p->len)) +if (ret == (const char *)(trace_seq_buffer_ptr (p)))trace_seq_printf (p,"0x%lx" , val);trace_seq_putc (p,0 );
@@ -137,7 +137,7 @@ ftrace_print_symbols_seq_u64(struct trace_seq *p, unsigned long long val, const struct trace_print_flags_u64 *symbol_array) {int i; -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);for (i =0 ; symbol_array[i].name; i++) {
@@ -148,7 +148,7 @@ ftrace_print_symbols_seq_u64(struct trace_seq *p, unsigned long long val,break ; } -if (ret == (const char *)(p->buffer + p->len)) +if (ret == (const char *)(trace_seq_buffer_ptr (p)))trace_seq_printf (p,"0x%llx" , val);trace_seq_putc (p,0 );
@@ -162,7 +162,7 @@ const char * ftrace_print_bitmask_seq(struct trace_seq *p, void *bitmask_ptr, unsigned int bitmask_size) { - const char *ret = p->buffer + p->len; + const char *ret = trace_seq_buffer_ptr(p);trace_seq_bitmask (p, bitmask_ptr, bitmask_size *8 );trace_seq_putc (p,0 );
@@ -175,7 +175,7 @@ const char * ftrace_print_hex_seq(struct trace_seq *p, const unsigned char *buf, int buf_len) { int i; -const char *ret = p->buffer + p->len; +const char *ret =trace_seq_buffer_ptr (p);for (i =0 ; i < buf_len; i++)trace_seq_printf (p,"%s%2.2x" , i ==0 ?"" :" " , buf[i]);
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 14/21 ftrace: Get rid of obsolete global_start_up variable
In reply to Steven RostedtFrom: Namhyung Kim <[email protected]>
It seems like it's a leftover from commit 4104d326b670 ("ftrace:
Remove global function list and call function directly"). As it isn't updated at all, checking its value is meaningless.
Let's get rid of it.
--- kernel/trace/ftrace.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
kernel/trace/ftrace.c +1 -3
@@ -2286,7 +2286,6 @@ static void ftrace_run_update_code(int command)static ftrace_func_t saved_ftrace_func;static int ftrace_start_up; -static int global_start_up;static void control_ops_free (struct ftrace_ops *ops) {
@@ -2350,8 +2349,7 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)ftrace_hash_rec_disable (ops,1 ); -if (!global_start_up) - ops->flags &= ~FTRACE_OPS_FL_ENABLED ; + ops->flags &= ~FTRACE_OPS_FL_ENABLED ; command |=FTRACE_UPDATE_CALLS ;
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 15/21 ftrace: Fix memory leak on failure path in ftrace_allocate_pages()
In reply to Steven RostedtFrom: Namhyung Kim <[email protected]>
As struct ftrace_page is managed in a single linked list, it should free from the start page.
--- kernel/trace/ftrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/trace/ftrace.c +2 -1
@@ -2637,7 +2637,8 @@ ftrace_allocate_pages(unsigned long num_to_init)return start_pg; free_pages: -while (start_pg) { + pg = start_pg; +while (pg) { order =get_count_order (pg->size /ENTRIES_PER_PAGE );free_pages ((unsigned long )pg->records, order); start_pg = pg->next;
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 16/21 ftrace: Do not copy hash if O_TRUNC is set
In reply to Steven RostedtFrom: Namhyung Kim <[email protected]>
When a filter file is open for writing and O_TRUNC is set, there's no need to copy and free the filter entries.
--- kernel/trace/ftrace.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
kernel/trace/ftrace.c +7 -5
@@ -3010,7 +3010,13 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, hash = ops->filter_hash;if (file->f_mode &FMODE_WRITE ) { - iter->hash =alloc_and_copy_ftrace_hash (FTRACE_HASH_DEFAULT_BITS , hash); +const int size_bits =FTRACE_HASH_DEFAULT_BITS ; + +if (file->f_flags &O_TRUNC ) + iter->hash =alloc_ftrace_hash (size_bits); +else + iter->hash =alloc_and_copy_ftrace_hash (size_bits, hash); +if (!iter->hash) {trace_parser_put (&iter->parser);kfree (iter);
@@ -3019,10 +3025,6 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, } } -if ((file->f_mode &FMODE_WRITE ) && - (file->f_flags &O_TRUNC )) -ftrace_filter_reset (iter->hash); -if (file->f_mode &FMODE_READ ) { iter->pg = ftrace_pages_start;
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 17/21 tracing: Convert pr_warning() to pr_warn() in trace_events.c
In reply to Steven RostedtFrom: Fabian Frederick <[email protected]>
Convert pr_warning to standard pr_warn
Define pr_fmt(fmt) fmt to avoid any future default fmt definition
--- kernel/trace/trace_events.c | 56 ++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 29 deletions(-)
kernel/trace/trace_events.c +27 -29
@@ -8,6 +8,8 @@* */ +#define pr_fmt (fmt) fmt +#include <linux/workqueue.h> #include <linux/spinlock.h> #include <linux/kthread.h>
@@ -1490,7 +1492,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name, dir->entry =debugfs_create_dir (name, parent);if (!dir->entry) { -pr_warning ("Failed to create system directory %s\n" , name); +pr_warn ("Failed to create system directory %s\n" , name);__put_system (system); goto out_free; }
@@ -1506,7 +1508,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name,if (!entry) {kfree (system->filter); system->filter =NULL ; -pr_warning ("Could not create debugfs '%s/filter' entry\n" , name); +pr_warn ("Could not create debugfs '%s/filter' entry\n" , name); } trace_create_file("enable", 0644, dir->entry, dir,
@@ -1521,8 +1523,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name, out_fail:/* Only print this message if failed on memory allocation */ if (!dir || !system) -pr_warning ("No memory to create event subsystem %s\n" , - name); +pr_warn ("No memory to create event subsystem %s\n" , name);return NULL ; }
@@ -1550,8 +1551,7 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file) name =ftrace_event_name (call); file->dir =debugfs_create_dir (name, d_events);if (!file->dir) { -pr_warning ("Could not create debugfs '%s' directory\n" , - name); +pr_warn ("Could not create debugfs '%s' directory\n" , name);return -1 ; }
@@ -1574,8 +1574,8 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file)if (list_empty (head)) { ret = call->class->define_fields (call);if (ret <0 ) { -pr_warning ("Could not initialize trace point" -" events/%s\n" , name); +pr_warn ("Could not initialize trace point events/%s\n" , + name);return -1 ; } }
@@ -1648,8 +1648,7 @@ static int event_init(struct ftrace_event_call *call)if (call->class->raw_init) { ret = call->class->raw_init (call);if (ret <0 && ret != -ENOSYS ) -pr_warn ("Could not initialize trace events/%s\n" , - name); +pr_warn ("Could not initialize trace events/%s\n" , name); }return ret;
@@ -1894,8 +1893,8 @@ __trace_add_event_dirs(struct trace_array *tr)list_for_each_entry (call, &ftrace_events, list) { ret =__trace_add_new_event (call, tr);if (ret <0 ) -pr_warning ("Could not create directory for event %s\n" , -ftrace_event_name (call)); +pr_warn ("Could not create directory for event %s\n" , +ftrace_event_name (call)); } }
@@ -2207,8 +2206,8 @@ __trace_early_add_event_dirs(struct trace_array *tr)list_for_each_entry (file, &tr->events, list) { ret =event_create_dir (tr->event_dir, file);if (ret <0 ) -pr_warning ("Could not create directory for event %s\n" , -ftrace_event_name (file->event_call)); +pr_warn ("Could not create directory for event %s\n" , +ftrace_event_name (file->event_call)); } }
@@ -2231,8 +2230,8 @@ __trace_early_add_events(struct trace_array *tr) ret =__trace_early_add_new_event (call, tr);if (ret <0 ) -pr_warning ("Could not create early event %s\n" , -ftrace_event_name (call)); +pr_warn ("Could not create early event %s\n" , +ftrace_event_name (call)); } }
@@ -2279,13 +2278,13 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr) entry =debugfs_create_file ("set_event" ,0644 , parent, tr, &ftrace_set_event_fops);if (!entry) { -pr_warning ("Could not create debugfs 'set_event' entry\n" ); +pr_warn ("Could not create debugfs 'set_event' entry\n" );return -ENOMEM ; } d_events =debugfs_create_dir ("events" , parent);if (!d_events) { -pr_warning ("Could not create debugfs 'events' directory\n" ); +pr_warn ("Could not create debugfs 'events' directory\n" );return -ENOMEM ; }
@@ -2461,11 +2460,10 @@ static __init int event_trace_init(void) entry =debugfs_create_file ("available_events" ,0444 , d_tracer, tr, &ftrace_avail_fops);if (!entry) -pr_warning ("Could not create debugfs " -"'available_events' entry\n" ); +pr_warn ("Could not create debugfs 'available_events' entry\n" );if (trace_define_common_fields ()) -pr_warning ("tracing: Failed to allocate common fields" ); +pr_warn ("tracing: Failed to allocate common fields" ); ret =early_event_add_tracer (d_tracer, tr);if (ret)
@@ -2474,7 +2472,7 @@ static __init int event_trace_init(void)#ifdef CONFIG_MODULES ret =register_module_notifier (&trace_module_nb);if (ret) -pr_warning ("Failed to register trace events module notifier\n" ); +pr_warn ("Failed to register trace events module notifier\n" );#endif return 0 ; }
@@ -2578,7 +2576,7 @@ static __init void event_trace_self_tests(void)* it and the self test should not be on. */ if (file->flags &FTRACE_EVENT_FL_ENABLED ) { -pr_warning ("Enabled event during self test!\n" ); +pr_warn ("Enabled event during self test!\n" );WARN_ON_ONCE (1 );continue ; }
@@ -2606,8 +2604,8 @@ static __init void event_trace_self_tests(void) ret =__ftrace_set_clr_event (tr,NULL , system->name,NULL ,1 );if (WARN_ON_ONCE (ret)) { -pr_warning ("error enabling system %s\n" , - system->name); +pr_warn ("error enabling system %s\n" , + system->name);continue ; }
@@ -2615,8 +2613,8 @@ static __init void event_trace_self_tests(void) ret =__ftrace_set_clr_event (tr,NULL , system->name,NULL ,0 );if (WARN_ON_ONCE (ret)) { -pr_warning ("error disabling system %s\n" , - system->name); +pr_warn ("error disabling system %s\n" , + system->name);continue ; }
@@ -2630,7 +2628,7 @@ static __init void event_trace_self_tests(void) ret =__ftrace_set_clr_event (tr,NULL ,NULL ,NULL ,1 );if (WARN_ON_ONCE (ret)) { -pr_warning ("error enabling all events\n" ); +pr_warn ("error enabling all events\n" );return ; }
@@ -2639,7 +2637,7 @@ static __init void event_trace_self_tests(void)/* reset sysname */ ret =__ftrace_set_clr_event (tr,NULL ,NULL ,NULL ,0 );if (WARN_ON_ONCE (ret)) { -pr_warning ("error disabling all events\n" ); +pr_warn ("error disabling all events\n" );return ; }
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 18/21 tracing: Add ftrace_graph_notrace boot parameter
In reply to Steven RostedtFrom: Namhyung Kim <[email protected]>
The ftrace_graph_notrace option is for specifying notrace filter for function graph tracer at boot time. It can be altered after boot using set_graph_notrace file on the debugfs.
--- Documentation/kernel-parameters.txt | 6 ++++++ kernel/trace/ftrace.c | 24 ++++++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-)
Documentation/kernel-parameters.txt +6 -0
@@ -1097,6 +1097,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. that can be changed at run time by the set_graph_function file in the debugfs tracing directory. + ftrace_graph_notrace=[function-list] + [FTRACE] Do not trace from the functions specified in + function-list. This list is a comma separated list of + functions that can be changed at run time by the + set_graph_notrace file in the debugfs tracing directory. + gamecon.map[2|3]= [HW,JOY] Multisystem joystick and NES/SNES/PSX pad support via parallel port (up to 5 devices per port)
kernel/trace/ftrace.c +20 -4
@@ -3884,6 +3884,7 @@ __setup("ftrace_filter=", set_ftrace_filter);#ifdef CONFIG_FUNCTION_GRAPH_TRACER static char ftrace_graph_buf[FTRACE_FILTER_SIZE ]__initdata ; +static char ftrace_graph_notrace_buf[FTRACE_FILTER_SIZE ]__initdata ;static int ftrace_set_func (unsigned long *array,int *idx,int size,char *buffer);static int __init set_graph_function (char *str)
@@ -3893,16 +3894,29 @@ static int __init set_graph_function(char *str) }__setup ("ftrace_graph_filter=" , set_graph_function); -static void __init set_ftrace_early_graph (char *buf) +static int __init set_graph_notrace_function (char *str) +{ +strlcpy (ftrace_graph_notrace_buf, str,FTRACE_FILTER_SIZE ); +return 1 ; +} +__setup ("ftrace_graph_notrace=" , set_graph_notrace_function); + +static void __init set_ftrace_early_graph (char *buf,int enable) {int ret;char *func; +unsigned long *table = ftrace_graph_funcs; +int *count = &ftrace_graph_count; + +if (!enable) { + table = ftrace_graph_notrace_funcs; + count = &ftrace_graph_notrace_count; + }while (buf) { func =strsep (&buf,"," );/* we allow only one expression at a time */ - ret =ftrace_set_func (ftrace_graph_funcs, &ftrace_graph_count, -FTRACE_GRAPH_MAX_FUNCS , func); + ret =ftrace_set_func (table, count,FTRACE_GRAPH_MAX_FUNCS , func);if (ret)printk (KERN_DEBUG "ftrace: function %s not " "traceable\n" , func);
@@ -3931,7 +3945,9 @@ static void __init set_ftrace_early_filters(void)ftrace_set_early_filter (&global_ops, ftrace_notrace_buf,0 );#ifdef CONFIG_FUNCTION_GRAPH_TRACER if (ftrace_graph_buf[0 ]) -set_ftrace_early_graph (ftrace_graph_buf); +set_ftrace_early_graph (ftrace_graph_buf,1 ); +if (ftrace_graph_notrace_buf[0 ]) +set_ftrace_early_graph (ftrace_graph_notrace_buf,0 );#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ }
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 19/21 tracing: Improve message of empty set_graph_notrace file
In reply to Steven RostedtFrom: Namhyung Kim <[email protected]>
When there's no entry in set_graph_notrace, it'll print below message
#### all functions enabled ####
While this is technically correct, it's better to print like below:
#### no functions disabled ####
--- kernel/trace/ftrace.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
kernel/trace/ftrace.c +6 -1
@@ -4089,7 +4089,12 @@ static int g_show(struct seq_file *m, void *v)return 0 ;if (ptr == (unsigned long *)1 ) { -seq_printf (m,"#### all functions enabled ####\n" ); +struct ftrace_graph_data *fgd = m->private; + +if (fgd->table == ftrace_graph_funcs) +seq_printf (m,"#### all functions enabled ####\n" ); +else +seq_printf (m,"#### no functions disabled ####\n" );return 0 ; }
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 20/21 tracing: Improve message of empty set_ftrace_notrace file
In reply to Steven RostedtFrom: Namhyung Kim <[email protected]>
When there's no entry in set_ftrace_notrace, it'll print nothing, but it's better to print something like below like set_graph_notrace does:
#### no functions disabled ####
--- kernel/trace/ftrace.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
kernel/trace/ftrace.c +8 -3
@@ -2835,8 +2835,10 @@ static void *t_start(struct seq_file *m, loff_t *pos)* off, we can short cut and just print out that all * functions are enabled. */ -if (iter->flags &FTRACE_ITER_FILTER && -ftrace_hash_empty (ops->filter_hash)) { +if ((iter->flags &FTRACE_ITER_FILTER && +ftrace_hash_empty (ops->filter_hash)) || + (iter->flags &FTRACE_ITER_NOTRACE && +ftrace_hash_empty (ops->notrace_hash))) {if (*pos >0 )return t_hash_start (m, pos); iter->flags |=FTRACE_ITER_PRINTALL ;
@@ -2881,7 +2883,10 @@ static int t_show(struct seq_file *m, void *v)return t_hash_show (m, iter);if (iter->flags &FTRACE_ITER_PRINTALL ) { -seq_printf (m,"#### all functions enabled ####\n" ); +if (iter->flags &FTRACE_ITER_NOTRACE ) +seq_printf (m,"#### no functions disabled ####\n" ); +else +seq_printf (m,"#### all functions enabled ####\n" );return 0 ; }
Signature · 1 line
2.0.0
Steven Rostedt
maintainerPATCH 21/21 tracing: Add description of set_graph_notrace to tracing/README
In reply to Steven RostedtFrom: Namhyung Kim <[email protected]>
It was missing the description of set_graph_notrace file. Add it.
--- kernel/trace/trace.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/trace.c +1 -0
@@ -3663,6 +3663,7 @@ static const char readme_msg[] =#endif #ifdef CONFIG_FUNCTION_GRAPH_TRACER " set_graph_function\t- Trace the nested calls of a function (function_graph)\n" +" set_graph_notrace\t- Do not trace the nested calls of a function (function_graph)\n" " max_graph_depth\t- Trace a limited depth of nested calls (0 is unlimited)\n"#endif #ifdef CONFIG_TRACER_SNAPSHOT
Signature · 1 line
2.0.0