[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1323105776-26961-11-git-send-email-jolsa@redhat.com>
Date: Mon, 5 Dec 2011 18:22:56 +0100
From: Jiri Olsa <jolsa@...hat.com>
To: rostedt@...dmis.org, fweisbec@...il.com, mingo@...hat.com,
paulus@...ba.org, acme@...stprotocols.net, a.p.zijlstra@...llo.nl
Cc: linux-kernel@...r.kernel.org, aarapov@...hat.com,
Jiri Olsa <jolsa@...hat.com>
Subject: [PATCHv2 10/10] ftrace, graph: Add global_ops filter callback for graph tracing
The function graph tracer should depend on the global_ops filter,
and process only functions that pass the global_ops filter.
Currently the function graph tracer gets all the functions
enabled for tracing no matter what ftrace_ops enabled them.
Adding a hook for the graph entry callback, which ensures the
function is compared against the global_ops filter and bail
out of if it does not match.
This hook is enabled only if there's at least one non global
ftrace_ops registered.
Signed-off-by: Jiri Olsa <jolsa@...hat.com>
---
kernel/trace/ftrace.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 2dae0c7..dc49ba6 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -95,10 +95,13 @@ ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
static struct ftrace_ops global_ops;
static struct ftrace_ops control_ops;
+static int non_global_ops_registered;
static void
ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip);
+static void ftrace_graph_update_filter(void);
+
/*
* Traverse the ftrace_global_list, invoking all entries. The reason that we
* can use rcu_dereference_raw() is that elements removed from this list
@@ -330,6 +333,9 @@ static int __register_ftrace_function(struct ftrace_ops *ops)
if (!core_kernel_data((unsigned long)ops))
ops->flags |= FTRACE_OPS_FL_DYNAMIC;
+ if (!(ops->flags & FTRACE_OPS_FL_GLOBAL))
+ non_global_ops_registered++;
+
if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
add_ftrace_ops(&ftrace_global_list, &global_ops, ops);
ops->flags |= FTRACE_OPS_FL_ENABLED;
@@ -359,6 +365,9 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)
if (FTRACE_WARN_ON(ops == &global_ops))
return -EINVAL;
+ if (!(ops->flags & FTRACE_OPS_FL_GLOBAL))
+ non_global_ops_registered--;
+
if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
ret = remove_ftrace_ops(&ftrace_global_list, &global_ops, ops);
if (!ret)
@@ -1695,6 +1704,8 @@ static int __ftrace_modify_code(void *data)
if (*command & FTRACE_UPDATE_TRACE_FUNC)
ftrace_update_ftrace_func(ftrace_trace_function);
+ ftrace_graph_update_filter();
+
if (*command & FTRACE_START_FUNC_RET)
ftrace_enable_ftrace_graph_caller();
else if (*command & FTRACE_STOP_FUNC_RET)
@@ -4339,4 +4350,34 @@ void ftrace_graph_stop(void)
{
ftrace_stop();
}
+
+static trace_func_graph_ent_t ftrace_graph_entry_saved;
+
+int ftrace_graph_entry_filter(struct ftrace_graph_ent *ent)
+{
+ if (ftrace_ops_test(&global_ops, ent->func))
+ return ftrace_graph_entry_saved(ent);
+
+ return 0;
+}
+
+static void ftrace_graph_update_filter(void)
+{
+ bool installed = (ftrace_graph_entry == ftrace_graph_entry_filter);
+
+ if (!ftrace_graph_active)
+ return;
+
+ if (!installed && non_global_ops_registered) {
+ ftrace_graph_entry_saved = ftrace_graph_entry;
+ ftrace_graph_entry = ftrace_graph_entry_filter;
+ return;
+ }
+
+ if (installed && !non_global_ops_registered)
+ ftrace_graph_entry = ftrace_graph_entry_saved;
+}
+
+#else
+static void ftrace_graph_update_filter(void) { }
#endif
--
1.7.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists