locking: Convert raw_spinlock to arch_spinlock
[safe/jmp/linux-2.6] / kernel / trace / trace.c
index 962e617..7d56cec 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/writeback.h>
 #include <linux/kallsyms.h>
 #include <linux/seq_file.h>
+#include <linux/smp_lock.h>
 #include <linux/notifier.h>
 #include <linux/irqflags.h>
 #include <linux/debugfs.h>
 
 #define TRACE_BUFFER_FLAGS     (RB_FL_OVERWRITE)
 
-unsigned long __read_mostly    tracing_max_latency;
-unsigned long __read_mostly    tracing_thresh;
-
 /*
  * On boot up, the ring buffer is set to the minimum size, so that
  * we do not waste memory on systems that are not using tracing.
  */
-static int ring_buffer_expanded;
+int ring_buffer_expanded;
 
 /*
  * We need to change this state when a selftest is running.
@@ -63,7 +61,7 @@ static bool __read_mostly tracing_selftest_running;
 /*
  * If a tracer is running, we do not want to run SELFTEST.
  */
-static bool __read_mostly tracing_selftest_disabled;
+bool __read_mostly tracing_selftest_disabled;
 
 /* For tracers that don't implement custom flags */
 static struct tracer_opt dummy_tracer_opt[] = {
@@ -88,17 +86,17 @@ static int dummy_set_flag(u32 old_flags, u32 bit, int set)
  */
 static int tracing_disabled = 1;
 
-static DEFINE_PER_CPU(local_t, ftrace_cpu_disabled);
+DEFINE_PER_CPU(int, ftrace_cpu_disabled);
 
 static inline void ftrace_disable_cpu(void)
 {
        preempt_disable();
-       local_inc(&__get_cpu_var(ftrace_cpu_disabled));
+       __this_cpu_inc(per_cpu_var(ftrace_cpu_disabled));
 }
 
 static inline void ftrace_enable_cpu(void)
 {
-       local_dec(&__get_cpu_var(ftrace_cpu_disabled));
+       __this_cpu_dec(per_cpu_var(ftrace_cpu_disabled));
        preempt_enable();
 }
 
@@ -127,19 +125,19 @@ int ftrace_dump_on_oops;
 
 static int tracing_set_tracer(const char *buf);
 
-#define BOOTUP_TRACER_SIZE             100
-static char bootup_tracer_buf[BOOTUP_TRACER_SIZE] __initdata;
+#define MAX_TRACER_SIZE                100
+static char bootup_tracer_buf[MAX_TRACER_SIZE] __initdata;
 static char *default_bootup_tracer;
 
-static int __init set_ftrace(char *str)
+static int __init set_cmdline_ftrace(char *str)
 {
-       strncpy(bootup_tracer_buf, str, BOOTUP_TRACER_SIZE);
+       strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
        default_bootup_tracer = bootup_tracer_buf;
        /* We are using ftrace early, expand it */
        ring_buffer_expanded = 1;
        return 1;
 }
-__setup("ftrace=", set_ftrace);
+__setup("ftrace=", set_cmdline_ftrace);
 
 static int __init set_ftrace_dump_on_oops(char *str)
 {
@@ -171,6 +169,14 @@ static struct trace_array  global_trace;
 
 static DEFINE_PER_CPU(struct trace_array_cpu, global_trace_cpu);
 
+int filter_current_check_discard(struct ring_buffer *buffer,
+                                struct ftrace_event_call *call, void *rec,
+                                struct ring_buffer_event *event)
+{
+       return filter_check_discard(call, rec, buffer, event);
+}
+EXPORT_SYMBOL_GPL(filter_current_check_discard);
+
 cycle_t ftrace_now(int cpu)
 {
        u64 ts;
@@ -197,7 +203,7 @@ cycle_t ftrace_now(int cpu)
  */
 static struct trace_array      max_tr;
 
-static DEFINE_PER_CPU(struct trace_array_cpu, max_data);
+static DEFINE_PER_CPU(struct trace_array_cpu, max_tr_data);
 
 /* tracer_enabled is used to toggle activation of a tracer */
 static int                     tracer_enabled = 1;
@@ -236,13 +242,6 @@ static struct tracer               *trace_types __read_mostly;
 static struct tracer           *current_trace __read_mostly;
 
 /*
- * max_tracer_type_len is used to simplify the allocating of
- * buffers to read userspace tracer names. We keep track of
- * the longest tracer name registered.
- */
-static int                     max_tracer_type_len;
-
-/*
  * trace_types_lock is used to protect the trace_types list.
  * This lock is also used to keep user access serialized.
  * Accesses from userspace will grab this lock while userspace
@@ -258,6 +257,9 @@ 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;
 
+static int trace_stop_count;
+static DEFINE_SPINLOCK(tracing_start_lock);
+
 /**
  * trace_wake_up - wake up tasks waiting for trace input
  *
@@ -266,24 +268,29 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
  */
 void trace_wake_up(void)
 {
+       int cpu;
+
+       if (trace_flags & TRACE_ITER_BLOCK)
+               return;
        /*
         * The runqueue_is_locked() can fail, but this is the best we
         * have for now:
         */
-       if (!(trace_flags & TRACE_ITER_BLOCK) && !runqueue_is_locked())
+       cpu = get_cpu();
+       if (!runqueue_is_locked(cpu))
                wake_up(&trace_wait);
+       put_cpu();
 }
 
 static int __init set_buf_size(char *str)
 {
        unsigned long buf_size;
-       int ret;
 
        if (!str)
                return 0;
-       ret = strict_strtoul(str, 0, &buf_size);
+       buf_size = memparse(str, &str);
        /* nr_entries can not be zero */
-       if (ret < 0 || buf_size == 0)
+       if (buf_size == 0)
                return 0;
        trace_buf_size = buf_size;
        return 1;
@@ -316,49 +323,125 @@ static const char *trace_options[] = {
        "printk-msg-only",
        "context-info",
        "latency-format",
-       "global-clock",
        "sleep-time",
        "graph-time",
        NULL
 };
 
+static struct {
+       u64 (*func)(void);
+       const char *name;
+} trace_clocks[] = {
+       { trace_clock_local,    "local" },
+       { trace_clock_global,   "global" },
+};
+
+int trace_clock_id;
+
 /*
- * ftrace_max_lock is used to protect the swapping of buffers
- * when taking a max snapshot. The buffers themselves are
- * protected by per_cpu spinlocks. But the action of the swap
- * needs its own lock.
- *
- * This is defined as a raw_spinlock_t in order to help
- * with performance when lockdep debugging is enabled.
+ * trace_parser_get_init - gets the buffer for trace parser
+ */
+int trace_parser_get_init(struct trace_parser *parser, int size)
+{
+       memset(parser, 0, sizeof(*parser));
+
+       parser->buffer = kmalloc(size, GFP_KERNEL);
+       if (!parser->buffer)
+               return 1;
+
+       parser->size = size;
+       return 0;
+}
+
+/*
+ * trace_parser_put - frees the buffer for trace parser
  */
-static raw_spinlock_t ftrace_max_lock =
-       (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+void trace_parser_put(struct trace_parser *parser)
+{
+       kfree(parser->buffer);
+}
 
 /*
- * Copy the new maximum trace into the separate maximum-trace
- * structure. (this way the maximum trace is permanently saved,
- * for later retrieval via /debugfs/tracing/latency_trace)
+ * trace_get_user - reads the user input string separated by  space
+ * (matched by isspace(ch))
+ *
+ * For each string found the 'struct trace_parser' is updated,
+ * and the function returns.
+ *
+ * Returns number of bytes read.
+ *
+ * See kernel/trace/trace.h for 'struct trace_parser' details.
  */
-static void
-__update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
+int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
+       size_t cnt, loff_t *ppos)
 {
-       struct trace_array_cpu *data = tr->data[cpu];
+       char ch;
+       size_t read = 0;
+       ssize_t ret;
 
-       max_tr.cpu = cpu;
-       max_tr.time_start = data->preempt_timestamp;
+       if (!*ppos)
+               trace_parser_clear(parser);
 
-       data = max_tr.data[cpu];
-       data->saved_latency = tracing_max_latency;
+       ret = get_user(ch, ubuf++);
+       if (ret)
+               goto out;
 
-       memcpy(data->comm, tsk->comm, TASK_COMM_LEN);
-       data->pid = tsk->pid;
-       data->uid = task_uid(tsk);
-       data->nice = tsk->static_prio - 20 - MAX_RT_PRIO;
-       data->policy = tsk->policy;
-       data->rt_priority = tsk->rt_priority;
+       read++;
+       cnt--;
 
-       /* record this tasks comm */
-       tracing_record_cmdline(tsk);
+       /*
+        * The parser is not finished with the last write,
+        * continue reading the user input without skipping spaces.
+        */
+       if (!parser->cont) {
+               /* skip white space */
+               while (cnt && isspace(ch)) {
+                       ret = get_user(ch, ubuf++);
+                       if (ret)
+                               goto out;
+                       read++;
+                       cnt--;
+               }
+
+               /* only spaces were written */
+               if (isspace(ch)) {
+                       *ppos += read;
+                       ret = read;
+                       goto out;
+               }
+
+               parser->idx = 0;
+       }
+
+       /* read the non-space input */
+       while (cnt && !isspace(ch)) {
+               if (parser->idx < parser->size - 1)
+                       parser->buffer[parser->idx++] = ch;
+               else {
+                       ret = -EINVAL;
+                       goto out;
+               }
+               ret = get_user(ch, ubuf++);
+               if (ret)
+                       goto out;
+               read++;
+               cnt--;
+       }
+
+       /* We either got finished input or we have to wait for another call. */
+       if (isspace(ch)) {
+               parser->buffer[parser->idx] = 0;
+               parser->cont = false;
+       } else {
+               parser->cont = true;
+               parser->buffer[parser->idx++] = ch;
+       }
+
+       *ppos += read;
+       ret = read;
+
+out:
+       return ret;
 }
 
 ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt)
@@ -404,6 +487,56 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
        return cnt;
 }
 
+/*
+ * ftrace_max_lock is used to protect the swapping of buffers
+ * when taking a max snapshot. The buffers themselves are
+ * protected by per_cpu spinlocks. But the action of the swap
+ * needs its own lock.
+ *
+ * This is defined as a arch_spinlock_t in order to help
+ * with performance when lockdep debugging is enabled.
+ *
+ * It is also used in other places outside the update_max_tr
+ * so it needs to be defined outside of the
+ * CONFIG_TRACER_MAX_TRACE.
+ */
+static arch_spinlock_t ftrace_max_lock =
+       (arch_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+
+#ifdef CONFIG_TRACER_MAX_TRACE
+unsigned long __read_mostly    tracing_max_latency;
+unsigned long __read_mostly    tracing_thresh;
+
+/*
+ * Copy the new maximum trace into the separate maximum-trace
+ * structure. (this way the maximum trace is permanently saved,
+ * for later retrieval via /sys/kernel/debug/tracing/latency_trace)
+ */
+static void
+__update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
+{
+       struct trace_array_cpu *data = tr->data[cpu];
+       struct trace_array_cpu *max_data = tr->data[cpu];
+
+       max_tr.cpu = cpu;
+       max_tr.time_start = data->preempt_timestamp;
+
+       max_data = max_tr.data[cpu];
+       max_data->saved_latency = tracing_max_latency;
+       max_data->critical_start = data->critical_start;
+       max_data->critical_end = data->critical_end;
+
+       memcpy(data->comm, tsk->comm, TASK_COMM_LEN);
+       max_data->pid = tsk->pid;
+       max_data->uid = task_uid(tsk);
+       max_data->nice = tsk->static_prio - 20 - MAX_RT_PRIO;
+       max_data->policy = tsk->policy;
+       max_data->rt_priority = tsk->rt_priority;
+
+       /* record this tasks comm */
+       tracing_record_cmdline(tsk);
+}
+
 /**
  * update_max_tr - snapshot all trace buffers from global_trace to max_tr
  * @tr: tracer
@@ -418,16 +551,15 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
 {
        struct ring_buffer *buf = tr->buffer;
 
+       if (trace_stop_count)
+               return;
+
        WARN_ON_ONCE(!irqs_disabled());
        __raw_spin_lock(&ftrace_max_lock);
 
        tr->buffer = max_tr.buffer;
        max_tr.buffer = buf;
 
-       ftrace_disable_cpu();
-       ring_buffer_reset(tr->buffer);
-       ftrace_enable_cpu();
-
        __update_max_tr(tr, tsk, cpu);
        __raw_spin_unlock(&ftrace_max_lock);
 }
@@ -445,21 +577,35 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 {
        int ret;
 
+       if (trace_stop_count)
+               return;
+
        WARN_ON_ONCE(!irqs_disabled());
        __raw_spin_lock(&ftrace_max_lock);
 
        ftrace_disable_cpu();
 
-       ring_buffer_reset(max_tr.buffer);
        ret = ring_buffer_swap_cpu(max_tr.buffer, tr->buffer, cpu);
 
+       if (ret == -EBUSY) {
+               /*
+                * We failed to swap the buffer due to a commit taking
+                * place on this CPU. We fail to record, but we reset
+                * the max trace buffer (no one writes directly to it)
+                * and flag that it failed.
+                */
+               trace_array_printk(&max_tr, _THIS_IP_,
+                       "Failed to swap buffers due to commit in progress\n");
+       }
+
        ftrace_enable_cpu();
 
-       WARN_ON_ONCE(ret && ret != -EAGAIN);
+       WARN_ON_ONCE(ret && ret != -EAGAIN && ret != -EBUSY);
 
        __update_max_tr(tr, tsk, cpu);
        __raw_spin_unlock(&ftrace_max_lock);
 }
+#endif /* CONFIG_TRACER_MAX_TRACE */
 
 /**
  * register_tracer - register a tracer with the ftrace system.
@@ -472,7 +618,6 @@ __releases(kernel_lock)
 __acquires(kernel_lock)
 {
        struct tracer *t;
-       int len;
        int ret = 0;
 
        if (!type->name) {
@@ -480,6 +625,11 @@ __acquires(kernel_lock)
                return -1;
        }
 
+       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
@@ -494,7 +644,7 @@ __acquires(kernel_lock)
        for (t = trace_types; t; t = t->next) {
                if (strcmp(type->name, t->name) == 0) {
                        /* already found */
-                       pr_info("Trace %s already registered\n",
+                       pr_info("Tracer %s already registered\n",
                                type->name);
                        ret = -1;
                        goto out;
@@ -516,7 +666,6 @@ __acquires(kernel_lock)
        if (type->selftest && !tracing_selftest_disabled) {
                struct tracer *saved_tracer = current_trace;
                struct trace_array *tr = &global_trace;
-               int i;
 
                /*
                 * Run a selftest on this tracer.
@@ -525,8 +674,7 @@ __acquires(kernel_lock)
                 * internal tracing to verify that everything is in order.
                 * If we fail, we do not register this tracer.
                 */
-               for_each_tracing_cpu(i)
-                       tracing_reset(tr, i);
+               tracing_reset_online_cpus(tr);
 
                current_trace = type;
                /* the test is responsible for initializing and enabling */
@@ -539,8 +687,7 @@ __acquires(kernel_lock)
                        goto out;
                }
                /* Only reset on passing, to avoid touching corrupted buffers */
-               for_each_tracing_cpu(i)
-                       tracing_reset(tr, i);
+               tracing_reset_online_cpus(tr);
 
                printk(KERN_CONT "PASSED\n");
        }
@@ -548,9 +695,6 @@ __acquires(kernel_lock)
 
        type->next = trace_types;
        trace_types = type;
-       len = strlen(type->name);
-       if (len > max_tracer_type_len)
-               max_tracer_type_len = len;
 
  out:
        tracing_selftest_running = false;
@@ -559,7 +703,7 @@ __acquires(kernel_lock)
        if (ret || !default_bootup_tracer)
                goto out_unlock;
 
-       if (strncmp(default_bootup_tracer, type->name, BOOTUP_TRACER_SIZE))
+       if (strncmp(default_bootup_tracer, type->name, MAX_TRACER_SIZE))
                goto out_unlock;
 
        printk(KERN_INFO "Starting tracer '%s'\n", type->name);
@@ -581,14 +725,13 @@ __acquires(kernel_lock)
 void unregister_tracer(struct tracer *type)
 {
        struct tracer **t;
-       int len;
 
        mutex_lock(&trace_types_lock);
        for (t = &trace_types; *t; t = &(*t)->next) {
                if (*t == type)
                        goto found;
        }
-       pr_info("Trace %s not registered\n", type->name);
+       pr_info("Tracer %s not registered\n", type->name);
        goto out;
 
  found:
@@ -601,35 +744,56 @@ void unregister_tracer(struct tracer *type)
                        current_trace->stop(&global_trace);
                current_trace = &nop_trace;
        }
-
-       if (strlen(type->name) != max_tracer_type_len)
-               goto out;
-
-       max_tracer_type_len = 0;
-       for (t = &trace_types; *t; t = &(*t)->next) {
-               len = strlen((*t)->name);
-               if (len > max_tracer_type_len)
-                       max_tracer_type_len = len;
-       }
- out:
+out:
        mutex_unlock(&trace_types_lock);
 }
 
-void tracing_reset(struct trace_array *tr, int cpu)
+static void __tracing_reset(struct trace_array *tr, int cpu)
 {
        ftrace_disable_cpu();
        ring_buffer_reset_cpu(tr->buffer, cpu);
        ftrace_enable_cpu();
 }
 
+void tracing_reset(struct trace_array *tr, int cpu)
+{
+       struct ring_buffer *buffer = tr->buffer;
+
+       ring_buffer_record_disable(buffer);
+
+       /* Make sure all commits have finished */
+       synchronize_sched();
+       __tracing_reset(tr, cpu);
+
+       ring_buffer_record_enable(buffer);
+}
+
 void tracing_reset_online_cpus(struct trace_array *tr)
 {
+       struct ring_buffer *buffer = tr->buffer;
        int cpu;
 
+       ring_buffer_record_disable(buffer);
+
+       /* Make sure all commits have finished */
+       synchronize_sched();
+
        tr->time_start = ftrace_now(tr->cpu);
 
        for_each_online_cpu(cpu)
-               tracing_reset(tr, cpu);
+               __tracing_reset(tr, cpu);
+
+       ring_buffer_record_enable(buffer);
+}
+
+void tracing_reset_current(int cpu)
+{
+       tracing_reset(&global_trace, cpu);
+}
+
+void tracing_reset_current_online_cpus(void)
+{
+       tracing_reset_online_cpus(&global_trace);
 }
 
 #define SAVED_CMDLINES 128
@@ -638,7 +802,7 @@ static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1];
 static unsigned map_cmdline_to_pid[SAVED_CMDLINES];
 static char saved_cmdlines[SAVED_CMDLINES][TASK_COMM_LEN];
 static int cmdline_idx;
-static raw_spinlock_t trace_cmdline_lock = __RAW_SPIN_LOCK_UNLOCKED;
+static arch_spinlock_t trace_cmdline_lock = __RAW_SPIN_LOCK_UNLOCKED;
 
 /* temporary disable recording */
 static atomic_t trace_record_cmdline_disabled __read_mostly;
@@ -650,8 +814,10 @@ static void trace_init_cmdlines(void)
        cmdline_idx = 0;
 }
 
-static int trace_stop_count;
-static DEFINE_SPINLOCK(tracing_start_lock);
+int is_tracing_stopped(void)
+{
+       return trace_stop_count;
+}
 
 /**
  * ftrace_off_permanent - disable all ftrace code permanently
@@ -791,6 +957,7 @@ void trace_find_cmdline(int pid, char comm[])
                return;
        }
 
+       preempt_disable();
        __raw_spin_lock(&trace_cmdline_lock);
        map = map_pid_to_cmdline[pid];
        if (map != NO_CMDLINE_MAP)
@@ -799,6 +966,7 @@ void trace_find_cmdline(int pid, char comm[])
                strcpy(comm, "<...>");
 
        __raw_spin_unlock(&trace_cmdline_lock);
+       preempt_enable();
 }
 
 void tracing_record_cmdline(struct task_struct *tsk)
@@ -818,7 +986,7 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
 
        entry->preempt_count            = pc & 0xff;
        entry->pid                      = (tsk) ? tsk->pid : 0;
-       entry->tgid                     = (tsk) ? tsk->tgid : 0;
+       entry->lock_depth               = (tsk) ? tsk->lock_depth : 0;
        entry->flags =
 #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
                (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
@@ -829,15 +997,17 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
                ((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
                (need_resched() ? TRACE_FLAG_NEED_RESCHED : 0);
 }
+EXPORT_SYMBOL_GPL(tracing_generic_entry_update);
 
-struct ring_buffer_event *trace_buffer_lock_reserve(struct trace_array *tr,
-                                                   unsigned char type,
-                                                   unsigned long len,
-                                                   unsigned long flags, int pc)
+struct ring_buffer_event *
+trace_buffer_lock_reserve(struct ring_buffer *buffer,
+                         int type,
+                         unsigned long len,
+                         unsigned long flags, int pc)
 {
        struct ring_buffer_event *event;
 
-       event = ring_buffer_lock_reserve(tr->buffer, len);
+       event = ring_buffer_lock_reserve(buffer, len);
        if (event != NULL) {
                struct trace_entry *ent = ring_buffer_event_data(event);
 
@@ -847,51 +1017,62 @@ struct ring_buffer_event *trace_buffer_lock_reserve(struct trace_array *tr,
 
        return event;
 }
-static void ftrace_trace_stack(struct trace_array *tr,
-                              unsigned long flags, int skip, int pc);
-static void ftrace_trace_userstack(struct trace_array *tr,
-                                  unsigned long flags, int pc);
 
-static inline void __trace_buffer_unlock_commit(struct trace_array *tr,
-                                       struct ring_buffer_event *event,
-                                       unsigned long flags, int pc,
-                                       int wake)
+static inline void
+__trace_buffer_unlock_commit(struct ring_buffer *buffer,
+                            struct ring_buffer_event *event,
+                            unsigned long flags, int pc,
+                            int wake)
 {
-       ring_buffer_unlock_commit(tr->buffer, event);
+       ring_buffer_unlock_commit(buffer, event);
 
-       ftrace_trace_stack(tr, flags, 6, pc);
-       ftrace_trace_userstack(tr, flags, pc);
+       ftrace_trace_stack(buffer, flags, 6, pc);
+       ftrace_trace_userstack(buffer, flags, pc);
 
        if (wake)
                trace_wake_up();
 }
 
-void trace_buffer_unlock_commit(struct trace_array *tr,
-                                       struct ring_buffer_event *event,
-                                       unsigned long flags, int pc)
+void trace_buffer_unlock_commit(struct ring_buffer *buffer,
+                               struct ring_buffer_event *event,
+                               unsigned long flags, int pc)
 {
-       __trace_buffer_unlock_commit(tr, event, flags, pc, 1);
+       __trace_buffer_unlock_commit(buffer, event, flags, pc, 1);
 }
 
 struct ring_buffer_event *
-trace_current_buffer_lock_reserve(unsigned char type, unsigned long len,
+trace_current_buffer_lock_reserve(struct ring_buffer **current_rb,
+                                 int type, unsigned long len,
                                  unsigned long flags, int pc)
 {
-       return trace_buffer_lock_reserve(&global_trace,
+       *current_rb = global_trace.buffer;
+       return trace_buffer_lock_reserve(*current_rb,
                                         type, len, flags, pc);
 }
+EXPORT_SYMBOL_GPL(trace_current_buffer_lock_reserve);
 
-void trace_current_buffer_unlock_commit(struct ring_buffer_event *event,
+void trace_current_buffer_unlock_commit(struct ring_buffer *buffer,
+                                       struct ring_buffer_event *event,
                                        unsigned long flags, int pc)
 {
-       return __trace_buffer_unlock_commit(&global_trace, event, flags, pc, 1);
+       __trace_buffer_unlock_commit(buffer, event, flags, pc, 1);
 }
+EXPORT_SYMBOL_GPL(trace_current_buffer_unlock_commit);
 
-void trace_nowake_buffer_unlock_commit(struct ring_buffer_event *event,
-                                       unsigned long flags, int pc)
+void trace_nowake_buffer_unlock_commit(struct ring_buffer *buffer,
+                                      struct ring_buffer_event *event,
+                                      unsigned long flags, int pc)
 {
-       return __trace_buffer_unlock_commit(&global_trace, event, flags, pc, 0);
+       __trace_buffer_unlock_commit(buffer, event, flags, pc, 0);
 }
+EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit);
+
+void trace_current_buffer_discard_commit(struct ring_buffer *buffer,
+                                        struct ring_buffer_event *event)
+{
+       ring_buffer_discard_commit(buffer, event);
+}
+EXPORT_SYMBOL_GPL(trace_current_buffer_discard_commit);
 
 void
 trace_function(struct trace_array *tr,
@@ -899,14 +1080,15 @@ trace_function(struct trace_array *tr,
               int pc)
 {
        struct ftrace_event_call *call = &event_function;
+       struct ring_buffer *buffer = tr->buffer;
        struct ring_buffer_event *event;
        struct ftrace_entry *entry;
 
        /* If we are reading the ring buffer, don't trace */
-       if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled))))
+       if (unlikely(__this_cpu_read(per_cpu_var(ftrace_cpu_disabled))))
                return;
 
-       event = trace_buffer_lock_reserve(tr, TRACE_FN, sizeof(*entry),
+       event = trace_buffer_lock_reserve(buffer, TRACE_FN, sizeof(*entry),
                                          flags, pc);
        if (!event)
                return;
@@ -914,59 +1096,10 @@ trace_function(struct trace_array *tr,
        entry->ip                       = ip;
        entry->parent_ip                = parent_ip;
 
-       filter_check_discard(call, entry, event);
-
-       ring_buffer_unlock_commit(tr->buffer, event);
+       if (!filter_check_discard(call, entry, buffer, event))
+               ring_buffer_unlock_commit(buffer, event);
 }
 
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-static int __trace_graph_entry(struct trace_array *tr,
-                               struct ftrace_graph_ent *trace,
-                               unsigned long flags,
-                               int pc)
-{
-       struct ftrace_event_call *call = &event_funcgraph_entry;
-       struct ring_buffer_event *event;
-       struct ftrace_graph_ent_entry *entry;
-
-       if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled))))
-               return 0;
-
-       event = trace_buffer_lock_reserve(&global_trace, TRACE_GRAPH_ENT,
-                                         sizeof(*entry), flags, pc);
-       if (!event)
-               return 0;
-       entry   = ring_buffer_event_data(event);
-       entry->graph_ent                        = *trace;
-       filter_check_discard(call, entry, event);
-       ring_buffer_unlock_commit(global_trace.buffer, event);
-
-       return 1;
-}
-
-static void __trace_graph_return(struct trace_array *tr,
-                               struct ftrace_graph_ret *trace,
-                               unsigned long flags,
-                               int pc)
-{
-       struct ftrace_event_call *call = &event_funcgraph_exit;
-       struct ring_buffer_event *event;
-       struct ftrace_graph_ret_entry *entry;
-
-       if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled))))
-               return;
-
-       event = trace_buffer_lock_reserve(&global_trace, TRACE_GRAPH_RET,
-                                         sizeof(*entry), flags, pc);
-       if (!event)
-               return;
-       entry   = ring_buffer_event_data(event);
-       entry->ret                              = *trace;
-       filter_check_discard(call, entry, event);
-       ring_buffer_unlock_commit(global_trace.buffer, event);
-}
-#endif
-
 void
 ftrace(struct trace_array *tr, struct trace_array_cpu *data,
        unsigned long ip, unsigned long parent_ip, unsigned long flags,
@@ -976,17 +1109,17 @@ ftrace(struct trace_array *tr, struct trace_array_cpu *data,
                trace_function(tr, ip, parent_ip, flags, pc);
 }
 
-static void __ftrace_trace_stack(struct trace_array *tr,
+#ifdef CONFIG_STACKTRACE
+static void __ftrace_trace_stack(struct ring_buffer *buffer,
                                 unsigned long flags,
                                 int skip, int pc)
 {
-#ifdef CONFIG_STACKTRACE
        struct ftrace_event_call *call = &event_kernel_stack;
        struct ring_buffer_event *event;
        struct stack_entry *entry;
        struct stack_trace trace;
 
-       event = trace_buffer_lock_reserve(tr, TRACE_STACK,
+       event = trace_buffer_lock_reserve(buffer, TRACE_STACK,
                                          sizeof(*entry), flags, pc);
        if (!event)
                return;
@@ -999,32 +1132,28 @@ static void __ftrace_trace_stack(struct trace_array *tr,
        trace.entries           = entry->caller;
 
        save_stack_trace(&trace);
-       filter_check_discard(call, entry, event);
-       ring_buffer_unlock_commit(tr->buffer, event);
-#endif
+       if (!filter_check_discard(call, entry, buffer, event))
+               ring_buffer_unlock_commit(buffer, event);
 }
 
-static void ftrace_trace_stack(struct trace_array *tr,
-                              unsigned long flags,
-                              int skip, int pc)
+void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags,
+                       int skip, int pc)
 {
        if (!(trace_flags & TRACE_ITER_STACKTRACE))
                return;
 
-       __ftrace_trace_stack(tr, flags, skip, pc);
+       __ftrace_trace_stack(buffer, flags, skip, pc);
 }
 
-void __trace_stack(struct trace_array *tr,
-                  unsigned long flags,
-                  int skip, int pc)
+void __trace_stack(struct trace_array *tr, unsigned long flags, int skip,
+                  int pc)
 {
-       __ftrace_trace_stack(tr, flags, skip, pc);
+       __ftrace_trace_stack(tr->buffer, flags, skip, pc);
 }
 
-static void ftrace_trace_userstack(struct trace_array *tr,
-                                  unsigned long flags, int pc)
+void
+ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
 {
-#ifdef CONFIG_STACKTRACE
        struct ftrace_event_call *call = &event_user_stack;
        struct ring_buffer_event *event;
        struct userstack_entry *entry;
@@ -1033,12 +1162,13 @@ static void ftrace_trace_userstack(struct trace_array *tr,
        if (!(trace_flags & TRACE_ITER_USERSTACKTRACE))
                return;
 
-       event = trace_buffer_lock_reserve(tr, TRACE_USER_STACK,
+       event = trace_buffer_lock_reserve(buffer, TRACE_USER_STACK,
                                          sizeof(*entry), flags, pc);
        if (!event)
                return;
        entry   = ring_buffer_event_data(event);
 
+       entry->tgid             = current->tgid;
        memset(&entry->caller, 0, sizeof(entry->caller));
 
        trace.nr_entries        = 0;
@@ -1047,9 +1177,8 @@ static void ftrace_trace_userstack(struct trace_array *tr,
        trace.entries           = entry->caller;
 
        save_stack_trace_user(&trace);
-       filter_check_discard(call, entry, event);
-       ring_buffer_unlock_commit(tr->buffer, event);
-#endif
+       if (!filter_check_discard(call, entry, buffer, event))
+               ring_buffer_unlock_commit(buffer, event);
 }
 
 #ifdef UNUSED
@@ -1059,6 +1188,8 @@ static void __trace_userstack(struct trace_array *tr, unsigned long flags)
 }
 #endif /* UNUSED */
 
+#endif /* CONFIG_STACKTRACE */
+
 static void
 ftrace_trace_special(void *__tr,
                     unsigned long arg1, unsigned long arg2, unsigned long arg3,
@@ -1067,9 +1198,10 @@ ftrace_trace_special(void *__tr,
        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(tr, TRACE_SPECIAL,
+       event = trace_buffer_lock_reserve(buffer, TRACE_SPECIAL,
                                          sizeof(*entry), 0, pc);
        if (!event)
                return;
@@ -1077,8 +1209,9 @@ ftrace_trace_special(void *__tr,
        entry->arg1                     = arg1;
        entry->arg2                     = arg2;
        entry->arg3                     = arg3;
-       filter_check_discard(call, entry, event);
-       trace_buffer_unlock_commit(tr, event, 0, pc);
+
+       if (!filter_check_discard(call, entry, buffer, event))
+               trace_buffer_unlock_commit(buffer, event, 0, pc);
 }
 
 void
@@ -1089,64 +1222,6 @@ __trace_special(void *__tr, void *__data,
 }
 
 void
-tracing_sched_switch_trace(struct trace_array *tr,
-                          struct task_struct *prev,
-                          struct task_struct *next,
-                          unsigned long flags, int pc)
-{
-       struct ftrace_event_call *call = &event_context_switch;
-       struct ring_buffer_event *event;
-       struct ctx_switch_entry *entry;
-
-       event = trace_buffer_lock_reserve(tr, TRACE_CTX,
-                                         sizeof(*entry), flags, pc);
-       if (!event)
-               return;
-       entry   = ring_buffer_event_data(event);
-       entry->prev_pid                 = prev->pid;
-       entry->prev_prio                = prev->prio;
-       entry->prev_state               = prev->state;
-       entry->next_pid                 = next->pid;
-       entry->next_prio                = next->prio;
-       entry->next_state               = next->state;
-       entry->next_cpu = task_cpu(next);
-
-       filter_check_discard(call, entry, event);
-
-       trace_buffer_unlock_commit(tr, event, flags, pc);
-}
-
-void
-tracing_sched_wakeup_trace(struct trace_array *tr,
-                          struct task_struct *wakee,
-                          struct task_struct *curr,
-                          unsigned long flags, int pc)
-{
-       struct ftrace_event_call *call = &event_wakeup;
-       struct ring_buffer_event *event;
-       struct ctx_switch_entry *entry;
-
-       event = trace_buffer_lock_reserve(tr, TRACE_WAKE,
-                                         sizeof(*entry), flags, pc);
-       if (!event)
-               return;
-       entry   = ring_buffer_event_data(event);
-       entry->prev_pid                 = curr->pid;
-       entry->prev_prio                = curr->prio;
-       entry->prev_state               = curr->state;
-       entry->next_pid                 = wakee->pid;
-       entry->next_prio                = wakee->prio;
-       entry->next_state               = wakee->state;
-       entry->next_cpu                 = task_cpu(wakee);
-
-       filter_check_discard(call, entry, event);
-
-       ring_buffer_unlock_commit(tr->buffer, event);
-       ftrace_trace_stack(tr, flags, 6, pc);
-       ftrace_trace_userstack(tr, flags, pc);
-}
-
-void
 ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3)
 {
        struct trace_array *tr = &global_trace;
@@ -1170,84 +1245,24 @@ ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3)
        local_irq_restore(flags);
 }
 
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-int trace_graph_entry(struct ftrace_graph_ent *trace)
-{
-       struct trace_array *tr = &global_trace;
-       struct trace_array_cpu *data;
-       unsigned long flags;
-       long disabled;
-       int ret;
-       int cpu;
-       int pc;
-
-       if (!ftrace_trace_task(current))
-               return 0;
-
-       if (!ftrace_graph_addr(trace->func))
-               return 0;
-
-       local_irq_save(flags);
-       cpu = raw_smp_processor_id();
-       data = tr->data[cpu];
-       disabled = atomic_inc_return(&data->disabled);
-       if (likely(disabled == 1)) {
-               pc = preempt_count();
-               ret = __trace_graph_entry(tr, trace, flags, pc);
-       } else {
-               ret = 0;
-       }
-       /* Only do the atomic if it is not already set */
-       if (!test_tsk_trace_graph(current))
-               set_tsk_trace_graph(current);
-
-       atomic_dec(&data->disabled);
-       local_irq_restore(flags);
-
-       return ret;
-}
-
-void trace_graph_return(struct ftrace_graph_ret *trace)
-{
-       struct trace_array *tr = &global_trace;
-       struct trace_array_cpu *data;
-       unsigned long flags;
-       long disabled;
-       int cpu;
-       int pc;
-
-       local_irq_save(flags);
-       cpu = raw_smp_processor_id();
-       data = tr->data[cpu];
-       disabled = atomic_inc_return(&data->disabled);
-       if (likely(disabled == 1)) {
-               pc = preempt_count();
-               __trace_graph_return(tr, trace, flags, pc);
-       }
-       if (!trace->depth)
-               clear_tsk_trace_graph(current);
-       atomic_dec(&data->disabled);
-       local_irq_restore(flags);
-}
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-
-
 /**
  * trace_vbprintk - write binary msg to tracing buffer
  *
  */
 int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
 {
-       static raw_spinlock_t trace_buf_lock =
-               (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+       static arch_spinlock_t trace_buf_lock =
+               (arch_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
        static u32 trace_buf[TRACE_BUF_SIZE];
 
        struct ftrace_event_call *call = &event_bprint;
        struct ring_buffer_event *event;
+       struct ring_buffer *buffer;
        struct trace_array *tr = &global_trace;
        struct trace_array_cpu *data;
        struct bprint_entry *entry;
        unsigned long flags;
+       int disable;
        int resched;
        int cpu, len = 0, size, pc;
 
@@ -1262,7 +1277,8 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
        cpu = raw_smp_processor_id();
        data = tr->data[cpu];
 
-       if (unlikely(atomic_read(&data->disabled)))
+       disable = atomic_inc_return(&data->disabled);
+       if (unlikely(disable != 1))
                goto out;
 
        /* Lockdep uses trace_printk for lock tracing */
@@ -1274,7 +1290,9 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
                goto out_unlock;
 
        size = sizeof(*entry) + sizeof(u32) * len;
-       event = trace_buffer_lock_reserve(tr, TRACE_BPRINT, size, flags, pc);
+       buffer = tr->buffer;
+       event = trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size,
+                                         flags, pc);
        if (!event)
                goto out_unlock;
        entry = ring_buffer_event_data(event);
@@ -1282,14 +1300,15 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
        entry->fmt                      = fmt;
 
        memcpy(entry->buf, trace_buf, sizeof(u32) * len);
-       filter_check_discard(call, entry, event);
-       ring_buffer_unlock_commit(tr->buffer, event);
+       if (!filter_check_discard(call, entry, buffer, event))
+               ring_buffer_unlock_commit(buffer, event);
 
 out_unlock:
        __raw_spin_unlock(&trace_buf_lock);
        local_irq_restore(flags);
 
 out:
+       atomic_dec_return(&data->disabled);
        ftrace_preempt_enable(resched);
        unpause_graph_tracing();
 
@@ -1297,18 +1316,35 @@ out:
 }
 EXPORT_SYMBOL_GPL(trace_vbprintk);
 
-int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
+int trace_array_printk(struct trace_array *tr,
+                      unsigned long ip, const char *fmt, ...)
 {
-       static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED;
+       int ret;
+       va_list ap;
+
+       if (!(trace_flags & TRACE_ITER_PRINTK))
+               return 0;
+
+       va_start(ap, fmt);
+       ret = trace_array_vprintk(tr, ip, fmt, ap);
+       va_end(ap);
+       return ret;
+}
+
+int trace_array_vprintk(struct trace_array *tr,
+                       unsigned long ip, const char *fmt, va_list args)
+{
+       static arch_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED;
        static char trace_buf[TRACE_BUF_SIZE];
 
        struct ftrace_event_call *call = &event_print;
        struct ring_buffer_event *event;
-       struct trace_array *tr = &global_trace;
+       struct ring_buffer *buffer;
        struct trace_array_cpu *data;
        int cpu, len = 0, size, pc;
        struct print_entry *entry;
        unsigned long irq_flags;
+       int disable;
 
        if (tracing_disabled || tracing_selftest_running)
                return 0;
@@ -1318,7 +1354,8 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
        cpu = raw_smp_processor_id();
        data = tr->data[cpu];
 
-       if (unlikely(atomic_read(&data->disabled)))
+       disable = atomic_inc_return(&data->disabled);
+       if (unlikely(disable != 1))
                goto out;
 
        pause_graph_tracing();
@@ -1326,30 +1363,35 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
        __raw_spin_lock(&trace_buf_lock);
        len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args);
 
-       len = min(len, TRACE_BUF_SIZE-1);
-       trace_buf[len] = 0;
-
        size = sizeof(*entry) + len + 1;
-       event = trace_buffer_lock_reserve(tr, TRACE_PRINT, size, irq_flags, pc);
+       buffer = tr->buffer;
+       event = trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,
+                                         irq_flags, pc);
        if (!event)
                goto out_unlock;
        entry = ring_buffer_event_data(event);
-       entry->ip                       = ip;
+       entry->ip = ip;
 
        memcpy(&entry->buf, trace_buf, len);
-       entry->buf[len] = 0;
-       filter_check_discard(call, entry, event);
-       ring_buffer_unlock_commit(tr->buffer, event);
+       entry->buf[len] = '\0';
+       if (!filter_check_discard(call, entry, buffer, event))
+               ring_buffer_unlock_commit(buffer, event);
 
  out_unlock:
        __raw_spin_unlock(&trace_buf_lock);
        raw_local_irq_restore(irq_flags);
        unpause_graph_tracing();
  out:
+       atomic_dec_return(&data->disabled);
        preempt_enable_notrace();
 
        return len;
 }
+
+int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
+{
+       return trace_array_vprintk(&global_trace, ip, fmt, args);
+}
 EXPORT_SYMBOL_GPL(trace_vprintk);
 
 enum trace_file_type {
@@ -1470,6 +1512,8 @@ static void *s_next(struct seq_file *m, void *v, loff_t *pos)
        int i = (int)*pos;
        void *ent;
 
+       WARN_ON_ONCE(iter->leftover);
+
        (*pos)++;
 
        /* can't go backwards */
@@ -1489,6 +1533,37 @@ static void *s_next(struct seq_file *m, void *v, loff_t *pos)
        return ent;
 }
 
+static void tracing_iter_reset(struct trace_iterator *iter, int cpu)
+{
+       struct trace_array *tr = iter->tr;
+       struct ring_buffer_event *event;
+       struct ring_buffer_iter *buf_iter;
+       unsigned long entries = 0;
+       u64 ts;
+
+       tr->data[cpu]->skipped_entries = 0;
+
+       if (!iter->buffer_iter[cpu])
+               return;
+
+       buf_iter = iter->buffer_iter[cpu];
+       ring_buffer_iter_reset(buf_iter);
+
+       /*
+        * We could have the case with the max latency tracers
+        * that a reset never took place on a cpu. This is evident
+        * by the timestamp being before the start of the buffer.
+        */
+       while ((event = ring_buffer_iter_peek(buf_iter, &ts))) {
+               if (ts >= iter->tr->time_start)
+                       break;
+               entries++;
+               ring_buffer_read(buf_iter, NULL);
+       }
+
+       tr->data[cpu]->skipped_entries = entries;
+}
+
 /*
  * No necessary locking here. The worst thing which can
  * happen is loosing events consumed at the same time
@@ -1527,10 +1602,9 @@ static void *s_start(struct seq_file *m, loff_t *pos)
 
                if (cpu_file == TRACE_PIPE_ALL_CPU) {
                        for_each_tracing_cpu(cpu)
-                               ring_buffer_iter_reset(iter->buffer_iter[cpu]);
+                               tracing_iter_reset(iter, cpu);
                } else
-                       ring_buffer_iter_reset(iter->buffer_iter[cpu_file]);
-
+                       tracing_iter_reset(iter, cpu_file);
 
                ftrace_enable_cpu();
 
@@ -1538,16 +1612,26 @@ static void *s_start(struct seq_file *m, loff_t *pos)
                        ;
 
        } else {
-               l = *pos - 1;
-               p = s_next(m, p, &l);
+               /*
+                * If we overflowed the seq_file before, then we want
+                * to just reuse the trace_seq buffer again.
+                */
+               if (iter->leftover)
+                       p = iter;
+               else {
+                       l = *pos - 1;
+                       p = s_next(m, p, &l);
+               }
        }
 
+       trace_event_read_lock();
        return p;
 }
 
 static void s_stop(struct seq_file *m, void *p)
 {
        atomic_dec(&trace_record_cmdline_disabled);
+       trace_event_read_unlock();
 }
 
 static void print_lat_help_header(struct seq_file *m)
@@ -1557,10 +1641,10 @@ static void print_lat_help_header(struct seq_file *m)
        seq_puts(m, "#                | / _----=> need-resched    \n");
        seq_puts(m, "#                || / _---=> hardirq/softirq \n");
        seq_puts(m, "#                ||| / _--=> preempt-depth   \n");
-       seq_puts(m, "#                |||| /                      \n");
-       seq_puts(m, "#                |||||     delay             \n");
-       seq_puts(m, "#  cmd     pid   ||||| time  |   caller      \n");
-       seq_puts(m, "#     \\   /      |||||   \\   |   /           \n");
+       seq_puts(m, "#                |||| /_--=> lock-depth       \n");
+       seq_puts(m, "#                |||||/     delay             \n");
+       seq_puts(m, "#  cmd     pid   |||||| time  |   caller      \n");
+       seq_puts(m, "#     \\   /      ||||||   \\   |   /           \n");
 }
 
 static void print_func_help_header(struct seq_file *m)
@@ -1577,16 +1661,32 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter)
        struct trace_array *tr = iter->tr;
        struct trace_array_cpu *data = tr->data[tr->cpu];
        struct tracer *type = current_trace;
-       unsigned long total;
-       unsigned long entries;
+       unsigned long entries = 0;
+       unsigned long total = 0;
+       unsigned long count;
        const char *name = "preemption";
+       int cpu;
 
        if (type)
                name = type->name;
 
-       entries = ring_buffer_entries(iter->tr->buffer);
-       total = entries +
-               ring_buffer_overruns(iter->tr->buffer);
+
+       for_each_tracing_cpu(cpu) {
+               count = ring_buffer_entries_cpu(tr->buffer, cpu);
+               /*
+                * If this buffer has skipped entries, then we hold all
+                * entries for the trace and we need to ignore the
+                * ones before the time stamp.
+                */
+               if (tr->data[cpu]->skipped_entries) {
+                       count -= tr->data[cpu]->skipped_entries;
+                       /* total is the same as the entries */
+                       total += count;
+               } else
+                       total += count +
+                               ring_buffer_overrun_cpu(tr->buffer, cpu);
+               entries += count;
+       }
 
        seq_printf(m, "# %s latency trace v1.1.5 on %s\n",
                   name, UTS_RELEASE);
@@ -1628,7 +1728,7 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter)
                seq_puts(m, "\n#  => ended at:   ");
                seq_print_ip_sym(&iter->seq, data->critical_end, sym_flags);
                trace_print_seq(m, &iter->seq);
-               seq_puts(m, "#\n");
+               seq_puts(m, "\n#\n");
        }
 
        seq_puts(m, "#\n");
@@ -1647,6 +1747,9 @@ static void test_cpu_buff_start(struct trace_iterator *iter)
        if (cpumask_test_cpu(iter->cpu, iter->started))
                return;
 
+       if (iter->tr->data[iter->cpu]->skipped_entries)
+               return;
+
        cpumask_set_cpu(iter->cpu, iter->started);
 
        /* Don't print started cpu buffer for the first entry of the trace */
@@ -1790,6 +1893,7 @@ static int trace_empty(struct trace_iterator *iter)
        return 1;
 }
 
+/*  Called with trace_event_read_lock() held. */
 static enum print_line_t print_trace_line(struct trace_iterator *iter)
 {
        enum print_line_t ret;
@@ -1825,6 +1929,7 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter)
 static int s_show(struct seq_file *m, void *v)
 {
        struct trace_iterator *iter = v;
+       int ret;
 
        if (iter->ent == NULL) {
                if (iter->tr) {
@@ -1844,15 +1949,33 @@ static int s_show(struct seq_file *m, void *v)
                        if (!(trace_flags & TRACE_ITER_VERBOSE))
                                print_func_help_header(m);
                }
+       } else if (iter->leftover) {
+               /*
+                * If we filled the seq_file buffer earlier, we
+                * want to just show it now.
+                */
+               ret = trace_print_seq(m, &iter->seq);
+
+               /* ret should this time be zero, but you never know */
+               iter->leftover = ret;
+
        } else {
                print_trace_line(iter);
-               trace_print_seq(m, &iter->seq);
+               ret = trace_print_seq(m, &iter->seq);
+               /*
+                * If we overflow the seq_file buffer, then it will
+                * ask us for this data again at start up.
+                * Use that instead.
+                *  ret is 0 if seq_file write succeeded.
+                *        -1 otherwise.
+                */
+               iter->leftover = ret;
        }
 
        return 0;
 }
 
-static struct seq_operations tracer_seq_ops = {
+static const struct seq_operations tracer_seq_ops = {
        .start          = s_start,
        .next           = s_next,
        .stop           = s_stop,
@@ -1887,11 +2010,9 @@ __tracing_open(struct inode *inode, struct file *file)
        if (current_trace)
                *iter->trace = *current_trace;
 
-       if (!alloc_cpumask_var(&iter->started, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&iter->started, GFP_KERNEL))
                goto fail;
 
-       cpumask_clear(iter->started);
-
        if (current_trace && current_trace->print_max)
                iter->tr = &max_tr;
        else
@@ -1908,19 +2029,23 @@ __tracing_open(struct inode *inode, struct file *file)
        if (ring_buffer_overruns(iter->tr->buffer))
                iter->iter_flags |= TRACE_FILE_ANNOTATE;
 
+       /* stop the trace while dumping */
+       tracing_stop();
+
        if (iter->cpu_file == TRACE_PIPE_ALL_CPU) {
                for_each_tracing_cpu(cpu) {
 
                        iter->buffer_iter[cpu] =
                                ring_buffer_read_start(iter->tr->buffer, cpu);
+                       tracing_iter_reset(iter, cpu);
                }
        } else {
                cpu = iter->cpu_file;
                iter->buffer_iter[cpu] =
                                ring_buffer_read_start(iter->tr->buffer, cpu);
+               tracing_iter_reset(iter, cpu);
        }
 
-       /* TODO stop tracer */
        ret = seq_open(file, &tracer_seq_ops);
        if (ret < 0) {
                fail_ret = ERR_PTR(ret);
@@ -1930,9 +2055,6 @@ __tracing_open(struct inode *inode, struct file *file)
        m = file->private_data;
        m->private = iter;
 
-       /* stop the trace while dumping */
-       tracing_stop();
-
        mutex_unlock(&trace_types_lock);
 
        return iter;
@@ -1943,6 +2065,7 @@ __tracing_open(struct inode *inode, struct file *file)
                        ring_buffer_read_finish(iter->buffer_iter[cpu]);
        }
        free_cpumask_var(iter->started);
+       tracing_start();
  fail:
        mutex_unlock(&trace_types_lock);
        kfree(iter->trace);
@@ -1999,7 +2122,7 @@ static int tracing_open(struct inode *inode, struct file *file)
 
        /* If this file was open for write, then erase contents */
        if ((file->f_mode & FMODE_WRITE) &&
-           !(file->f_flags & O_APPEND)) {
+           (file->f_flags & O_TRUNC)) {
                long cpu = (long) inode->i_private;
 
                if (cpu == TRACE_PIPE_ALL_CPU)
@@ -2021,25 +2144,23 @@ static int tracing_open(struct inode *inode, struct file *file)
 static void *
 t_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       struct tracer *t = m->private;
+       struct tracer *t = v;
 
        (*pos)++;
 
        if (t)
                t = t->next;
 
-       m->private = t;
-
        return t;
 }
 
 static void *t_start(struct seq_file *m, loff_t *pos)
 {
-       struct tracer *t = m->private;
+       struct tracer *t;
        loff_t l = 0;
 
        mutex_lock(&trace_types_lock);
-       for (; t && l < *pos; t = t_next(m, t, &l))
+       for (t = trace_types; t && l < *pos; t = t_next(m, t, &l))
                ;
 
        return t;
@@ -2066,7 +2187,7 @@ static int t_show(struct seq_file *m, void *v)
        return 0;
 }
 
-static struct seq_operations show_traces_seq_ops = {
+static const struct seq_operations show_traces_seq_ops = {
        .start          = t_start,
        .next           = t_next,
        .stop           = t_stop,
@@ -2075,18 +2196,10 @@ static struct seq_operations show_traces_seq_ops = {
 
 static int show_traces_open(struct inode *inode, struct file *file)
 {
-       int ret;
-
        if (tracing_disabled)
                return -ENODEV;
 
-       ret = seq_open(file, &show_traces_seq_ops);
-       if (!ret) {
-               struct seq_file *m = file->private_data;
-               m->private = trace_types;
-       }
-
-       return ret;
+       return seq_open(file, &show_traces_seq_ops);
 }
 
 static ssize_t
@@ -2159,11 +2272,12 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
        if (!alloc_cpumask_var(&tracing_cpumask_new, GFP_KERNEL))
                return -ENOMEM;
 
-       mutex_lock(&tracing_cpumask_update_lock);
        err = cpumask_parse_user(ubuf, count, tracing_cpumask_new);
        if (err)
                goto err_unlock;
 
+       mutex_lock(&tracing_cpumask_update_lock);
+
        local_irq_disable();
        __raw_spin_lock(&ftrace_max_lock);
        for_each_tracing_cpu(cpu) {
@@ -2191,8 +2305,7 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
        return count;
 
 err_unlock:
-       mutex_unlock(&tracing_cpumask_update_lock);
-       free_cpumask_var(tracing_cpumask);
+       free_cpumask_var(tracing_cpumask_new);
 
        return err;
 }
@@ -2234,8 +2347,8 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
                len += 3; /* "no" and newline */
        }
 
-       /* +2 for \n and \0 */
-       buf = kmalloc(len + 2, GFP_KERNEL);
+       /* +1 for \0 */
+       buf = kmalloc(len + 1, GFP_KERNEL);
        if (!buf) {
                mutex_unlock(&trace_types_lock);
                return -ENOMEM;
@@ -2258,7 +2371,7 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
        }
        mutex_unlock(&trace_types_lock);
 
-       WARN_ON(r >= len + 2);
+       WARN_ON(r >= len + 1);
 
        r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
 
@@ -2269,23 +2382,23 @@ tracing_trace_options_read(struct file *filp, char __user *ubuf,
 /* Try to assign a tracer specific option */
 static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
 {
-       struct tracer_flags *trace_flags = trace->flags;
+       struct tracer_flags *tracer_flags = trace->flags;
        struct tracer_opt *opts = NULL;
        int ret = 0, i = 0;
        int len;
 
-       for (i = 0; trace_flags->opts[i].name; i++) {
-               opts = &trace_flags->opts[i];
+       for (i = 0; tracer_flags->opts[i].name; i++) {
+               opts = &tracer_flags->opts[i];
                len = strlen(opts->name);
 
                if (strncmp(cmp, opts->name, len) == 0) {
-                       ret = trace->set_flag(trace_flags->val,
+                       ret = trace->set_flag(tracer_flags->val,
                                opts->bit, !neg);
                        break;
                }
        }
        /* Not found */
-       if (!trace_flags->opts[i].name)
+       if (!tracer_flags->opts[i].name)
                return -EINVAL;
 
        /* Refused to handle */
@@ -2293,9 +2406,9 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
                return ret;
 
        if (neg)
-               trace_flags->val &= ~opts->bit;
+               tracer_flags->val &= ~opts->bit;
        else
-               trace_flags->val |= opts->bit;
+               tracer_flags->val |= opts->bit;
 
        return 0;
 }
@@ -2310,22 +2423,6 @@ static void set_tracer_flags(unsigned int mask, int enabled)
                trace_flags |= mask;
        else
                trace_flags &= ~mask;
-
-       if (mask == TRACE_ITER_GLOBAL_CLK) {
-               u64 (*func)(void);
-
-               if (enabled)
-                       func = trace_clock_global;
-               else
-                       func = trace_clock_local;
-
-               mutex_lock(&trace_types_lock);
-               ring_buffer_set_clock(global_trace.buffer, func);
-
-               if (max_tr.buffer)
-                       ring_buffer_set_clock(max_tr.buffer, func);
-               mutex_unlock(&trace_types_lock);
-       }
 }
 
 static ssize_t
@@ -2369,7 +2466,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
                        return ret;
        }
 
-       filp->f_pos += cnt;
+       *ppos += cnt;
 
        return cnt;
 }
@@ -2382,21 +2479,20 @@ static const struct file_operations tracing_iter_fops = {
 
 static const char readme_msg[] =
        "tracing mini-HOWTO:\n\n"
-       "# mkdir /debug\n"
-       "# mount -t debugfs nodev /debug\n\n"
-       "# cat /debug/tracing/available_tracers\n"
+       "# mount -t debugfs nodev /sys/kernel/debug\n\n"
+       "# cat /sys/kernel/debug/tracing/available_tracers\n"
        "wakeup preemptirqsoff preemptoff irqsoff function sched_switch nop\n\n"
-       "# cat /debug/tracing/current_tracer\n"
+       "# cat /sys/kernel/debug/tracing/current_tracer\n"
        "nop\n"
-       "# echo sched_switch > /debug/tracing/current_tracer\n"
-       "# cat /debug/tracing/current_tracer\n"
+       "# echo sched_switch > /sys/kernel/debug/tracing/current_tracer\n"
+       "# cat /sys/kernel/debug/tracing/current_tracer\n"
        "sched_switch\n"
-       "# cat /debug/tracing/trace_options\n"
+       "# cat /sys/kernel/debug/tracing/trace_options\n"
        "noprint-parent nosym-offset nosym-addr noverbose\n"
-       "# echo print-parent > /debug/tracing/trace_options\n"
-       "# echo 1 > /debug/tracing/tracing_enabled\n"
-       "# cat /debug/tracing/trace > /tmp/trace.txt\n"
-       "echo 0 > /debug/tracing/tracing_enabled\n"
+       "# echo print-parent > /sys/kernel/debug/tracing/trace_options\n"
+       "# echo 1 > /sys/kernel/debug/tracing/tracing_enabled\n"
+       "# cat /sys/kernel/debug/tracing/trace > /tmp/trace.txt\n"
+       "# echo 0 > /sys/kernel/debug/tracing/tracing_enabled\n"
 ;
 
 static ssize_t
@@ -2413,6 +2509,56 @@ static const struct file_operations tracing_readme_fops = {
 };
 
 static ssize_t
+tracing_saved_cmdlines_read(struct file *file, char __user *ubuf,
+                               size_t cnt, loff_t *ppos)
+{
+       char *buf_comm;
+       char *file_buf;
+       char *buf;
+       int len = 0;
+       int pid;
+       int i;
+
+       file_buf = kmalloc(SAVED_CMDLINES*(16+TASK_COMM_LEN), GFP_KERNEL);
+       if (!file_buf)
+               return -ENOMEM;
+
+       buf_comm = kmalloc(TASK_COMM_LEN, GFP_KERNEL);
+       if (!buf_comm) {
+               kfree(file_buf);
+               return -ENOMEM;
+       }
+
+       buf = file_buf;
+
+       for (i = 0; i < SAVED_CMDLINES; i++) {
+               int r;
+
+               pid = map_cmdline_to_pid[i];
+               if (pid == -1 || pid == NO_CMDLINE_MAP)
+                       continue;
+
+               trace_find_cmdline(pid, buf_comm);
+               r = sprintf(buf, "%d %s\n", pid, buf_comm);
+               buf += r;
+               len += r;
+       }
+
+       len = simple_read_from_buffer(ubuf, cnt, ppos,
+                                     file_buf, len);
+
+       kfree(file_buf);
+       kfree(buf_comm);
+
+       return len;
+}
+
+static const struct file_operations tracing_saved_cmdlines_fops = {
+    .open       = tracing_open_generic,
+    .read       = tracing_saved_cmdlines_read,
+};
+
+static ssize_t
 tracing_ctrl_read(struct file *filp, char __user *ubuf,
                  size_t cnt, loff_t *ppos)
 {
@@ -2462,7 +2608,7 @@ tracing_ctrl_write(struct file *filp, const char __user *ubuf,
        }
        mutex_unlock(&trace_types_lock);
 
-       filp->f_pos += cnt;
+       *ppos += cnt;
 
        return cnt;
 }
@@ -2471,7 +2617,7 @@ static ssize_t
 tracing_set_trace_read(struct file *filp, char __user *ubuf,
                       size_t cnt, loff_t *ppos)
 {
-       char buf[max_tracer_type_len+2];
+       char buf[MAX_TRACER_SIZE+2];
        int r;
 
        mutex_lock(&trace_types_lock);
@@ -2621,15 +2767,15 @@ static ssize_t
 tracing_set_trace_write(struct file *filp, const char __user *ubuf,
                        size_t cnt, loff_t *ppos)
 {
-       char buf[max_tracer_type_len+1];
+       char buf[MAX_TRACER_SIZE+1];
        int i;
        size_t ret;
        int err;
 
        ret = cnt;
 
-       if (cnt > max_tracer_type_len)
-               cnt = max_tracer_type_len;
+       if (cnt > MAX_TRACER_SIZE)
+               cnt = MAX_TRACER_SIZE;
 
        if (copy_from_user(&buf, ubuf, cnt))
                return -EFAULT;
@@ -2644,7 +2790,7 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf,
        if (err)
                return err;
 
-       filp->f_pos += ret;
+       *ppos += ret;
 
        return ret;
 }
@@ -2744,6 +2890,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
        /* trace pipe does not show start of buffer */
        cpumask_setall(iter->started);
 
+       if (trace_flags & TRACE_ITER_LATENCY_FMT)
+               iter->iter_flags |= TRACE_FILE_LAT_FMT;
+
        iter->cpu_file = cpu_file;
        iter->tr = &global_trace;
        mutex_init(&iter->mutex);
@@ -2774,6 +2923,10 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
        else
                cpumask_clear_cpu(iter->cpu_file, tracing_reader_cpumask);
 
+
+       if (iter->trace->pipe_close)
+               iter->trace->pipe_close(iter);
+
        mutex_unlock(&trace_types_lock);
 
        free_cpumask_var(iter->started);
@@ -2931,6 +3084,7 @@ waitagain:
               offsetof(struct trace_iterator, seq));
        iter->pos = -1;
 
+       trace_event_read_lock();
        while (find_next_entry_inc(iter) != NULL) {
                enum print_line_t ret;
                int len = iter->seq.len;
@@ -2947,6 +3101,7 @@ waitagain:
                if (iter->seq.len >= cnt)
                        break;
        }
+       trace_event_read_unlock();
 
        /* Now copy what we have to the user */
        sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
@@ -3009,7 +3164,8 @@ tracing_fill_pipe_page(size_t rem, struct trace_iterator *iter)
                        break;
                }
 
-               trace_consume(iter);
+               if (ret != TRACE_TYPE_NO_CONSUME)
+                       trace_consume(iter);
                rem -= count;
                if (!find_next_entry_inc(iter)) {
                        rem = 0;
@@ -3069,6 +3225,8 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
                goto out_err;
        }
 
+       trace_event_read_lock();
+
        /* Fill as many pages as possible. */
        for (i = 0, rem = len; i < PIPE_BUFFERS && rem; i++) {
                pages[i] = alloc_page(GFP_KERNEL);
@@ -3091,6 +3249,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
                trace_seq_init(&iter->seq);
        }
 
+       trace_event_read_unlock();
        mutex_unlock(&iter->mutex);
 
        spd.nr_pages = i;
@@ -3170,7 +3329,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
                }
        }
 
-       filp->f_pos += cnt;
+       *ppos += cnt;
 
        /* If check pages failed, return ENOMEM */
        if (tracing_disabled)
@@ -3205,7 +3364,6 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
                                        size_t cnt, loff_t *fpos)
 {
        char *buf;
-       char *end;
 
        if (tracing_disabled)
                return -EINVAL;
@@ -3213,7 +3371,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
        if (cnt > TRACE_BUF_SIZE)
                cnt = TRACE_BUF_SIZE;
 
-       buf = kmalloc(cnt + 1, GFP_KERNEL);
+       buf = kmalloc(cnt + 2, GFP_KERNEL);
        if (buf == NULL)
                return -ENOMEM;
 
@@ -3221,20 +3379,75 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
                kfree(buf);
                return -EFAULT;
        }
+       if (buf[cnt-1] != '\n') {
+               buf[cnt] = '\n';
+               buf[cnt+1] = '\0';
+       } else
+               buf[cnt] = '\0';
 
-       /* Cut from the first nil or newline. */
-       buf[cnt] = '\0';
-       end = strchr(buf, '\n');
-       if (end)
-               *end = '\0';
-
-       cnt = mark_printk("%s\n", buf);
+       cnt = mark_printk("%s", buf);
        kfree(buf);
        *fpos += cnt;
 
        return cnt;
 }
 
+static ssize_t tracing_clock_read(struct file *filp, char __user *ubuf,
+                                 size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+       int bufiter = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(trace_clocks); i++)
+               bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter,
+                       "%s%s%s%s", i ? " " : "",
+                       i == trace_clock_id ? "[" : "", trace_clocks[i].name,
+                       i == trace_clock_id ? "]" : "");
+       bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter, "\n");
+
+       return simple_read_from_buffer(ubuf, cnt, ppos, buf, bufiter);
+}
+
+static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
+                                  size_t cnt, loff_t *fpos)
+{
+       char buf[64];
+       const char *clockstr;
+       int i;
+
+       if (cnt >= sizeof(buf))
+               return -EINVAL;
+
+       if (copy_from_user(&buf, ubuf, cnt))
+               return -EFAULT;
+
+       buf[cnt] = 0;
+
+       clockstr = strstrip(buf);
+
+       for (i = 0; i < ARRAY_SIZE(trace_clocks); i++) {
+               if (strcmp(trace_clocks[i].name, clockstr) == 0)
+                       break;
+       }
+       if (i == ARRAY_SIZE(trace_clocks))
+               return -EINVAL;
+
+       trace_clock_id = i;
+
+       mutex_lock(&trace_types_lock);
+
+       ring_buffer_set_clock(global_trace.buffer, trace_clocks[i].func);
+       if (max_tr.buffer)
+               ring_buffer_set_clock(max_tr.buffer, trace_clocks[i].func);
+
+       mutex_unlock(&trace_types_lock);
+
+       *fpos += cnt;
+
+       return cnt;
+}
+
 static const struct file_operations tracing_max_lat_fops = {
        .open           = tracing_open_generic,
        .read           = tracing_max_lat_read,
@@ -3272,6 +3485,12 @@ static const struct file_operations tracing_mark_fops = {
        .write          = tracing_mark_write,
 };
 
+static const struct file_operations trace_clock_fops = {
+       .open           = tracing_open_generic,
+       .read           = tracing_clock_read,
+       .write          = tracing_clock_write,
+};
+
 struct ftrace_buffer_info {
        struct trace_array      *tr;
        void                    *spare;
@@ -3441,7 +3660,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                .spd_release    = buffer_spd_release,
        };
        struct buffer_ref *ref;
-       int size, i;
+       int entries, size, i;
        size_t ret;
 
        if (*ppos & (PAGE_SIZE - 1)) {
@@ -3456,7 +3675,9 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                len &= PAGE_MASK;
        }
 
-       for (i = 0; i < PIPE_BUFFERS && len; i++, len -= PAGE_SIZE) {
+       entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu);
+
+       for (i = 0; i < PIPE_BUFFERS && len && entries; i++, len -= PAGE_SIZE) {
                struct page *page;
                int r;
 
@@ -3464,6 +3685,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                if (!ref)
                        break;
 
+               ref->ref = 1;
                ref->buffer = info->tr->buffer;
                ref->page = ring_buffer_alloc_read_page(ref->buffer);
                if (!ref->page) {
@@ -3472,7 +3694,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                }
 
                r = ring_buffer_read_page(ref->buffer, &ref->page,
-                                         len, info->cpu, 0);
+                                         len, info->cpu, 1);
                if (r < 0) {
                        ring_buffer_free_read_page(ref->buffer,
                                                   ref->page);
@@ -3496,6 +3718,8 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                spd.partial[i].private = (unsigned long)ref;
                spd.nr_pages++;
                *ppos += PAGE_SIZE;
+
+               entries = ring_buffer_entries_cpu(info->tr->buffer, info->cpu);
        }
 
        spd.nr_pages = i;
@@ -3523,6 +3747,42 @@ static const struct file_operations tracing_buffers_fops = {
        .llseek         = no_llseek,
 };
 
+static ssize_t
+tracing_stats_read(struct file *filp, char __user *ubuf,
+                  size_t count, loff_t *ppos)
+{
+       unsigned long cpu = (unsigned long)filp->private_data;
+       struct trace_array *tr = &global_trace;
+       struct trace_seq *s;
+       unsigned long cnt;
+
+       s = kmalloc(sizeof(*s), GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+
+       trace_seq_init(s);
+
+       cnt = ring_buffer_entries_cpu(tr->buffer, cpu);
+       trace_seq_printf(s, "entries: %ld\n", cnt);
+
+       cnt = ring_buffer_overrun_cpu(tr->buffer, cpu);
+       trace_seq_printf(s, "overrun: %ld\n", cnt);
+
+       cnt = ring_buffer_commit_overrun_cpu(tr->buffer, cpu);
+       trace_seq_printf(s, "commit overrun: %ld\n", cnt);
+
+       count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len);
+
+       kfree(s);
+
+       return count;
+}
+
+static const struct file_operations tracing_stats_fops = {
+       .open           = tracing_open_generic,
+       .read           = tracing_stats_read,
+};
+
 #ifdef CONFIG_DYNAMIC_FTRACE
 
 int __weak ftrace_arch_read_dyn_info(char *buf, int size)
@@ -3636,6 +3896,9 @@ static void tracing_init_debugfs_percpu(long cpu)
 
        trace_create_file("trace_pipe_raw", 0444, d_cpu,
                        (void *) cpu, &tracing_buffers_fops);
+
+       trace_create_file("stats", 0444, d_cpu,
+                       (void *) cpu, &tracing_stats_fops);
 }
 
 #ifdef CONFIG_FTRACE_SELFTEST
@@ -3768,17 +4031,9 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
        if (ret < 0)
                return ret;
 
-       switch (val) {
-       case 0:
-               trace_flags &= ~(1 << index);
-               break;
-       case 1:
-               trace_flags |= 1 << index;
-               break;
-
-       default:
+       if (val != 0 && val != 1)
                return -EINVAL;
-       }
+       set_tracer_flags(1 << index, val);
 
        *ppos += cnt;
 
@@ -3943,16 +4198,18 @@ static __init int tracer_init_debugfs(void)
        trace_create_file("available_tracers", 0444, d_tracer,
                        &global_trace, &show_traces_fops);
 
-       trace_create_file("current_tracer", 0444, d_tracer,
+       trace_create_file("current_tracer", 0644, d_tracer,
                        &global_trace, &set_tracer_fops);
 
+#ifdef CONFIG_TRACER_MAX_TRACE
        trace_create_file("tracing_max_latency", 0644, d_tracer,
                        &tracing_max_latency, &tracing_max_lat_fops);
 
        trace_create_file("tracing_thresh", 0644, d_tracer,
                        &tracing_thresh, &tracing_max_lat_fops);
+#endif
 
-       trace_create_file("README", 0644, d_tracer,
+       trace_create_file("README", 0444, d_tracer,
                        NULL, &tracing_readme_fops);
 
        trace_create_file("trace_pipe", 0444, d_tracer,
@@ -3964,6 +4221,12 @@ static __init int tracer_init_debugfs(void)
        trace_create_file("trace_marker", 0220, d_tracer,
                        NULL, &tracing_mark_fops);
 
+       trace_create_file("saved_cmdlines", 0444, d_tracer,
+                       NULL, &tracing_saved_cmdlines_fops);
+
+       trace_create_file("trace_clock", 0644, d_tracer, NULL,
+                         &trace_clock_fops);
+
 #ifdef CONFIG_DYNAMIC_FTRACE
        trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
                        &ftrace_update_tot_cnt, &tracing_dyn_info_fops);
@@ -4044,7 +4307,8 @@ trace_printk_seq(struct trace_seq *s)
 
 static void __ftrace_dump(bool disable_tracing)
 {
-       static DEFINE_SPINLOCK(ftrace_dump_lock);
+       static arch_spinlock_t ftrace_dump_lock =
+               (arch_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
        /* use static because iter can be a bit big for the stack */
        static struct trace_iterator iter;
        unsigned int old_userobj;
@@ -4053,7 +4317,8 @@ static void __ftrace_dump(bool disable_tracing)
        int cnt = 0, cpu;
 
        /* only one dump */
-       spin_lock_irqsave(&ftrace_dump_lock, flags);
+       local_irq_save(flags);
+       __raw_spin_lock(&ftrace_dump_lock);
        if (dump_ran)
                goto out;
 
@@ -4102,8 +4367,11 @@ static void __ftrace_dump(bool disable_tracing)
                iter.pos = -1;
 
                if (find_next_entry_inc(&iter) != NULL) {
-                       print_trace_line(&iter);
-                       trace_consume(&iter);
+                       int ret;
+
+                       ret = print_trace_line(&iter);
+                       if (ret != TRACE_TYPE_NO_CONSUME)
+                               trace_consume(&iter);
                }
 
                trace_printk_seq(&iter.seq);
@@ -4125,7 +4393,8 @@ static void __ftrace_dump(bool disable_tracing)
        }
 
  out:
-       spin_unlock_irqrestore(&ftrace_dump_lock, flags);
+       __raw_spin_unlock(&ftrace_dump_lock);
+       local_irq_restore(flags);
 }
 
 /* By default: disable tracing after the dump */
@@ -4136,7 +4405,6 @@ void ftrace_dump(void)
 
 __init static int tracer_alloc_buffers(void)
 {
-       struct trace_array_cpu *data;
        int ring_buf_size;
        int i;
        int ret = -ENOMEM;
@@ -4147,7 +4415,7 @@ __init static int tracer_alloc_buffers(void)
        if (!alloc_cpumask_var(&tracing_cpumask, GFP_KERNEL))
                goto out_free_buffer_mask;
 
-       if (!alloc_cpumask_var(&tracing_reader_cpumask, GFP_KERNEL))
+       if (!zalloc_cpumask_var(&tracing_reader_cpumask, GFP_KERNEL))
                goto out_free_tracing_cpumask;
 
        /* To save memory, keep the ring buffer size to its minimum */
@@ -4158,7 +4426,6 @@ __init static int tracer_alloc_buffers(void)
 
        cpumask_copy(tracing_buffer_mask, cpu_possible_mask);
        cpumask_copy(tracing_cpumask, cpu_all_mask);
-       cpumask_clear(tracing_reader_cpumask);
 
        /* TODO: make the number of buffers hot pluggable with CPUS */
        global_trace.buffer = ring_buffer_alloc(ring_buf_size,
@@ -4186,8 +4453,8 @@ __init static int tracer_alloc_buffers(void)
 
        /* Allocate the first page for all buffers */
        for_each_tracing_cpu(i) {
-               data = global_trace.data[i] = &per_cpu(global_trace_cpu, i);
-               max_tr.data[i] = &per_cpu(max_data, i);
+               global_trace.data[i] = &per_cpu(global_trace_cpu, i);
+               max_tr.data[i] = &per_cpu(max_tr_data, i);
        }
 
        trace_init_cmdlines();