Merge branch 'bkl/core' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[sfrench/cifs-2.6.git] / kernel / trace / trace.c
index d6736b93dc2aed0a1934165cf945012306a2f516..ba14a22be4cc4aca4af73121a09910dcbebaf050 100644 (file)
@@ -341,7 +341,7 @@ static DECLARE_WAIT_QUEUE_HEAD(trace_wait);
 /* trace_flags holds trace_options default values */
 unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
        TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO | TRACE_ITER_SLEEP_TIME |
-       TRACE_ITER_GRAPH_TIME;
+       TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD;
 
 static int trace_stop_count;
 static DEFINE_SPINLOCK(tracing_start_lock);
@@ -425,6 +425,7 @@ static const char *trace_options[] = {
        "latency-format",
        "sleep-time",
        "graph-time",
+       "record-cmd",
        NULL
 };
 
@@ -656,6 +657,10 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
                return;
 
        WARN_ON_ONCE(!irqs_disabled());
+       if (!current_trace->use_max_tr) {
+               WARN_ON_ONCE(1);
+               return;
+       }
        arch_spin_lock(&ftrace_max_lock);
 
        tr->buffer = max_tr.buffer;
@@ -682,6 +687,11 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
                return;
 
        WARN_ON_ONCE(!irqs_disabled());
+       if (!current_trace->use_max_tr) {
+               WARN_ON_ONCE(1);
+               return;
+       }
+
        arch_spin_lock(&ftrace_max_lock);
 
        ftrace_disable_cpu();
@@ -726,18 +736,11 @@ __acquires(kernel_lock)
                return -1;
        }
 
-       if (strlen(type->name) > MAX_TRACER_SIZE) {
+       if (strlen(type->name) >= MAX_TRACER_SIZE) {
                pr_info("Tracer has a name longer than %d\n", MAX_TRACER_SIZE);
                return -1;
        }
 
-       /*
-        * When this gets called we hold the BKL which means that
-        * preemption is disabled. Various trace selftests however
-        * need to disable and enable preemption for successful tests.
-        * So we drop the BKL here and grab it after the tests again.
-        */
-       unlock_kernel();
        mutex_lock(&trace_types_lock);
 
        tracing_selftest_running = true;
@@ -819,7 +822,6 @@ __acquires(kernel_lock)
 #endif
 
  out_unlock:
-       lock_kernel();
        return ret;
 }
 
@@ -1328,61 +1330,6 @@ static void __trace_userstack(struct trace_array *tr, unsigned long flags)
 
 #endif /* CONFIG_STACKTRACE */
 
-static void
-ftrace_trace_special(void *__tr,
-                    unsigned long arg1, unsigned long arg2, unsigned long arg3,
-                    int pc)
-{
-       struct ftrace_event_call *call = &event_special;
-       struct ring_buffer_event *event;
-       struct trace_array *tr = __tr;
-       struct ring_buffer *buffer = tr->buffer;
-       struct special_entry *entry;
-
-       event = trace_buffer_lock_reserve(buffer, TRACE_SPECIAL,
-                                         sizeof(*entry), 0, pc);
-       if (!event)
-               return;
-       entry   = ring_buffer_event_data(event);
-       entry->arg1                     = arg1;
-       entry->arg2                     = arg2;
-       entry->arg3                     = arg3;
-
-       if (!filter_check_discard(call, entry, buffer, event))
-               trace_buffer_unlock_commit(buffer, event, 0, pc);
-}
-
-void
-__trace_special(void *__tr, void *__data,
-               unsigned long arg1, unsigned long arg2, unsigned long arg3)
-{
-       ftrace_trace_special(__tr, arg1, arg2, arg3, preempt_count());
-}
-
-void
-ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3)
-{
-       struct trace_array *tr = &global_trace;
-       struct trace_array_cpu *data;
-       unsigned long flags;
-       int cpu;
-       int pc;
-
-       if (tracing_disabled)
-               return;
-
-       pc = preempt_count();
-       local_irq_save(flags);
-       cpu = raw_smp_processor_id();
-       data = tr->data[cpu];
-
-       if (likely(atomic_inc_return(&data->disabled) == 1))
-               ftrace_trace_special(tr, arg1, arg2, arg3, pc);
-
-       atomic_dec(&data->disabled);
-       local_irq_restore(flags);
-}
-
 /**
  * trace_vbprintk - write binary msg to tracing buffer
  *
@@ -1401,7 +1348,6 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
        struct bprint_entry *entry;
        unsigned long flags;
        int disable;
-       int resched;
        int cpu, len = 0, size, pc;
 
        if (unlikely(tracing_selftest_running || tracing_disabled))
@@ -1411,7 +1357,7 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
        pause_graph_tracing();
 
        pc = preempt_count();
-       resched = ftrace_preempt_disable();
+       preempt_disable_notrace();
        cpu = raw_smp_processor_id();
        data = tr->data[cpu];
 
@@ -1449,7 +1395,7 @@ out_unlock:
 
 out:
        atomic_dec_return(&data->disabled);
-       ftrace_preempt_enable(resched);
+       preempt_enable_notrace();
        unpause_graph_tracing();
 
        return len;
@@ -2386,6 +2332,7 @@ static const struct file_operations show_traces_fops = {
        .open           = show_traces_open,
        .read           = seq_read,
        .release        = seq_release,
+       .llseek         = seq_lseek,
 };
 
 /*
@@ -2479,6 +2426,7 @@ static const struct file_operations tracing_cpumask_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_cpumask_read,
        .write          = tracing_cpumask_write,
+       .llseek         = generic_file_llseek,
 };
 
 static int tracing_trace_options_show(struct seq_file *m, void *v)
@@ -2554,6 +2502,9 @@ static void set_tracer_flags(unsigned int mask, int enabled)
                trace_flags |= mask;
        else
                trace_flags &= ~mask;
+
+       if (mask == TRACE_ITER_RECORD_CMD)
+               trace_event_enable_cmd_record(enabled);
 }
 
 static ssize_t
@@ -2645,6 +2596,7 @@ tracing_readme_read(struct file *filp, char __user *ubuf,
 static const struct file_operations tracing_readme_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_readme_read,
+       .llseek         = generic_file_llseek,
 };
 
 static ssize_t
@@ -2695,6 +2647,7 @@ tracing_saved_cmdlines_read(struct file *file, char __user *ubuf,
 static const struct file_operations tracing_saved_cmdlines_fops = {
     .open       = tracing_open_generic,
     .read       = tracing_saved_cmdlines_read,
+    .llseek    = generic_file_llseek,
 };
 
 static ssize_t
@@ -2790,6 +2743,9 @@ static int tracing_resize_ring_buffer(unsigned long size)
        if (ret < 0)
                return ret;
 
+       if (!current_trace->use_max_tr)
+               goto out;
+
        ret = ring_buffer_resize(max_tr.buffer, size);
        if (ret < 0) {
                int r;
@@ -2817,11 +2773,14 @@ static int tracing_resize_ring_buffer(unsigned long size)
                return ret;
        }
 
+       max_tr.entries = size;
+ out:
        global_trace.entries = size;
 
        return ret;
 }
 
+
 /**
  * tracing_update_buffers - used by tracing facility to expand ring buffers
  *
@@ -2882,12 +2841,26 @@ static int tracing_set_tracer(const char *buf)
        trace_branch_disable();
        if (current_trace && current_trace->reset)
                current_trace->reset(tr);
-
+       if (current_trace && current_trace->use_max_tr) {
+               /*
+                * We don't free the ring buffer. instead, resize it because
+                * The max_tr ring buffer has some state (e.g. ring->clock) and
+                * we want preserve it.
+                */
+               ring_buffer_resize(max_tr.buffer, 1);
+               max_tr.entries = 1;
+       }
        destroy_trace_option_files(topts);
 
        current_trace = t;
 
        topts = create_trace_option_files(current_trace);
+       if (current_trace->use_max_tr) {
+               ret = ring_buffer_resize(max_tr.buffer, global_trace.entries);
+               if (ret < 0)
+                       goto out;
+               max_tr.entries = global_trace.entries;
+       }
 
        if (t->init) {
                ret = tracer_init(t, tr);
@@ -3024,6 +2997,7 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
        if (iter->trace->pipe_open)
                iter->trace->pipe_open(iter);
 
+       nonseekable_open(inode, filp);
 out:
        mutex_unlock(&trace_types_lock);
        return ret;
@@ -3469,7 +3443,6 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
        }
 
        tracing_start();
-       max_tr.entries = global_trace.entries;
        mutex_unlock(&trace_types_lock);
 
        return cnt;
@@ -3582,18 +3555,21 @@ static const struct file_operations tracing_max_lat_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_max_lat_read,
        .write          = tracing_max_lat_write,
+       .llseek         = generic_file_llseek,
 };
 
 static const struct file_operations tracing_ctrl_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_ctrl_read,
        .write          = tracing_ctrl_write,
+       .llseek         = generic_file_llseek,
 };
 
 static const struct file_operations set_tracer_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_set_trace_read,
        .write          = tracing_set_trace_write,
+       .llseek         = generic_file_llseek,
 };
 
 static const struct file_operations tracing_pipe_fops = {
@@ -3602,17 +3578,20 @@ static const struct file_operations tracing_pipe_fops = {
        .read           = tracing_read_pipe,
        .splice_read    = tracing_splice_read_pipe,
        .release        = tracing_release_pipe,
+       .llseek         = no_llseek,
 };
 
 static const struct file_operations tracing_entries_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_entries_read,
        .write          = tracing_entries_write,
+       .llseek         = generic_file_llseek,
 };
 
 static const struct file_operations tracing_mark_fops = {
        .open           = tracing_open_generic,
        .write          = tracing_mark_write,
+       .llseek         = generic_file_llseek,
 };
 
 static const struct file_operations trace_clock_fops = {
@@ -3918,6 +3897,7 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
 static const struct file_operations tracing_stats_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_stats_read,
+       .llseek         = generic_file_llseek,
 };
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -3954,6 +3934,7 @@ tracing_read_dyn_info(struct file *filp, char __user *ubuf,
 static const struct file_operations tracing_dyn_info_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_read_dyn_info,
+       .llseek         = generic_file_llseek,
 };
 #endif
 
@@ -4107,6 +4088,7 @@ static const struct file_operations trace_options_fops = {
        .open = tracing_open_generic,
        .read = trace_options_read,
        .write = trace_options_write,
+       .llseek = generic_file_llseek,
 };
 
 static ssize_t
@@ -4158,6 +4140,7 @@ static const struct file_operations trace_options_core_fops = {
        .open = tracing_open_generic,
        .read = trace_options_core_read,
        .write = trace_options_core_write,
+       .llseek = generic_file_llseek,
 };
 
 struct dentry *trace_create_file(const char *name,
@@ -4347,9 +4330,6 @@ static __init int tracer_init_debugfs(void)
        trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
                        &ftrace_update_tot_cnt, &tracing_dyn_info_fops);
 #endif
-#ifdef CONFIG_SYSPROF_TRACER
-       init_tracer_sysprof_debugfs(d_tracer);
-#endif
 
        create_trace_options_dir();
 
@@ -4576,16 +4556,14 @@ __init static int tracer_alloc_buffers(void)
 
 
 #ifdef CONFIG_TRACER_MAX_TRACE
-       max_tr.buffer = ring_buffer_alloc(ring_buf_size,
-                                            TRACE_BUFFER_FLAGS);
+       max_tr.buffer = ring_buffer_alloc(1, TRACE_BUFFER_FLAGS);
        if (!max_tr.buffer) {
                printk(KERN_ERR "tracer: failed to allocate max ring buffer!\n");
                WARN_ON(1);
                ring_buffer_free(global_trace.buffer);
                goto out_free_cpumask;
        }
-       max_tr.entries = ring_buffer_size(max_tr.buffer);
-       WARN_ON(max_tr.entries != global_trace.entries);
+       max_tr.entries = 1;
 #endif
 
        /* Allocate the first page for all buffers */
@@ -4598,9 +4576,6 @@ __init static int tracer_alloc_buffers(void)
 
        register_tracer(&nop_trace);
        current_trace = &nop_trace;
-#ifdef CONFIG_BOOT_TRACER
-       register_tracer(&boot_tracer);
-#endif
        /* All seems OK, enable tracing */
        tracing_disabled = 0;