tracing: Remove unnecessary WARN_ONCE's from tracing_buffers_splice_read
[cascardo/linux.git] / kernel / trace / trace.c
index 37d1c70..5bc3590 100644 (file)
@@ -155,6 +155,18 @@ static int __init set_ftrace_dump_on_oops(char *str)
 }
 __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops);
 
+
+static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata;
+static char *trace_boot_options __initdata;
+
+static int __init set_trace_boot_options(char *str)
+{
+       strncpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
+       trace_boot_options = trace_boot_options_buf;
+       return 0;
+}
+__setup("trace_options=", set_trace_boot_options);
+
 unsigned long long ns2usecs(cycle_t nsec)
 {
        nsec += 500;
@@ -472,10 +484,12 @@ static const char *trace_options[] = {
 static struct {
        u64 (*func)(void);
        const char *name;
+       int in_ns;              /* is this clock in nanoseconds? */
 } trace_clocks[] = {
-       { trace_clock_local,    "local" },
-       { trace_clock_global,   "global" },
-       { trace_clock_counter,  "counter" },
+       { trace_clock_local,    "local",        1 },
+       { trace_clock_global,   "global",       1 },
+       { trace_clock_counter,  "counter",      0 },
+       ARCH_TRACE_CLOCKS
 };
 
 int trace_clock_id;
@@ -2465,6 +2479,10 @@ __tracing_open(struct inode *inode, struct file *file)
        if (ring_buffer_overruns(iter->tr->buffer))
                iter->iter_flags |= TRACE_FILE_ANNOTATE;
 
+       /* Output in nanoseconds only if we are using a clock in nanoseconds. */
+       if (trace_clocks[trace_clock_id].in_ns)
+               iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
+
        /* stop the trace while dumping */
        tracing_stop();
 
@@ -2838,24 +2856,14 @@ static void set_tracer_flags(unsigned int mask, int enabled)
                trace_printk_start_stop_comm(enabled);
 }
 
-static ssize_t
-tracing_trace_options_write(struct file *filp, const char __user *ubuf,
-                       size_t cnt, loff_t *ppos)
+static int trace_set_options(char *option)
 {
-       char buf[64];
        char *cmp;
        int neg = 0;
-       int ret;
+       int ret = 0;
        int i;
 
-       if (cnt >= sizeof(buf))
-               return -EINVAL;
-
-       if (copy_from_user(&buf, ubuf, cnt))
-               return -EFAULT;
-
-       buf[cnt] = 0;
-       cmp = strstrip(buf);
+       cmp = strstrip(option);
 
        if (strncmp(cmp, "no", 2) == 0) {
                neg = 1;
@@ -2874,10 +2882,25 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
                mutex_lock(&trace_types_lock);
                ret = set_tracer_option(current_trace, cmp, neg);
                mutex_unlock(&trace_types_lock);
-               if (ret)
-                       return ret;
        }
 
+       return ret;
+}
+
+static ssize_t
+tracing_trace_options_write(struct file *filp, const char __user *ubuf,
+                       size_t cnt, loff_t *ppos)
+{
+       char buf[64];
+
+       if (cnt >= sizeof(buf))
+               return -EINVAL;
+
+       if (copy_from_user(&buf, ubuf, cnt))
+               return -EFAULT;
+
+       trace_set_options(buf);
+
        *ppos += cnt;
 
        return cnt;
@@ -3011,6 +3034,31 @@ static void set_buffer_entries(struct trace_array *tr, unsigned long val)
                tr->data[cpu]->entries = val;
 }
 
+/* resize @tr's buffer to the size of @size_tr's entries */
+static int resize_buffer_duplicate_size(struct trace_array *tr,
+                                       struct trace_array *size_tr, int cpu_id)
+{
+       int cpu, ret = 0;
+
+       if (cpu_id == RING_BUFFER_ALL_CPUS) {
+               for_each_tracing_cpu(cpu) {
+                       ret = ring_buffer_resize(tr->buffer,
+                                       size_tr->data[cpu]->entries, cpu);
+                       if (ret < 0)
+                               break;
+                       tr->data[cpu]->entries = size_tr->data[cpu]->entries;
+               }
+       } else {
+               ret = ring_buffer_resize(tr->buffer,
+                                       size_tr->data[cpu_id]->entries, cpu_id);
+               if (ret == 0)
+                       tr->data[cpu_id]->entries =
+                               size_tr->data[cpu_id]->entries;
+       }
+
+       return ret;
+}
+
 static int __tracing_resize_ring_buffer(unsigned long size, int cpu)
 {
        int ret;
@@ -3035,23 +3083,8 @@ static int __tracing_resize_ring_buffer(unsigned long size, int cpu)
 
        ret = ring_buffer_resize(max_tr.buffer, size, cpu);
        if (ret < 0) {
-               int r = 0;
-
-               if (cpu == RING_BUFFER_ALL_CPUS) {
-                       int i;
-                       for_each_tracing_cpu(i) {
-                               r = ring_buffer_resize(global_trace.buffer,
-                                               global_trace.data[i]->entries,
-                                               i);
-                               if (r < 0)
-                                       break;
-                       }
-               } else {
-                       r = ring_buffer_resize(global_trace.buffer,
-                                               global_trace.data[cpu]->entries,
-                                               cpu);
-               }
-
+               int r = resize_buffer_duplicate_size(&global_trace,
+                                                    &global_trace, cpu);
                if (r < 0) {
                        /*
                         * AARGH! We are left with different
@@ -3189,17 +3222,11 @@ static int tracing_set_tracer(const char *buf)
 
        topts = create_trace_option_files(t);
        if (t->use_max_tr) {
-               int cpu;
                /* we need to make per cpu buffer sizes equivalent */
-               for_each_tracing_cpu(cpu) {
-                       ret = ring_buffer_resize(max_tr.buffer,
-                                               global_trace.data[cpu]->entries,
-                                               cpu);
-                       if (ret < 0)
-                               goto out;
-                       max_tr.data[cpu]->entries =
-                                       global_trace.data[cpu]->entries;
-               }
+               ret = resize_buffer_duplicate_size(&max_tr, &global_trace,
+                                                  RING_BUFFER_ALL_CPUS);
+               if (ret < 0)
+                       goto out;
        }
 
        if (t->init) {
@@ -3321,6 +3348,10 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
        if (trace_flags & TRACE_ITER_LATENCY_FMT)
                iter->iter_flags |= TRACE_FILE_LAT_FMT;
 
+       /* Output in nanoseconds only if we are using a clock in nanoseconds. */
+       if (trace_clocks[trace_clock_id].in_ns)
+               iter->iter_flags |= TRACE_FILE_TIME_IN_NS;
+
        iter->cpu_file = cpu_file;
        iter->tr = &global_trace;
        mutex_init(&iter->mutex);
@@ -4244,13 +4275,11 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                return -ENOMEM;
 
        if (*ppos & (PAGE_SIZE - 1)) {
-               WARN_ONCE(1, "Ftrace: previous read must page-align\n");
                ret = -EINVAL;
                goto out;
        }
 
        if (len & (PAGE_SIZE - 1)) {
-               WARN_ONCE(1, "Ftrace: splice_read should page-align\n");
                if (len < PAGE_SIZE) {
                        ret = -EINVAL;
                        goto out;
@@ -4361,13 +4390,24 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
        cnt = ring_buffer_bytes_cpu(tr->buffer, cpu);
        trace_seq_printf(s, "bytes: %ld\n", cnt);
 
-       t = ns2usecs(ring_buffer_oldest_event_ts(tr->buffer, cpu));
-       usec_rem = do_div(t, USEC_PER_SEC);
-       trace_seq_printf(s, "oldest event ts: %5llu.%06lu\n", t, usec_rem);
+       if (trace_clocks[trace_clock_id].in_ns) {
+               /* local or global for trace_clock */
+               t = ns2usecs(ring_buffer_oldest_event_ts(tr->buffer, cpu));
+               usec_rem = do_div(t, USEC_PER_SEC);
+               trace_seq_printf(s, "oldest event ts: %5llu.%06lu\n",
+                                                               t, usec_rem);
+
+               t = ns2usecs(ring_buffer_time_stamp(tr->buffer, cpu));
+               usec_rem = do_div(t, USEC_PER_SEC);
+               trace_seq_printf(s, "now ts: %5llu.%06lu\n", t, usec_rem);
+       } else {
+               /* counter or tsc mode for trace_clock */
+               trace_seq_printf(s, "oldest event ts: %llu\n",
+                               ring_buffer_oldest_event_ts(tr->buffer, cpu));
 
-       t = ns2usecs(ring_buffer_time_stamp(tr->buffer, cpu));
-       usec_rem = do_div(t, USEC_PER_SEC);
-       trace_seq_printf(s, "now ts: %5llu.%06lu\n", t, usec_rem);
+               trace_seq_printf(s, "now ts: %llu\n",
+                               ring_buffer_time_stamp(tr->buffer, cpu));
+       }
 
        cnt = ring_buffer_dropped_events_cpu(tr->buffer, cpu);
        trace_seq_printf(s, "dropped events: %ld\n", cnt);
@@ -5133,6 +5173,13 @@ __init static int tracer_alloc_buffers(void)
 
        register_die_notifier(&trace_die_notifier);
 
+       while (trace_boot_options) {
+               char *option;
+
+               option = strsep(&trace_boot_options, ",");
+               trace_set_options(option);
+       }
+
        return 0;
 
 out_free_cpumask: