lkml.org 
[lkml]   [2022]   [Oct]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 109/530] ring-buffer: Add ring_buffer_wake_waiters()
    Date
    From: Steven Rostedt (Google) <rostedt@goodmis.org>

    commit 7e9fbbb1b776d8d7969551565bc246f74ec53b27 upstream.

    On closing of a file that represents a ring buffer or flushing the file,
    there may be waiters on the ring buffer that needs to be woken up and exit
    the ring_buffer_wait() function.

    Add ring_buffer_wake_waiters() to wake up the waiters on the ring buffer
    and allow them to exit the wait loop.

    Link: https://lkml.kernel.org/r/20220928133938.28dc2c27@gandalf.local.home

    Cc: stable@vger.kernel.org
    Cc: Ingo Molnar <mingo@kernel.org>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Fixes: 15693458c4bc0 ("tracing/ring-buffer: Move poll wake ups into ring buffer code")
    Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    include/linux/ring_buffer.h | 2 +-
    kernel/trace/ring_buffer.c | 39 +++++++++++++++++++++++++++++++++++++++
    2 files changed, 40 insertions(+), 1 deletion(-)

    --- a/include/linux/ring_buffer.h
    +++ b/include/linux/ring_buffer.h
    @@ -101,7 +101,7 @@ __ring_buffer_alloc(unsigned long size,
    int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full);
    __poll_t ring_buffer_poll_wait(struct trace_buffer *buffer, int cpu,
    struct file *filp, poll_table *poll_table);
    -
    +void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu);

    #define RING_BUFFER_ALL_CPUS -1

    --- a/kernel/trace/ring_buffer.c
    +++ b/kernel/trace/ring_buffer.c
    @@ -405,6 +405,7 @@ struct rb_irq_work {
    struct irq_work work;
    wait_queue_head_t waiters;
    wait_queue_head_t full_waiters;
    + long wait_index;
    bool waiters_pending;
    bool full_waiters_pending;
    bool wakeup_full;
    @@ -889,6 +890,37 @@ static void rb_wake_up_waiters(struct ir
    }

    /**
    + * ring_buffer_wake_waiters - wake up any waiters on this ring buffer
    + * @buffer: The ring buffer to wake waiters on
    + *
    + * In the case of a file that represents a ring buffer is closing,
    + * it is prudent to wake up any waiters that are on this.
    + */
    +void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu)
    +{
    + struct ring_buffer_per_cpu *cpu_buffer;
    + struct rb_irq_work *rbwork;
    +
    + if (cpu == RING_BUFFER_ALL_CPUS) {
    +
    + /* Wake up individual ones too. One level recursion */
    + for_each_buffer_cpu(buffer, cpu)
    + ring_buffer_wake_waiters(buffer, cpu);
    +
    + rbwork = &buffer->irq_work;
    + } else {
    + cpu_buffer = buffer->buffers[cpu];
    + rbwork = &cpu_buffer->irq_work;
    + }
    +
    + rbwork->wait_index++;
    + /* make sure the waiters see the new index */
    + smp_wmb();
    +
    + rb_wake_up_waiters(&rbwork->work);
    +}
    +
    +/**
    * ring_buffer_wait - wait for input to the ring buffer
    * @buffer: buffer to wait on
    * @cpu: the cpu buffer to wait on
    @@ -903,6 +935,7 @@ int ring_buffer_wait(struct trace_buffer
    struct ring_buffer_per_cpu *cpu_buffer;
    DEFINE_WAIT(wait);
    struct rb_irq_work *work;
    + long wait_index;
    int ret = 0;

    /*
    @@ -921,6 +954,7 @@ int ring_buffer_wait(struct trace_buffer
    work = &cpu_buffer->irq_work;
    }

    + wait_index = READ_ONCE(work->wait_index);

    while (true) {
    if (full)
    @@ -985,6 +1019,11 @@ int ring_buffer_wait(struct trace_buffer
    }

    schedule();
    +
    + /* Make sure to see the new wait index */
    + smp_rmb();
    + if (wait_index != work->wait_index)
    + break;
    }

    if (full)

    \
     
     \ /
      Last update: 2022-10-24 15:43    [W:4.035 / U:0.088 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site