tracing: Wake up ring buffer waiters on closing of the file
authorSteven Rostedt (Google) <rostedt@goodmis.org>
Tue, 27 Sep 2022 23:15:27 +0000 (19:15 -0400)
committerSteven Rostedt (Google) <rostedt@goodmis.org>
Thu, 29 Sep 2022 00:28:13 +0000 (20:28 -0400)
When the file that represents the ring buffer is closed, there may be
waiters waiting on more input from the ring buffer. Call
ring_buffer_wake_waiters() to wake up any waiters when the file is
closed.

Link: https://lkml.kernel.org/r/20220927231825.182416969@goodmis.org
Cc: stable@vger.kernel.org
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Fixes: e30f53aad2202 ("tracing: Do not busy wait in buffer splice")
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
include/linux/trace_events.h
kernel/trace/trace.c

index 8401dec..20749bd 100644 (file)
@@ -92,6 +92,7 @@ struct trace_iterator {
        unsigned int            temp_size;
        char                    *fmt;   /* modified format holder */
        unsigned int            fmt_size;
+       long                    wait_index;
 
        /* trace_seq for __print_flags() and __print_symbolic() etc. */
        struct trace_seq        tmp_seq;
index aed7ea6..e101b07 100644 (file)
@@ -8160,6 +8160,12 @@ static int tracing_buffers_release(struct inode *inode, struct file *file)
 
        __trace_array_put(iter->tr);
 
+       iter->wait_index++;
+       /* Make sure the waiters see the new wait_index */
+       smp_wmb();
+
+       ring_buffer_wake_waiters(iter->array_buffer->buffer, iter->cpu_file);
+
        if (info->spare)
                ring_buffer_free_read_page(iter->array_buffer->buffer,
                                           info->spare_cpu, info->spare);
@@ -8313,6 +8319,8 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
 
        /* did we read anything? */
        if (!spd.nr_pages) {
+               long wait_index;
+
                if (ret)
                        goto out;
 
@@ -8320,10 +8328,17 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
                if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK))
                        goto out;
 
+               wait_index = READ_ONCE(iter->wait_index);
+
                ret = wait_on_pipe(iter, iter->tr->buffer_percent);
                if (ret)
                        goto out;
 
+               /* Make sure we see the new wait_index */
+               smp_rmb();
+               if (wait_index != iter->wait_index)
+                       goto out;
+
                goto again;
        }