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/20240308202432.107909457@goodmis.org

Cc: stable@vger.kernel.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: linke li <lilinke99@qq.com>
Cc: Rabin Vincent <rabin@rab.in>
Fixes: f3ddb74ad0790 ("tracing: Wake up ring buffer waiters on closing of the file")
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

Changed files
+15 -6
kernel
trace
+15 -6
kernel/trace/trace.c
··· 8393 8393 return size; 8394 8394 } 8395 8395 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 + 8396 8410 static int tracing_buffers_release(struct inode *inode, struct file *file) 8397 8411 { 8398 8412 struct ftrace_buffer_info *info = file->private_data; ··· 8417 8403 iter->tr->trace_ref--; 8418 8404 8419 8405 __trace_array_put(iter->tr); 8420 - 8421 - iter->wait_index++; 8422 - /* Make sure the waiters see the new wait_index */ 8423 - smp_wmb(); 8424 - 8425 - ring_buffer_wake_waiters(iter->array_buffer->buffer, iter->cpu_file); 8426 8406 8427 8407 if (info->spare) 8428 8408 ring_buffer_free_read_page(iter->array_buffer->buffer, ··· 8633 8625 .read = tracing_buffers_read, 8634 8626 .poll = tracing_buffers_poll, 8635 8627 .release = tracing_buffers_release, 8628 + .flush = tracing_buffers_flush, 8636 8629 .splice_read = tracing_buffers_splice_read, 8637 8630 .unlocked_ioctl = tracing_buffers_ioctl, 8638 8631 .llseek = no_llseek,