Skip to content

Commit 7e9fbbb

Browse files
committed
ring-buffer: Add ring_buffer_wake_waiters()
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/[email protected] Cc: [email protected] Cc: Ingo Molnar <[email protected]> Cc: Andrew Morton <[email protected]> Fixes: 1569345 ("tracing/ring-buffer: Move poll wake ups into ring buffer code") Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent ec0bbc5 commit 7e9fbbb

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

include/linux/ring_buffer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ __ring_buffer_alloc(unsigned long size, unsigned flags, struct lock_class_key *k
101101
int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full);
102102
__poll_t ring_buffer_poll_wait(struct trace_buffer *buffer, int cpu,
103103
struct file *filp, poll_table *poll_table);
104-
104+
void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu);
105105

106106
#define RING_BUFFER_ALL_CPUS -1
107107

kernel/trace/ring_buffer.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ struct rb_irq_work {
413413
struct irq_work work;
414414
wait_queue_head_t waiters;
415415
wait_queue_head_t full_waiters;
416+
long wait_index;
416417
bool waiters_pending;
417418
bool full_waiters_pending;
418419
bool wakeup_full;
@@ -924,6 +925,37 @@ static void rb_wake_up_waiters(struct irq_work *work)
924925
}
925926
}
926927

928+
/**
929+
* ring_buffer_wake_waiters - wake up any waiters on this ring buffer
930+
* @buffer: The ring buffer to wake waiters on
931+
*
932+
* In the case of a file that represents a ring buffer is closing,
933+
* it is prudent to wake up any waiters that are on this.
934+
*/
935+
void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu)
936+
{
937+
struct ring_buffer_per_cpu *cpu_buffer;
938+
struct rb_irq_work *rbwork;
939+
940+
if (cpu == RING_BUFFER_ALL_CPUS) {
941+
942+
/* Wake up individual ones too. One level recursion */
943+
for_each_buffer_cpu(buffer, cpu)
944+
ring_buffer_wake_waiters(buffer, cpu);
945+
946+
rbwork = &buffer->irq_work;
947+
} else {
948+
cpu_buffer = buffer->buffers[cpu];
949+
rbwork = &cpu_buffer->irq_work;
950+
}
951+
952+
rbwork->wait_index++;
953+
/* make sure the waiters see the new index */
954+
smp_wmb();
955+
956+
rb_wake_up_waiters(&rbwork->work);
957+
}
958+
927959
/**
928960
* ring_buffer_wait - wait for input to the ring buffer
929961
* @buffer: buffer to wait on
@@ -939,6 +971,7 @@ int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full)
939971
struct ring_buffer_per_cpu *cpu_buffer;
940972
DEFINE_WAIT(wait);
941973
struct rb_irq_work *work;
974+
long wait_index;
942975
int ret = 0;
943976

944977
/*
@@ -957,6 +990,7 @@ int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full)
957990
work = &cpu_buffer->irq_work;
958991
}
959992

993+
wait_index = READ_ONCE(work->wait_index);
960994

961995
while (true) {
962996
if (full)
@@ -1021,6 +1055,11 @@ int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full)
10211055
}
10221056

10231057
schedule();
1058+
1059+
/* Make sure to see the new wait index */
1060+
smp_rmb();
1061+
if (wait_index != work->wait_index)
1062+
break;
10241063
}
10251064

10261065
if (full)

0 commit comments

Comments
 (0)