Merge tag 'trace-probes-v6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[sfrench/cifs-2.6.git] / kernel / trace / trace.c
index 9ee519ad164e90b1c09a812440e812742ea3d5c7..a555a861b97811b31f833d483cab0539f379258f 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/kallsyms.h>
 #include <linux/security.h>
 #include <linux/seq_file.h>
-#include <linux/notifier.h>
 #include <linux/irqflags.h>
 #include <linux/debugfs.h>
 #include <linux/tracefs.h>
@@ -85,7 +84,7 @@ void __init disable_tracing_selftest(const char *reason)
 #endif
 
 /* Pipe tracepoints to printk */
-struct trace_iterator *tracepoint_print_iter;
+static struct trace_iterator *tracepoint_print_iter;
 int tracepoint_printk;
 static bool tracepoint_printk_stop_on_boot __initdata;
 static DEFINE_STATIC_KEY_FALSE(tracepoint_printk_key);
@@ -999,7 +998,7 @@ __buffer_unlock_commit(struct trace_buffer *buffer, struct ring_buffer_event *ev
                /* ring_buffer_unlock_commit() enables preemption */
                preempt_enable_notrace();
        } else
-               ring_buffer_unlock_commit(buffer, event);
+               ring_buffer_unlock_commit(buffer);
 }
 
 /**
@@ -1421,6 +1420,7 @@ int tracing_snapshot_cond_disable(struct trace_array *tr)
        return false;
 }
 EXPORT_SYMBOL_GPL(tracing_snapshot_cond_disable);
+#define free_snapshot(tr)      do { } while (0)
 #endif /* CONFIG_TRACER_SNAPSHOT */
 
 void tracer_tracing_off(struct trace_array *tr)
@@ -1692,6 +1692,8 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
 }
 
 unsigned long __read_mostly    tracing_thresh;
+
+#ifdef CONFIG_TRACER_MAX_TRACE
 static const struct file_operations tracing_max_lat_fops;
 
 #ifdef LATENCY_FS_NOTIFY
@@ -1748,18 +1750,14 @@ void latency_fsnotify(struct trace_array *tr)
        irq_work_queue(&tr->fsnotify_irqwork);
 }
 
-#elif defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER) \
-       || defined(CONFIG_OSNOISE_TRACER)
+#else /* !LATENCY_FS_NOTIFY */
 
 #define trace_create_maxlat_file(tr, d_tracer)                         \
        trace_create_file("tracing_max_latency", TRACE_MODE_WRITE,      \
                          d_tracer, &tr->max_latency, &tracing_max_lat_fops)
 
-#else
-#define trace_create_maxlat_file(tr, d_tracer)  do { } while (0)
 #endif
 
-#ifdef CONFIG_TRACER_MAX_TRACE
 /*
  * Copy the new maximum trace into the separate maximum-trace
  * structure. (this way the maximum trace is permanently saved,
@@ -1834,14 +1832,15 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu,
                ring_buffer_record_off(tr->max_buffer.buffer);
 
 #ifdef CONFIG_TRACER_SNAPSHOT
-       if (tr->cond_snapshot && !tr->cond_snapshot->update(tr, cond_data))
-               goto out_unlock;
+       if (tr->cond_snapshot && !tr->cond_snapshot->update(tr, cond_data)) {
+               arch_spin_unlock(&tr->max_lock);
+               return;
+       }
 #endif
        swap(tr->array_buffer.buffer, tr->max_buffer.buffer);
 
        __update_max_tr(tr, tsk, cpu);
 
- out_unlock:
        arch_spin_unlock(&tr->max_lock);
 }
 
@@ -1888,6 +1887,7 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
        __update_max_tr(tr, tsk, cpu);
        arch_spin_unlock(&tr->max_lock);
 }
+
 #endif /* CONFIG_TRACER_MAX_TRACE */
 
 static int wait_on_pipe(struct trace_iterator *iter, int full)
@@ -2180,10 +2180,12 @@ void tracing_reset_online_cpus(struct array_buffer *buf)
 }
 
 /* Must have trace_types_lock held */
-void tracing_reset_all_online_cpus(void)
+void tracing_reset_all_online_cpus_unlocked(void)
 {
        struct trace_array *tr;
 
+       lockdep_assert_held(&trace_types_lock);
+
        list_for_each_entry(tr, &ftrace_trace_arrays, list) {
                if (!tr->clear_trace)
                        continue;
@@ -2195,6 +2197,13 @@ void tracing_reset_all_online_cpus(void)
        }
 }
 
+void tracing_reset_all_online_cpus(void)
+{
+       mutex_lock(&trace_types_lock);
+       tracing_reset_all_online_cpus_unlocked();
+       mutex_unlock(&trace_types_lock);
+}
+
 /*
  * The tgid_map array maps from pid to tgid; i.e. the value stored at index i
  * is the tgid last observed corresponding to pid=i.
@@ -5669,6 +5678,7 @@ static const char readme_msg[] =
        "\t            [:size=#entries]\n"
        "\t            [:pause][:continue][:clear]\n"
        "\t            [:name=histname1]\n"
+       "\t            [:nohitcount]\n"
        "\t            [:<handler>.<action>]\n"
        "\t            [if <filter>]\n\n"
        "\t    Note, special fields can be used as well:\n"
@@ -5715,7 +5725,9 @@ static const char readme_msg[] =
        "\t            .syscall    display a syscall id as a syscall name\n"
        "\t            .log2       display log2 value rather than raw number\n"
        "\t            .buckets=size  display values in groups of size rather than raw number\n"
-       "\t            .usecs      display a common_timestamp in microseconds\n\n"
+       "\t            .usecs      display a common_timestamp in microseconds\n"
+       "\t            .percent    display a number of percentage value\n"
+       "\t            .graph      display a bar-graph of a value\n\n"
        "\t    The 'pause' parameter can be used to pause an existing hist\n"
        "\t    trigger or to start a hist trigger but not log any events\n"
        "\t    until told to do so.  'continue' can be used to start or\n"
@@ -5723,6 +5735,8 @@ static const char readme_msg[] =
        "\t    The 'clear' parameter will clear the contents of a running\n"
        "\t    hist trigger and leave its current paused/active state\n"
        "\t    unchanged.\n\n"
+       "\t    The 'nohitcount' (or NOHC) parameter will suppress display of\n"
+       "\t    raw hitcount in the histogram.\n\n"
        "\t    The enable_hist and disable_hist triggers can be used to\n"
        "\t    have one event conditionally start and stop another event's\n"
        "\t    already-attached hist trigger.  The syntax is analogous to\n"
@@ -6563,7 +6577,7 @@ out:
        return ret;
 }
 
-#if defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER)
+#ifdef CONFIG_TRACER_MAX_TRACE
 
 static ssize_t
 tracing_max_lat_read(struct file *filp, char __user *ubuf,
@@ -6657,6 +6671,7 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
        mutex_unlock(&trace_types_lock);
 
        free_cpumask_var(iter->started);
+       kfree(iter->fmt);
        mutex_destroy(&iter->mutex);
        kfree(iter);
 
@@ -6786,7 +6801,20 @@ waitagain:
 
                ret = print_trace_line(iter);
                if (ret == TRACE_TYPE_PARTIAL_LINE) {
-                       /* don't print partial lines */
+                       /*
+                        * If one print_trace_line() fills entire trace_seq in one shot,
+                        * trace_seq_to_user() will returns -EBUSY because save_len == 0,
+                        * In this case, we need to consume it, otherwise, loop will peek
+                        * this event next time, resulting in an infinite loop.
+                        */
+                       if (save_len == 0) {
+                               iter->seq.full = 0;
+                               trace_seq_puts(&iter->seq, "[LINE TOO BIG]\n");
+                               trace_consume(iter);
+                               break;
+                       }
+
+                       /* In other cases, don't print partial lines */
                        iter->seq.seq.len = save_len;
                        break;
                }
@@ -7577,7 +7605,7 @@ static const struct file_operations tracing_thresh_fops = {
        .llseek         = generic_file_llseek,
 };
 
-#if defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER)
+#ifdef CONFIG_TRACER_MAX_TRACE
 static const struct file_operations tracing_max_lat_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_max_lat_read,
@@ -7802,6 +7830,7 @@ static struct tracing_log_err *get_tracing_log_err(struct trace_array *tr,
                                                   int len)
 {
        struct tracing_log_err *err;
+       char *cmd;
 
        if (tr->n_err_log_entries < TRACING_LOG_ERRS_MAX) {
                err = alloc_tracing_log_err(len);
@@ -7810,12 +7839,12 @@ static struct tracing_log_err *get_tracing_log_err(struct trace_array *tr,
 
                return err;
        }
-
+       cmd = kzalloc(len, GFP_KERNEL);
+       if (!cmd)
+               return ERR_PTR(-ENOMEM);
        err = list_first_entry(&tr->err_log, struct tracing_log_err, list);
        kfree(err->cmd);
-       err->cmd = kzalloc(len, GFP_KERNEL);
-       if (!err->cmd)
-               return ERR_PTR(-ENOMEM);
+       err->cmd = cmd;
        list_del(&err->list);
 
        return err;
@@ -9590,7 +9619,9 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer)
 
        create_trace_options_dir(tr);
 
+#ifdef CONFIG_TRACER_MAX_TRACE
        trace_create_maxlat_file(tr, d_tracer);
+#endif
 
        if (ftrace_create_function_files(tr, d_tracer))
                MEM_FAIL(1, "Could not allocate function filter files");
@@ -9844,40 +9875,40 @@ static __init int tracer_init_tracefs(void)
 
 fs_initcall(tracer_init_tracefs);
 
-static int trace_panic_handler(struct notifier_block *this,
-                              unsigned long event, void *unused)
-{
-       if (ftrace_dump_on_oops)
-               ftrace_dump(ftrace_dump_on_oops);
-       return NOTIFY_OK;
-}
+static int trace_die_panic_handler(struct notifier_block *self,
+                               unsigned long ev, void *unused);
 
 static struct notifier_block trace_panic_notifier = {
-       .notifier_call  = trace_panic_handler,
-       .next           = NULL,
-       .priority       = 150   /* priority: INT_MAX >= x >= 0 */
+       .notifier_call = trace_die_panic_handler,
+       .priority = INT_MAX - 1,
 };
 
-static int trace_die_handler(struct notifier_block *self,
-                            unsigned long val,
-                            void *data)
-{
-       switch (val) {
-       case DIE_OOPS:
-               if (ftrace_dump_on_oops)
-                       ftrace_dump(ftrace_dump_on_oops);
-               break;
-       default:
-               break;
-       }
-       return NOTIFY_OK;
-}
-
 static struct notifier_block trace_die_notifier = {
-       .notifier_call = trace_die_handler,
-       .priority = 200
+       .notifier_call = trace_die_panic_handler,
+       .priority = INT_MAX - 1,
 };
 
+/*
+ * The idea is to execute the following die/panic callback early, in order
+ * to avoid showing irrelevant information in the trace (like other panic
+ * notifier functions); we are the 2nd to run, after hung_task/rcu_stall
+ * warnings get disabled (to prevent potential log flooding).
+ */
+static int trace_die_panic_handler(struct notifier_block *self,
+                               unsigned long ev, void *unused)
+{
+       if (!ftrace_dump_on_oops)
+               return NOTIFY_DONE;
+
+       /* The die notifier requires DIE_OOPS to trigger */
+       if (self == &trace_die_notifier && ev != DIE_OOPS)
+               return NOTIFY_DONE;
+
+       ftrace_dump(ftrace_dump_on_oops);
+
+       return NOTIFY_DONE;
+}
+
 /*
  * printk is set to max of 1024, we really don't need it that big.
  * Nothing should be printing 1000 characters anyway.