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 e890d2d..2e76797 100644 (file)
@@ -950,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;
 }
 
@@ -1088,13 +1089,14 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
 }
 #endif /* CONFIG_TRACER_MAX_TRACE */
 
-static int wait_on_pipe(struct trace_iterator *iter)
+static int wait_on_pipe(struct trace_iterator *iter, bool full)
 {
        /* Iterators are static, they should be filled or empty */
        if (trace_buffer_iter(iter, iter->cpu_file))
                return 0;
 
-       return ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file);
+       return ring_buffer_wait(iter->trace_buffer->buffer, iter->cpu_file,
+                               full);
 }
 
 #ifdef CONFIG_FTRACE_STARTUP_TEST
@@ -2040,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");
@@ -4323,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.
@@ -4444,15 +4448,12 @@ static int tracing_wait_pipe(struct file *filp)
 
                mutex_unlock(&iter->mutex);
 
-               ret = wait_on_pipe(iter);
+               ret = wait_on_pipe(iter, false);
 
                mutex_lock(&iter->mutex);
 
                if (ret)
                        return ret;
-
-               if (signal_pending(current))
-                       return -EINTR;
        }
 
        return 1;
@@ -4519,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;
 
                /*
@@ -4546,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);
 
        /*
@@ -4580,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;
                }
 
@@ -4674,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);
        }
@@ -5382,16 +5396,12 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
                                goto out_unlock;
                        }
                        mutex_unlock(&trace_types_lock);
-                       ret = wait_on_pipe(iter);
+                       ret = wait_on_pipe(iter, false);
                        mutex_lock(&trace_types_lock);
                        if (ret) {
                                size = ret;
                                goto out_unlock;
                        }
-                       if (signal_pending(current)) {
-                               size = -EINTR;
-                               goto out_unlock;
-                       }
                        goto again;
                }
                size = 0;
@@ -5510,7 +5520,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
        };
        struct buffer_ref *ref;
        int entries, size, i;
-       ssize_t ret;
+       ssize_t ret = 0;
 
        mutex_lock(&trace_types_lock);
 
@@ -5548,13 +5558,16 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                int r;
 
                ref = kzalloc(sizeof(*ref), GFP_KERNEL);
-               if (!ref)
+               if (!ref) {
+                       ret = -ENOMEM;
                        break;
+               }
 
                ref->ref = 1;
                ref->buffer = iter->trace_buffer->buffer;
                ref->page = ring_buffer_alloc_read_page(ref->buffer, iter->cpu_file);
                if (!ref->page) {
+                       ret = -ENOMEM;
                        kfree(ref);
                        break;
                }
@@ -5592,19 +5605,19 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 
        /* did we read anything? */
        if (!spd.nr_pages) {
+               if (ret)
+                       goto out;
+
                if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK)) {
                        ret = -EAGAIN;
                        goto out;
                }
                mutex_unlock(&trace_types_lock);
-               ret = wait_on_pipe(iter);
+               ret = wait_on_pipe(iter, true);
                mutex_lock(&trace_types_lock);
                if (ret)
                        goto out;
-               if (signal_pending(current)) {
-                       ret = -EINTR;
-                       goto out;
-               }
+
                goto again;
        }
 
@@ -5681,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);
 
@@ -6430,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;
 
@@ -6457,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;
 
@@ -6644,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);