The snapshot operation currently uses smp_call_function_single() to invoke ring_buffer_swap_cpu() on the target CPU. Since interrupt can hit at any point during the write path, this may return -EBUSY if the target CPU is actively writing to the buffer, which could be confusing to users who may not understand the internal state of the ring buffer.
Replace smp_call_function_single() with work_on_cpu() for the snapshot operation. This ensures that the swap only occurs after the ongoing write completes. Signed-off-by: Tengda Wu <[email protected]> --- kernel/trace/trace_snapshot.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace_snapshot.c b/kernel/trace/trace_snapshot.c index 07b43c9863a2..22323c97289b 100644 --- a/kernel/trace/trace_snapshot.c +++ b/kernel/trace/trace_snapshot.c @@ -625,9 +625,12 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file) return ret; } -static void tracing_swap_cpu_buffer(void *tr) +static long tracing_swap_cpu_buffer(void *tr) { + local_irq_disable(); update_max_tr_single((struct trace_array *)tr, current, smp_processor_id()); + local_irq_enable(); + return 0; } static ssize_t @@ -689,8 +692,7 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt, update_max_tr(tr, current, smp_processor_id(), NULL); local_irq_enable(); } else { - smp_call_function_single(iter->cpu_file, tracing_swap_cpu_buffer, - (void *)tr, 1); + work_on_cpu(iter->cpu_file, tracing_swap_cpu_buffer, (void *)tr); } tracing_disarm_snapshot(tr); break; -- 2.34.1
