Skip to content

Commit e5d7c19

Browse files
committed
tracing: Use .flush() call to wake up readers
The .release() function does not get called until all readers of a file descriptor are finished. If a thread is blocked on reading a file descriptor in ring_buffer_wait(), and another thread closes the file descriptor, it will not wake up the other thread as ring_buffer_wake_waiters() is called by .release(), and that will not get called until the .read() is finished. The issue originally showed up in trace-cmd, but the readers are actually other processes with their own file descriptors. So calling close() would wake up the other tasks because they are blocked on another descriptor then the one that was closed(). But there's other wake ups that solve that issue. When a thread is blocked on a read, it can still hang even when another thread closed its descriptor. This is what the .flush() callback is for. Have the .flush() wake up the readers. Link: https://lore.kernel.org/linux-trace-kernel/[email protected] Cc: [email protected] Cc: Masami Hiramatsu <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: linke li <[email protected]> Cc: Rabin Vincent <[email protected]> Fixes: f3ddb74 ("tracing: Wake up ring buffer waiters on closing of the file") Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 68282dd commit e5d7c19

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

kernel/trace/trace.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8393,6 +8393,20 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
83938393
return size;
83948394
}
83958395

8396+
static int tracing_buffers_flush(struct file *file, fl_owner_t id)
8397+
{
8398+
struct ftrace_buffer_info *info = file->private_data;
8399+
struct trace_iterator *iter = &info->iter;
8400+
8401+
iter->wait_index++;
8402+
/* Make sure the waiters see the new wait_index */
8403+
smp_wmb();
8404+
8405+
ring_buffer_wake_waiters(iter->array_buffer->buffer, iter->cpu_file);
8406+
8407+
return 0;
8408+
}
8409+
83968410
static int tracing_buffers_release(struct inode *inode, struct file *file)
83978411
{
83988412
struct ftrace_buffer_info *info = file->private_data;
@@ -8404,12 +8418,6 @@ static int tracing_buffers_release(struct inode *inode, struct file *file)
84048418

84058419
__trace_array_put(iter->tr);
84068420

8407-
iter->wait_index++;
8408-
/* Make sure the waiters see the new wait_index */
8409-
smp_wmb();
8410-
8411-
ring_buffer_wake_waiters(iter->array_buffer->buffer, iter->cpu_file);
8412-
84138421
if (info->spare)
84148422
ring_buffer_free_read_page(iter->array_buffer->buffer,
84158423
info->spare_cpu, info->spare);
@@ -8625,6 +8633,7 @@ static const struct file_operations tracing_buffers_fops = {
86258633
.read = tracing_buffers_read,
86268634
.poll = tracing_buffers_poll,
86278635
.release = tracing_buffers_release,
8636+
.flush = tracing_buffers_flush,
86288637
.splice_read = tracing_buffers_splice_read,
86298638
.unlocked_ioctl = tracing_buffers_ioctl,
86308639
.llseek = no_llseek,

0 commit comments

Comments
 (0)