ftrace: Add private data to ftrace_ops
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>
Thu, 7 Nov 2013 14:36:25 +0000 (09:36 -0500)
committerSteven Rostedt <rostedt@goodmis.org>
Thu, 20 Feb 2014 17:13:12 +0000 (12:13 -0500)
Passing data to the function callback was originally done by adding the
ftrace_ops in another structure, and using the container_of() to get
the field. But this adds a bit more complexity than it is worth, and
adding a simple .private field to ftrace_ops makes things a lot easier.

But be warned, the .private data should not be freed once it is used
unless the ftrace_ops itself has gone through the necessary freeing
routines. A simple synchronize_sched() is not enough as functions
can be traced that are called outside the view of RCU and all its
concoctions.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
include/linux/ftrace.h

index f4233b195dab3e5fd64a0a1885c286374499d6ac..ef1607ed704439ead78575e0d87378792c8cefc7 100644 (file)
@@ -105,11 +105,23 @@ enum {
        FTRACE_OPS_FL_INITIALIZED               = 1 << 8,
 };
 
+/*
+ * Note, ftrace_ops can be referenced outside of RCU protection.
+ * (Although, for perf, the control ops prevent that). If ftrace_ops is
+ * allocated and not part of kernel core data, the unregistering of it will
+ * perform a scheduling on all CPUs to make sure that there are no more users.
+ * Depending on the load of the system that may take a bit of time.
+ *
+ * Any private data added must also take care not to be freed and if private
+ * data is added to a ftrace_ops that is in core code, the user of the
+ * ftrace_ops must perform a schedule_on_each_cpu() before freeing it.
+ */
 struct ftrace_ops {
        ftrace_func_t                   func;
        struct ftrace_ops               *next;
        unsigned long                   flags;
        int __percpu                    *disabled;
+       void                            *private;
 #ifdef CONFIG_DYNAMIC_FTRACE
        struct ftrace_hash              *notrace_hash;
        struct ftrace_hash              *filter_hash;