tracing: Make the snapshot trigger work with instances
authorSteven Rostedt (VMware) <rostedt@goodmis.org>
Mon, 28 May 2018 14:56:36 +0000 (10:56 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Jun 2018 09:41:56 +0000 (11:41 +0200)
commit 2824f5033248600673e3e126a4d135363cbfd9ac upstream.

The snapshot trigger currently only affects the main ring buffer, even when
it is used by the instances. This can be confusing as the snapshot trigger
is listed in the instance.

 > # cd /sys/kernel/tracing
 > # mkdir instances/foo
 > # echo snapshot > instances/foo/events/syscalls/sys_enter_fchownat/trigger
 > # echo top buffer > trace_marker
 > # echo foo buffer > instances/foo/trace_marker
 > # touch /tmp/bar
 > # chown rostedt /tmp/bar
 > # cat instances/foo/snapshot
 # tracer: nop
 #
 #
 # * Snapshot is freed *
 #
 # Snapshot commands:
 # echo 0 > snapshot : Clears and frees snapshot buffer
 # echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.
 #                      Takes a snapshot of the main buffer.
 # echo 2 > snapshot : Clears snapshot buffer (but does not allocate or free)
 #                      (Doesn't have to be '2' works with any number that
 #                       is not a '0' or '1')

 > # cat snapshot
 # tracer: nop
 #
 #                              _-----=> irqs-off
 #                             / _----=> need-resched
 #                            | / _---=> hardirq/softirq
 #                            || / _--=> preempt-depth
 #                            ||| /     delay
 #           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION
 #              | |       |   ||||       |         |
             bash-1189  [000] ....   111.488323: tracing_mark_write: top buffer

Not only did the snapshot occur in the top level buffer, but the instance
snapshot buffer should have been allocated, and it is still free.

Cc: stable@vger.kernel.org
Fixes: 85f2b08268c01 ("tracing: Add basic event trigger framework")
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events_trigger.c

index 76bcc80b893ebc15868defc6d6b0af253c07ad57..520ecaf61dc4f736d4c9d07e912a1e01a938a698 100644 (file)
@@ -894,7 +894,7 @@ int __trace_bputs(unsigned long ip, const char *str)
 EXPORT_SYMBOL_GPL(__trace_bputs);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
-static void tracing_snapshot_instance(struct trace_array *tr)
+void tracing_snapshot_instance(struct trace_array *tr)
 {
        struct tracer *tracer = tr->current_trace;
        unsigned long flags;
@@ -950,7 +950,7 @@ static int resize_buffer_duplicate_size(struct trace_buffer *trace_buf,
                                        struct trace_buffer *size_buf, int cpu_id);
 static void set_buffer_entries(struct trace_buffer *buf, unsigned long val);
 
-static int alloc_snapshot(struct trace_array *tr)
+int tracing_alloc_snapshot_instance(struct trace_array *tr)
 {
        int ret;
 
@@ -996,7 +996,7 @@ int tracing_alloc_snapshot(void)
        struct trace_array *tr = &global_trace;
        int ret;
 
-       ret = alloc_snapshot(tr);
+       ret = tracing_alloc_snapshot_instance(tr);
        WARN_ON(ret < 0);
 
        return ret;
@@ -5400,7 +5400,7 @@ static int tracing_set_tracer(struct trace_array *tr, const char *buf)
 
 #ifdef CONFIG_TRACER_MAX_TRACE
        if (t->use_max_tr && !had_max_tr) {
-               ret = alloc_snapshot(tr);
+               ret = tracing_alloc_snapshot_instance(tr);
                if (ret < 0)
                        goto out;
        }
@@ -6378,7 +6378,7 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
                }
 #endif
                if (!tr->allocated_snapshot) {
-                       ret = alloc_snapshot(tr);
+                       ret = tracing_alloc_snapshot_instance(tr);
                        if (ret < 0)
                                break;
                }
@@ -7099,7 +7099,7 @@ ftrace_trace_snapshot_callback(struct trace_array *tr, struct ftrace_hash *hash,
                return ret;
 
  out_reg:
-       ret = alloc_snapshot(tr);
+       ret = tracing_alloc_snapshot_instance(tr);
        if (ret < 0)
                goto out;
 
index 401b0639116f216c78b3dad0ad663c9e74858d52..851cd1605085774f21e85eaafeb09047fe87dce7 100644 (file)
@@ -1807,6 +1807,17 @@ static inline void __init trace_event_init(void) { }
 static inline void trace_event_eval_update(struct trace_eval_map **map, int len) { }
 #endif
 
+#ifdef CONFIG_TRACER_SNAPSHOT
+void tracing_snapshot_instance(struct trace_array *tr);
+int tracing_alloc_snapshot_instance(struct trace_array *tr);
+#else
+static inline void tracing_snapshot_instance(struct trace_array *tr) { }
+static inline int tracing_alloc_snapshot_instance(struct trace_array *tr)
+{
+       return 0;
+}
+#endif
+
 extern struct trace_iterator *tracepoint_print_iter;
 
 #endif /* _LINUX_KERNEL_TRACE_H */
index c7c12f82095c2ead6bf871a87e6ec47038f44c08..b413fab7d75becb63fec1e9c795e135463ee552c 100644 (file)
@@ -642,6 +642,7 @@ event_trigger_callback(struct event_command *cmd_ops,
        trigger_data->count = -1;
        trigger_data->ops = trigger_ops;
        trigger_data->cmd_ops = cmd_ops;
+       trigger_data->private_data = file;
        INIT_LIST_HEAD(&trigger_data->list);
        INIT_LIST_HEAD(&trigger_data->named_list);
 
@@ -1042,7 +1043,12 @@ static struct event_command trigger_traceoff_cmd = {
 static void
 snapshot_trigger(struct event_trigger_data *data, void *rec)
 {
-       tracing_snapshot();
+       struct trace_event_file *file = data->private_data;
+
+       if (file)
+               tracing_snapshot_instance(file->tr);
+       else
+               tracing_snapshot();
 }
 
 static void
@@ -1064,7 +1070,7 @@ register_snapshot_trigger(char *glob, struct event_trigger_ops *ops,
 {
        int ret = register_trigger(glob, ops, data, file);
 
-       if (ret > 0 && tracing_alloc_snapshot() != 0) {
+       if (ret > 0 && tracing_alloc_snapshot_instance(file->tr) != 0) {
                unregister_trigger(glob, ops, data, file);
                ret = 0;
        }