aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
authorSteven Rostedt (VMware) <rostedt@goodmis.org>2019-02-11 15:00:48 -0500
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2019-02-15 13:10:09 -0500
commitf79b3f338564e7674dbe6375bcf685c2ba483efe (patch)
tree481aa4a5340b5c1f3d9a167f06fce036ba08fbc7 /kernel/trace/ftrace.c
parent85acbb21b9310043692cf18b1fd14067b5a25ccd (diff)
ftrace: Allow enabling of filters via index of available_filter_functions
Enabling of large number of functions by echoing in a large subset of the functions in available_filter_functions can take a very long time. The process requires testing all functions registered by the function tracer (which is in the 10s of thousands), and doing a kallsyms lookup to convert the ip address into a name, then comparing that name with the string passed in. When a function causes the function tracer to crash the system, a binary bisect of the available_filter_functions can be done to find the culprit. But this requires passing in half of the functions in available_filter_functions over and over again, which makes it basically a O(n^2) operation. With 40,000 functions, that ends up bing 1,600,000,000 opertions! And enabling this can take over 20 minutes. As a quick speed up, if a number is passed into one of the filter files, instead of doing a search, it just enables the function at the corresponding line of the available_filter_functions file. That is: # echo 50 > set_ftrace_filter # cat set_ftrace_filter x86_pmu_commit_txn # head -50 available_filter_functions | tail -1 x86_pmu_commit_txn This allows setting of half the available_filter_functions to take place in less than a second! # time seq 20000 > set_ftrace_filter real 0m0.042s user 0m0.005s sys 0m0.015s # wc -l set_ftrace_filter 20000 set_ftrace_filter Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index aac7847c0214..fa79323331b2 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3702,6 +3702,31 @@ enter_record(struct ftrace_hash *hash, struct dyn_ftrace *rec, int clear_filter)
3702} 3702}
3703 3703
3704static int 3704static int
3705add_rec_by_index(struct ftrace_hash *hash, struct ftrace_glob *func_g,
3706 int clear_filter)
3707{
3708 long index = simple_strtoul(func_g->search, NULL, 0);
3709 struct ftrace_page *pg;
3710 struct dyn_ftrace *rec;
3711
3712 /* The index starts at 1 */
3713 if (--index < 0)
3714 return 0;
3715
3716 do_for_each_ftrace_rec(pg, rec) {
3717 if (pg->index <= index) {
3718 index -= pg->index;
3719 /* this is a double loop, break goes to the next page */
3720 break;
3721 }
3722 rec = &pg->records[index];
3723 enter_record(hash, rec, clear_filter);
3724 return 1;
3725 } while_for_each_ftrace_rec();
3726 return 0;
3727}
3728
3729static int
3705ftrace_match_record(struct dyn_ftrace *rec, struct ftrace_glob *func_g, 3730ftrace_match_record(struct dyn_ftrace *rec, struct ftrace_glob *func_g,
3706 struct ftrace_glob *mod_g, int exclude_mod) 3731 struct ftrace_glob *mod_g, int exclude_mod)
3707{ 3732{
@@ -3769,6 +3794,11 @@ match_records(struct ftrace_hash *hash, char *func, int len, char *mod)
3769 if (unlikely(ftrace_disabled)) 3794 if (unlikely(ftrace_disabled))
3770 goto out_unlock; 3795 goto out_unlock;
3771 3796
3797 if (func_g.type == MATCH_INDEX) {
3798 found = add_rec_by_index(hash, &func_g, clear_filter);
3799 goto out_unlock;
3800 }
3801
3772 do_for_each_ftrace_rec(pg, rec) { 3802 do_for_each_ftrace_rec(pg, rec) {
3773 3803
3774 if (rec->flags & FTRACE_FL_DISABLED) 3804 if (rec->flags & FTRACE_FL_DISABLED)