ftrace/x86: Add a counter to test function_graph with direct
authorSteven Rostedt (VMware) <rostedt@goodmis.org>
Fri, 8 Nov 2019 18:12:57 +0000 (13:12 -0500)
committerSteven Rostedt (VMware) <rostedt@goodmis.org>
Wed, 13 Nov 2019 14:36:49 +0000 (09:36 -0500)
As testing for direct calls from the function graph tracer adds a little
overhead (which is a lot when tracing every function), add a counter that
can be used to test if function_graph tracer needs to test for a direct
caller or not.

It would have been nicer if we could use a static branch, but the static
branch logic fails when used within the function graph tracer trampoline.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
arch/x86/kernel/ftrace.c
include/linux/ftrace.h
kernel/trace/ftrace.c

index fef283f6341df04856adfc9a1b0fc439f4b18202..060a361d9d11b09303d901cbfa7dff896d5af1d2 100644 (file)
@@ -1049,9 +1049,11 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
         * return address is actually off by one word, and we
         * need to adjust for that.
         */
-       if (ftrace_find_direct_func(self_addr + MCOUNT_INSN_SIZE)) {
-               self_addr = *parent;
-               parent++;
+       if (ftrace_direct_func_count) {
+               if (ftrace_find_direct_func(self_addr + MCOUNT_INSN_SIZE)) {
+                       self_addr = *parent;
+                       parent++;
+               }
        }
 
        /*
index 2bc7bd6b838727cafd9a17c7b7b1f9da5f61b5ba..55647e1851411b2b408856d64237f5ec4c502f4d 100644 (file)
@@ -247,10 +247,12 @@ static inline void ftrace_free_mem(struct module *mod, void *start, void *end) {
 #endif /* CONFIG_FUNCTION_TRACER */
 
 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+extern int ftrace_direct_func_count;
 int register_ftrace_direct(unsigned long ip, unsigned long addr);
 int unregister_ftrace_direct(unsigned long ip, unsigned long addr);
 struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr);
 #else
+# define ftrace_direct_func_count 0
 static inline int register_ftrace_direct(unsigned long ip, unsigned long addr)
 {
        return -ENODEV;
index c4446eabacbe599452057fc14bfef1e9b487bbfe..f9456346ec6673097658a675cfb0d867b9f2168e 100644 (file)
@@ -2364,6 +2364,7 @@ ftrace_find_tramp_ops_new(struct dyn_ftrace *rec)
 /* Protected by rcu_tasks for reading, and direct_mutex for writing */
 static struct ftrace_hash *direct_functions = EMPTY_HASH;
 static DEFINE_MUTEX(direct_mutex);
+int ftrace_direct_func_count;
 
 /*
  * Search the direct_functions hash to see if the given instruction pointer
@@ -5056,6 +5057,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
                direct->addr = addr;
                direct->count = 0;
                list_add_rcu(&direct->next, &ftrace_direct_funcs);
+               ftrace_direct_func_count++;
        }
 
        entry->ip = ip;
@@ -5081,6 +5083,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
                        if (free_hash)
                                free_ftrace_hash(free_hash);
                        free_hash = NULL;
+                       ftrace_direct_func_count--;
                }
        } else {
                if (!direct->count)
@@ -5141,6 +5144,7 @@ int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
                        list_del_rcu(&direct->next);
                        synchronize_rcu_tasks();
                        kfree(direct);
+                       ftrace_direct_func_count--;
                }
        }
  out_unlock: