From: "Steven Rostedt (Red Hat)" <[email protected]>

Add a enum_map file in the tracing directory to see what enums have been
saved to convert in the print fmt files.

Signed-off-by: Steven Rostedt <[email protected]>
---
 kernel/trace/trace.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 107 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c9a714a42b7b..f2e63d0bf45e 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -123,7 +123,7 @@ enum ftrace_dump_mode ftrace_dump_on_oops;
 /* When set, tracing will stop when a WARN*() is hit */
 int __disable_trace_on_warning;
 
-/* Map of enums to their values */
+/* Map of enums to their values, for "enum_map" file */
 struct trace_enum_map_head {
        struct module                   *mod;
        unsigned long                   length;
@@ -136,10 +136,12 @@ struct trace_enum_map_tail {
         * "end" is first and points to NULL as it must be different
         * than "mod" or "enum_string"
         */
-       const char                      *end;   /* points to NULL */
        union trace_enum_map_item       *next;
+       const char                      *end;   /* points to NULL */
 };
 
+static DEFINE_MUTEX(trace_enum_mutex);
+
 /*
  * The trace_enum_maps are saved in an array with two extra elements,
  * one at the beginning, and one at the end. The beginning item contains
@@ -3940,6 +3942,97 @@ static const struct file_operations 
tracing_saved_cmdlines_size_fops = {
        .write          = tracing_saved_cmdlines_size_write,
 };
 
+static union trace_enum_map_item *
+update_enum_map(union trace_enum_map_item *ptr)
+{
+       if (!ptr->map.enum_string) {
+               if (ptr->tail.next) {
+                       ptr = ptr->tail.next;
+                       /* Set ptr to the next real item (skip head) */
+                       ptr++;
+               } else
+                       return NULL;
+       }
+       return ptr;
+}
+
+static void *enum_map_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       union trace_enum_map_item *ptr = v;
+
+       /*
+        * Paranoid! If ptr points to end, we don't want to increment past it.
+        * This really should never happen.
+        */
+       ptr = update_enum_map(ptr);
+       if (WARN_ON_ONCE(!ptr))
+               return NULL;
+
+       ptr++;
+
+       (*pos)++;
+
+       ptr = update_enum_map(ptr);
+
+       return ptr;
+}
+
+static void *enum_map_start(struct seq_file *m, loff_t *pos)
+{
+       union trace_enum_map_item *v;
+       loff_t l = 0;
+
+       mutex_lock(&trace_enum_mutex);
+
+       v = trace_enum_maps;
+       if (v)
+               v++;
+
+       while (v && l < *pos) {
+               v = enum_map_next(m, v, &l);
+       }
+
+       return v;
+}
+
+static void enum_map_stop(struct seq_file *m, void *v)
+{
+       mutex_unlock(&trace_enum_mutex);
+}
+
+static int enum_map_show(struct seq_file *m, void *v)
+{
+       union trace_enum_map_item *ptr = v;
+
+       seq_printf(m, "%s %ld (%s)\n",
+                  ptr->map.enum_string, ptr->map.enum_value,
+                  ptr->map.system);
+
+       return 0;
+}
+
+static const struct seq_operations tracing_enum_map_seq_ops = {
+       .start          = enum_map_start,
+       .next           = enum_map_next,
+       .stop           = enum_map_stop,
+       .show           = enum_map_show,
+};
+
+static int tracing_enum_map_open(struct inode *inode, struct file *filp)
+{
+       if (tracing_disabled)
+               return -ENODEV;
+
+       return seq_open(filp, &tracing_enum_map_seq_ops);
+}
+
+static const struct file_operations tracing_enum_map_fops = {
+       .open           = tracing_enum_map_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
 static inline union trace_enum_map_item *
 trace_enum_jmp_to_tail(union trace_enum_map_item *ptr)
 {
@@ -3971,6 +4064,8 @@ static void trace_insert_enum_map(struct module *mod,
                return;
        }
 
+       mutex_lock(&trace_enum_mutex);
+
        if (!trace_enum_maps)
                trace_enum_maps = map_array;
        else {
@@ -3996,6 +4091,8 @@ static void trace_insert_enum_map(struct module *mod,
 
        /* Pass in the start of the array (-len) */
        trace_event_enum_update(&map_array[-len].map, len);
+
+       mutex_unlock(&trace_enum_mutex);
 }
 
 static ssize_t
@@ -6667,6 +6764,8 @@ static void trace_module_remove_enums(struct module *mod)
        if (!mod->num_trace_enums)
                return;
 
+       mutex_lock(&trace_enum_mutex);
+
        map = trace_enum_maps;
 
        while (map) {
@@ -6677,10 +6776,12 @@ static void trace_module_remove_enums(struct module 
*mod)
                map = map->tail.next;
        }
        if (!map)
-               return;
+               goto out;
 
        *last = trace_enum_jmp_to_tail(map)->tail.next;
        kfree(map);
+ out:
+       mutex_unlock(&trace_enum_mutex);
 }
 
 static int trace_module_notify(struct notifier_block *self,
@@ -6732,6 +6833,9 @@ static __init int tracer_init_debugfs(void)
 
        trace_enum_init();
 
+       trace_create_file("enum_map", 0444, d_tracer,
+                         NULL, &tracing_enum_map_fops);
+
 #ifdef CONFIG_MODULES
        register_module_notifier(&trace_module_nb);
 #endif
-- 
2.1.4


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
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