Merge tag 'trace-3.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[cascardo/linux.git] / kernel / trace / trace.c
index 92f4a6c..2e76797 100644 (file)
@@ -63,6 +63,10 @@ static bool __read_mostly tracing_selftest_running;
  */
 bool __read_mostly tracing_selftest_disabled;
 
+/* Pipe tracepoints to printk */
+struct trace_iterator *tracepoint_print_iter;
+int tracepoint_printk;
+
 /* For tracers that don't implement custom flags */
 static struct tracer_opt dummy_tracer_opt[] = {
        { }
@@ -155,10 +159,11 @@ __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops);
 
 static int __init stop_trace_on_warning(char *str)
 {
-       __disable_trace_on_warning = 1;
+       if ((strcmp(str, "=0") != 0 && strcmp(str, "=off") != 0))
+               __disable_trace_on_warning = 1;
        return 1;
 }
-__setup("traceoff_on_warning=", stop_trace_on_warning);
+__setup("traceoff_on_warning", stop_trace_on_warning);
 
 static int __init boot_alloc_snapshot(char *str)
 {
@@ -192,6 +197,13 @@ static int __init set_trace_boot_clock(char *str)
 }
 __setup("trace_clock=", set_trace_boot_clock);
 
+static int __init set_tracepoint_printk(char *str)
+{
+       if ((strcmp(str, "=0") != 0 && strcmp(str, "=off") != 0))
+               tracepoint_printk = 1;
+       return 1;
+}
+__setup("tp_printk", set_tracepoint_printk);
 
 unsigned long long ns2usecs(cycle_t nsec)
 {
@@ -938,19 +950,20 @@ out:
        return ret;
 }
 
+/* TODO add a seq_buf_to_buffer() */
 static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
 {
        int len;
 
-       if (s->len <= s->readpos)
+       if (trace_seq_used(s) <= s->seq.readpos)
                return -EBUSY;
 
-       len = s->len - s->readpos;
+       len = trace_seq_used(s) - s->seq.readpos;
        if (cnt > len)
                cnt = len;
-       memcpy(buf, s->buffer + s->readpos, cnt);
+       memcpy(buf, s->buffer + s->seq.readpos, cnt);
 
-       s->readpos += cnt;
+       s->seq.readpos += cnt;
        return cnt;
 }
 
@@ -2029,7 +2042,7 @@ void trace_printk_init_buffers(void)
        pr_warning("** trace_printk() being used. Allocating extra memory.  **\n");
        pr_warning("**                                                      **\n");
        pr_warning("** This means that this is a DEBUG kernel and it is     **\n");
-       pr_warning("** unsafe for produciton use.                           **\n");
+       pr_warning("** unsafe for production use.                           **\n");
        pr_warning("**                                                      **\n");
        pr_warning("** If you see this message and you are not debugging    **\n");
        pr_warning("** the kernel, report this immediately to your vendor!  **\n");
@@ -2158,9 +2171,7 @@ __trace_array_vprintk(struct ring_buffer *buffer,
                goto out;
        }
 
-       len = vsnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);
-       if (len > TRACE_BUF_SIZE)
-               goto out;
+       len = vscnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);
 
        local_save_flags(flags);
        size = sizeof(*entry) + len + 1;
@@ -2171,8 +2182,7 @@ __trace_array_vprintk(struct ring_buffer *buffer,
        entry = ring_buffer_event_data(event);
        entry->ip = ip;
 
-       memcpy(&entry->buf, tbuffer, len);
-       entry->buf[len] = '\0';
+       memcpy(&entry->buf, tbuffer, len + 1);
        if (!call_filter_check_discard(call, entry, buffer, event)) {
                __buffer_unlock_commit(buffer, event);
                ftrace_trace_stack(buffer, flags, 6, pc);
@@ -2509,14 +2519,14 @@ get_total_entries(struct trace_buffer *buf,
 
 static void print_lat_help_header(struct seq_file *m)
 {
-       seq_puts(m, "#                  _------=> CPU#            \n");
-       seq_puts(m, "#                 / _-----=> irqs-off        \n");
-       seq_puts(m, "#                | / _----=> need-resched    \n");
-       seq_puts(m, "#                || / _---=> hardirq/softirq \n");
-       seq_puts(m, "#                ||| / _--=> preempt-depth   \n");
-       seq_puts(m, "#                |||| /     delay             \n");
-       seq_puts(m, "#  cmd     pid   ||||| time  |   caller      \n");
-       seq_puts(m, "#     \\   /      |||||  \\    |   /           \n");
+       seq_puts(m, "#                  _------=> CPU#            \n"
+                   "#                 / _-----=> irqs-off        \n"
+                   "#                | / _----=> need-resched    \n"
+                   "#                || / _---=> hardirq/softirq \n"
+                   "#                ||| / _--=> preempt-depth   \n"
+                   "#                |||| /     delay            \n"
+                   "#  cmd     pid   ||||| time  |   caller      \n"
+                   "#     \\   /      |||||  \\    |   /         \n");
 }
 
 static void print_event_info(struct trace_buffer *buf, struct seq_file *m)
@@ -2533,20 +2543,20 @@ static void print_event_info(struct trace_buffer *buf, struct seq_file *m)
 static void print_func_help_header(struct trace_buffer *buf, struct seq_file *m)
 {
        print_event_info(buf, m);
-       seq_puts(m, "#           TASK-PID   CPU#      TIMESTAMP  FUNCTION\n");
-       seq_puts(m, "#              | |       |          |         |\n");
+       seq_puts(m, "#           TASK-PID   CPU#      TIMESTAMP  FUNCTION\n"
+                   "#              | |       |          |         |\n");
 }
 
 static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file *m)
 {
        print_event_info(buf, m);
-       seq_puts(m, "#                              _-----=> irqs-off\n");
-       seq_puts(m, "#                             / _----=> need-resched\n");
-       seq_puts(m, "#                            | / _---=> hardirq/softirq\n");
-       seq_puts(m, "#                            || / _--=> preempt-depth\n");
-       seq_puts(m, "#                            ||| /     delay\n");
-       seq_puts(m, "#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION\n");
-       seq_puts(m, "#              | |       |   ||||       |         |\n");
+       seq_puts(m, "#                              _-----=> irqs-off\n"
+                   "#                             / _----=> need-resched\n"
+                   "#                            | / _---=> hardirq/softirq\n"
+                   "#                            || / _--=> preempt-depth\n"
+                   "#                            ||| /     delay\n"
+                   "#           TASK-PID   CPU#  ||||    TIMESTAMP  FUNCTION\n"
+                   "#              | |       |   ||||       |         |\n");
 }
 
 void
@@ -2649,24 +2659,21 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
        event = ftrace_find_event(entry->type);
 
        if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
-               if (iter->iter_flags & TRACE_FILE_LAT_FMT) {
-                       if (!trace_print_lat_context(iter))
-                               goto partial;
-               } else {
-                       if (!trace_print_context(iter))
-                               goto partial;
-               }
+               if (iter->iter_flags & TRACE_FILE_LAT_FMT)
+                       trace_print_lat_context(iter);
+               else
+                       trace_print_context(iter);
        }
 
+       if (trace_seq_has_overflowed(s))
+               return TRACE_TYPE_PARTIAL_LINE;
+
        if (event)
                return event->funcs->trace(iter, sym_flags, event);
 
-       if (!trace_seq_printf(s, "Unknown type %d\n", entry->type))
-               goto partial;
+       trace_seq_printf(s, "Unknown type %d\n", entry->type);
 
-       return TRACE_TYPE_HANDLED;
-partial:
-       return TRACE_TYPE_PARTIAL_LINE;
+       return trace_handle_return(s);
 }
 
 static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
@@ -2677,22 +2684,20 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter)
 
        entry = iter->ent;
 
-       if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
-               if (!trace_seq_printf(s, "%d %d %llu ",
-                                     entry->pid, iter->cpu, iter->ts))
-                       goto partial;
-       }
+       if (trace_flags & TRACE_ITER_CONTEXT_INFO)
+               trace_seq_printf(s, "%d %d %llu ",
+                                entry->pid, iter->cpu, iter->ts);
+
+       if (trace_seq_has_overflowed(s))
+               return TRACE_TYPE_PARTIAL_LINE;
 
        event = ftrace_find_event(entry->type);
        if (event)
                return event->funcs->raw(iter, 0, event);
 
-       if (!trace_seq_printf(s, "%d ?\n", entry->type))
-               goto partial;
+       trace_seq_printf(s, "%d ?\n", entry->type);
 
-       return TRACE_TYPE_HANDLED;
-partial:
-       return TRACE_TYPE_PARTIAL_LINE;
+       return trace_handle_return(s);
 }
 
 static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
@@ -2705,9 +2710,11 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
        entry = iter->ent;
 
        if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
-               SEQ_PUT_HEX_FIELD_RET(s, entry->pid);
-               SEQ_PUT_HEX_FIELD_RET(s, iter->cpu);
-               SEQ_PUT_HEX_FIELD_RET(s, iter->ts);
+               SEQ_PUT_HEX_FIELD(s, entry->pid);
+               SEQ_PUT_HEX_FIELD(s, iter->cpu);
+               SEQ_PUT_HEX_FIELD(s, iter->ts);
+               if (trace_seq_has_overflowed(s))
+                       return TRACE_TYPE_PARTIAL_LINE;
        }
 
        event = ftrace_find_event(entry->type);
@@ -2717,9 +2724,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter)
                        return ret;
        }
 
-       SEQ_PUT_FIELD_RET(s, newline);
+       SEQ_PUT_FIELD(s, newline);
 
-       return TRACE_TYPE_HANDLED;
+       return trace_handle_return(s);
 }
 
 static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
@@ -2731,9 +2738,11 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
        entry = iter->ent;
 
        if (trace_flags & TRACE_ITER_CONTEXT_INFO) {
-               SEQ_PUT_FIELD_RET(s, entry->pid);
-               SEQ_PUT_FIELD_RET(s, iter->cpu);
-               SEQ_PUT_FIELD_RET(s, iter->ts);
+               SEQ_PUT_FIELD(s, entry->pid);
+               SEQ_PUT_FIELD(s, iter->cpu);
+               SEQ_PUT_FIELD(s, iter->ts);
+               if (trace_seq_has_overflowed(s))
+                       return TRACE_TYPE_PARTIAL_LINE;
        }
 
        event = ftrace_find_event(entry->type);
@@ -2779,10 +2788,12 @@ enum print_line_t print_trace_line(struct trace_iterator *iter)
 {
        enum print_line_t ret;
 
-       if (iter->lost_events &&
-           !trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n",
-                                iter->cpu, iter->lost_events))
-               return TRACE_TYPE_PARTIAL_LINE;
+       if (iter->lost_events) {
+               trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n",
+                                iter->cpu, iter->lost_events);
+               if (trace_seq_has_overflowed(&iter->seq))
+                       return TRACE_TYPE_PARTIAL_LINE;
+       }
 
        if (iter->trace && iter->trace->print_line) {
                ret = iter->trace->print_line(iter);
@@ -2860,44 +2871,44 @@ static void test_ftrace_alive(struct seq_file *m)
 {
        if (!ftrace_is_dead())
                return;
-       seq_printf(m, "# WARNING: FUNCTION TRACING IS CORRUPTED\n");
-       seq_printf(m, "#          MAY BE MISSING FUNCTION EVENTS\n");
+       seq_puts(m, "# WARNING: FUNCTION TRACING IS CORRUPTED\n"
+                   "#          MAY BE MISSING FUNCTION EVENTS\n");
 }
 
 #ifdef CONFIG_TRACER_MAX_TRACE
 static void show_snapshot_main_help(struct seq_file *m)
 {
-       seq_printf(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n");
-       seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n");
-       seq_printf(m, "#                      Takes a snapshot of the main buffer.\n");
-       seq_printf(m, "# echo 2 > snapshot : Clears snapshot buffer (but does not allocate or free)\n");
-       seq_printf(m, "#                      (Doesn't have to be '2' works with any number that\n");
-       seq_printf(m, "#                       is not a '0' or '1')\n");
+       seq_puts(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n"
+                   "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n"
+                   "#                      Takes a snapshot of the main buffer.\n"
+                   "# echo 2 > snapshot : Clears snapshot buffer (but does not allocate or free)\n"
+                   "#                      (Doesn't have to be '2' works with any number that\n"
+                   "#                       is not a '0' or '1')\n");
 }
 
 static void show_snapshot_percpu_help(struct seq_file *m)
 {
-       seq_printf(m, "# echo 0 > snapshot : Invalid for per_cpu snapshot file.\n");
+       seq_puts(m, "# echo 0 > snapshot : Invalid for per_cpu snapshot file.\n");
 #ifdef CONFIG_RING_BUFFER_ALLOW_SWAP
-       seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n");
-       seq_printf(m, "#                      Takes a snapshot of the main buffer for this cpu.\n");
+       seq_puts(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n"
+                   "#                      Takes a snapshot of the main buffer for this cpu.\n");
 #else
-       seq_printf(m, "# echo 1 > snapshot : Not supported with this kernel.\n");
-       seq_printf(m, "#                     Must use main snapshot file to allocate.\n");
+       seq_puts(m, "# echo 1 > snapshot : Not supported with this kernel.\n"
+                   "#                     Must use main snapshot file to allocate.\n");
 #endif
-       seq_printf(m, "# echo 2 > snapshot : Clears this cpu's snapshot buffer (but does not allocate)\n");
-       seq_printf(m, "#                      (Doesn't have to be '2' works with any number that\n");
-       seq_printf(m, "#                       is not a '0' or '1')\n");
+       seq_puts(m, "# echo 2 > snapshot : Clears this cpu's snapshot buffer (but does not allocate)\n"
+                   "#                      (Doesn't have to be '2' works with any number that\n"
+                   "#                       is not a '0' or '1')\n");
 }
 
 static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter)
 {
        if (iter->tr->allocated_snapshot)
-               seq_printf(m, "#\n# * Snapshot is allocated *\n#\n");
+               seq_puts(m, "#\n# * Snapshot is allocated *\n#\n");
        else
-               seq_printf(m, "#\n# * Snapshot is freed *\n#\n");
+               seq_puts(m, "#\n# * Snapshot is freed *\n#\n");
 
-       seq_printf(m, "# Snapshot commands:\n");
+       seq_puts(m, "# Snapshot commands:\n");
        if (iter->cpu_file == RING_BUFFER_ALL_CPUS)
                show_snapshot_main_help(m);
        else
@@ -3251,7 +3262,7 @@ static int t_show(struct seq_file *m, void *v)
        if (!t)
                return 0;
 
-       seq_printf(m, "%s", t->name);
+       seq_puts(m, t->name);
        if (t->next)
                seq_putc(m, ' ');
        else
@@ -4314,6 +4325,8 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
                goto out;
        }
 
+       trace_seq_init(&iter->seq);
+
        /*
         * We make a copy of the current tracer to avoid concurrent
         * changes on it while we are reading.
@@ -4507,18 +4520,18 @@ waitagain:
        trace_access_lock(iter->cpu_file);
        while (trace_find_next_entry_inc(iter) != NULL) {
                enum print_line_t ret;
-               int len = iter->seq.len;
+               int save_len = iter->seq.seq.len;
 
                ret = print_trace_line(iter);
                if (ret == TRACE_TYPE_PARTIAL_LINE) {
                        /* don't print partial lines */
-                       iter->seq.len = len;
+                       iter->seq.seq.len = save_len;
                        break;
                }
                if (ret != TRACE_TYPE_NO_CONSUME)
                        trace_consume(iter);
 
-               if (iter->seq.len >= cnt)
+               if (trace_seq_used(&iter->seq) >= cnt)
                        break;
 
                /*
@@ -4534,7 +4547,7 @@ waitagain:
 
        /* Now copy what we have to the user */
        sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
-       if (iter->seq.readpos >= iter->seq.len)
+       if (iter->seq.seq.readpos >= trace_seq_used(&iter->seq))
                trace_seq_init(&iter->seq);
 
        /*
@@ -4568,20 +4581,33 @@ static size_t
 tracing_fill_pipe_page(size_t rem, struct trace_iterator *iter)
 {
        size_t count;
+       int save_len;
        int ret;
 
        /* Seq buffer is page-sized, exactly what we need. */
        for (;;) {
-               count = iter->seq.len;
+               save_len = iter->seq.seq.len;
                ret = print_trace_line(iter);
-               count = iter->seq.len - count;
-               if (rem < count) {
-                       rem = 0;
-                       iter->seq.len -= count;
+
+               if (trace_seq_has_overflowed(&iter->seq)) {
+                       iter->seq.seq.len = save_len;
                        break;
                }
+
+               /*
+                * This should not be hit, because it should only
+                * be set if the iter->seq overflowed. But check it
+                * anyway to be safe.
+                */
                if (ret == TRACE_TYPE_PARTIAL_LINE) {
-                       iter->seq.len -= count;
+                       iter->seq.seq.len = save_len;
+                       break;
+               }
+
+               count = trace_seq_used(&iter->seq) - save_len;
+               if (rem < count) {
+                       rem = 0;
+                       iter->seq.seq.len = save_len;
                        break;
                }
 
@@ -4662,13 +4688,13 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
                /* Copy the data into the page, so we can start over. */
                ret = trace_seq_to_buffer(&iter->seq,
                                          page_address(spd.pages[i]),
-                                         iter->seq.len);
+                                         trace_seq_used(&iter->seq));
                if (ret < 0) {
                        __free_page(spd.pages[i]);
                        break;
                }
                spd.partial[i].offset = 0;
-               spd.partial[i].len = iter->seq.len;
+               spd.partial[i].len = trace_seq_used(&iter->seq);
 
                trace_seq_init(&iter->seq);
        }
@@ -5668,7 +5694,8 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
        cnt = ring_buffer_read_events_cpu(trace_buf->buffer, cpu);
        trace_seq_printf(s, "read events: %ld\n", cnt);
 
-       count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->len);
+       count = simple_read_from_buffer(ubuf, count, ppos,
+                                       s->buffer, trace_seq_used(s));
 
        kfree(s);
 
@@ -5749,10 +5776,10 @@ ftrace_snapshot_print(struct seq_file *m, unsigned long ip,
 
        seq_printf(m, "%ps:", (void *)ip);
 
-       seq_printf(m, "snapshot");
+       seq_puts(m, "snapshot");
 
        if (count == -1)
-               seq_printf(m, ":unlimited\n");
+               seq_puts(m, ":unlimited\n");
        else
                seq_printf(m, ":count=%ld\n", count);
 
@@ -6417,7 +6444,7 @@ static int instance_mkdir (struct inode *inode, struct dentry *dentry, umode_t m
        int ret;
 
        /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
 
@@ -6444,7 +6471,7 @@ static int instance_rmdir(struct inode *inode, struct dentry *dentry)
        int ret;
 
        /* Paranoid: Make sure the parent is the "instances" directory */
-       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
+       parent = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias);
        if (WARN_ON_ONCE(parent != trace_instance_dir))
                return -ENOENT;
 
@@ -6631,11 +6658,19 @@ void
 trace_printk_seq(struct trace_seq *s)
 {
        /* Probably should print a warning here. */
-       if (s->len >= TRACE_MAX_PRINT)
-               s->len = TRACE_MAX_PRINT;
+       if (s->seq.len >= TRACE_MAX_PRINT)
+               s->seq.len = TRACE_MAX_PRINT;
+
+       /*
+        * More paranoid code. Although the buffer size is set to
+        * PAGE_SIZE, and TRACE_MAX_PRINT is 1000, this is just
+        * an extra layer of protection.
+        */
+       if (WARN_ON_ONCE(s->seq.len >= s->seq.size))
+               s->seq.len = s->seq.size - 1;
 
        /* should be zero ended, but we are paranoid. */
-       s->buffer[s->len] = 0;
+       s->buffer[s->seq.len] = 0;
 
        printk(KERN_TRACE "%s", s->buffer);
 
@@ -6874,6 +6909,19 @@ out:
        return ret;
 }
 
+void __init trace_init(void)
+{
+       if (tracepoint_printk) {
+               tracepoint_print_iter =
+                       kmalloc(sizeof(*tracepoint_print_iter), GFP_KERNEL);
+               if (WARN_ON(!tracepoint_print_iter))
+                       tracepoint_printk = 0;
+       }
+       tracer_alloc_buffers();
+       init_ftrace_syscalls();
+       trace_event_init();     
+}
+
 __init static int clear_boot_tracer(void)
 {
        /*
@@ -6893,6 +6941,5 @@ __init static int clear_boot_tracer(void)
        return 0;
 }
 
-early_initcall(tracer_alloc_buffers);
 fs_initcall(tracer_init_debugfs);
 late_initcall(clear_boot_tracer);