From: "Steven Rostedt (Red Hat)" <srost...@redhat.com>

The new multi-buffers added a descriptor that kept track of module
events, and the directories they use, with struct ftace_module_file_ops.
This is used to add a ref count to keep modules from unloading while
their files are being accessed.

As the descriptor is only needed when CONFIG_MODULES is enabled, it
is only declared when the config is enabled. But that struct is
dereferenced in a few areas outside the #ifdef CONFIG_MODULES.

By adding some helper routines and moving code around a little,
events can be compiled again without modules.

Reported-by: Fengguang Wu <fengguang...@intel.com>
Signed-off-by: Steven Rostedt <rost...@goodmis.org>
---
 kernel/trace/trace_events.c |   55 ++++++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 19 deletions(-)

diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 63b4bdf..0f1307a 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1546,9 +1546,18 @@ struct ftrace_module_file_ops {
        struct file_operations          filter;
 };
 
-static struct ftrace_module_file_ops *find_ftrace_file_ops(struct module *mod)
+static struct ftrace_module_file_ops *
+find_ftrace_file_ops(struct ftrace_module_file_ops *file_ops, struct module 
*mod)
 {
-       struct ftrace_module_file_ops *file_ops;
+       /*
+        * As event_calls are added in groups by module,
+        * when we find one file_ops, we don't need to search for
+        * each call in that module, as the rest should be the
+        * same. Only search for a new one if the last one did
+        * not match.
+        */
+       if (file_ops && mod == file_ops->mod)
+               return file_ops;
 
        list_for_each_entry(file_ops, &ftrace_module_file_list, list) {
                if (file_ops->mod == mod)
@@ -1664,16 +1673,35 @@ static int trace_module_notify(struct notifier_block 
*self,
 
        return 0;
 }
+
+static int
+__trace_add_new_mod_event(struct ftrace_event_call *call,
+                         struct trace_array *tr,
+                         struct ftrace_module_file_ops *file_ops)
+{
+       return __trace_add_new_event(call, tr,
+                                    &file_ops->id, &file_ops->enable,
+                                    &file_ops->filter, &file_ops->format);
+}
+
 #else
-static struct ftrace_module_file_ops *find_ftrace_file_ops(struct module *mod)
+static inline struct ftrace_module_file_ops *
+find_ftrace_file_ops(struct ftrace_module_file_ops *file_ops, struct module 
*mod)
 {
        return NULL;
 }
-static int trace_module_notify(struct notifier_block *self,
-                              unsigned long val, void *data)
+static inline int trace_module_notify(struct notifier_block *self,
+                                     unsigned long val, void *data)
 {
        return 0;
 }
+static inline int
+__trace_add_new_mod_event(struct ftrace_event_call *call,
+                         struct trace_array *tr,
+                         struct ftrace_module_file_ops *file_ops)
+{
+       return -ENODEV;
+}
 #endif /* CONFIG_MODULES */
 
 /* Create a new event directory structure for a trace directory. */
@@ -1692,20 +1720,11 @@ __trace_add_event_dirs(struct trace_array *tr)
                         * want the module to disappear when reading one
                         * of these files). The file_ops keep account of
                         * the module ref count.
-                        *
-                        * As event_calls are added in groups by module,
-                        * when we find one file_ops, we don't need to search 
for
-                        * each call in that module, as the rest should be the
-                        * same. Only search for a new one if the last one did
-                        * not match.
                         */
-                       if (!file_ops || call->mod != file_ops->mod)
-                               file_ops = find_ftrace_file_ops(call->mod);
+                       file_ops = find_ftrace_file_ops(file_ops, call->mod);
                        if (!file_ops)
                                continue; /* Warn? */
-                       ret = __trace_add_new_event(call, tr,
-                                       &file_ops->id, &file_ops->enable,
-                                       &file_ops->filter, &file_ops->format);
+                       ret = __trace_add_new_mod_event(call, tr, file_ops);
                        if (ret < 0)
                                pr_warning("Could not create directory for 
event %s\n",
                                           call->name);
@@ -1794,9 +1813,7 @@ __add_event_to_tracers(struct ftrace_event_call *call,
 
        list_for_each_entry(tr, &ftrace_trace_arrays, list) {
                if (file_ops)
-                       __trace_add_new_event(call, tr,
-                                             &file_ops->id, &file_ops->enable,
-                                             &file_ops->filter, 
&file_ops->format);
+                       __trace_add_new_mod_event(call, tr, file_ops);
                else
                        __trace_add_new_event(call, tr,
                                              &ftrace_event_id_fops,
-- 
1.7.10.4


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to