Thread (6 messages) flat view 6 messages, 2 authors, 5d ago

Re: [PATCH v2 2/2] tracing/snapshot: Use work_on_cpu to avoid -EBUSY during snapshot swap

From: Tengda Wu <hidden>
Date: 2026-08-10 13:14:07
Also in: lkml


On 2026/8/8 22:58, Steven Rostedt wrote:
Sashiko brings up a good point. This will break the recording of what
task is being interrupted.

  https://sashiko.dev/#/patchset/20260803005640.2445666-2-wutengda%40huaweicloud.com

quoted
--- Patch [2]: [PATCH v2 2/2] tracing/snapshot: Use work_on_cpu to avoid -EBUSY during snapshot swap ---
commit b61ca8359fdea427c80a410f6d4052c68af5eae3
Author: Tengda Wu [off-list ref]

tracing/snapshot: Use work_on_cpu to avoid -EBUSY during snapshot swap

This commit replaces smp_call_function_single() with work_on_cpu() in
the snapshot write path to avoid -EBUSY errors when a target CPU is
actively writing to the ring buffer.
quoted
diff --git a/kernel/trace/trace_snapshot.c b/kernel/trace/trace_snapshot.c
--- a/kernel/trace/trace_snapshot.c
+++ b/kernel/trace/trace_snapshot.c
[ ... ]
quoted
-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());
When calling update_max_tr_single() from a workqueue thread, does passing
current result in the trace snapshot recording the kworker task instead of
the interrupted task?

In the previous smp_call_function_single() implementation, current would
represent the task executing on the target CPU, but now it will capture
the kworker thread.
And thinking of one usecase, what if you had a high priroity task you
wanted to snashot? This wouldn't work to do that.

Now we can still keep the ipi and send data that holds the tr and
state. It waits for the ipi to finish anyway. Then it can check if the
swap happened or not, and could report a fail, or it could try again?
Indeed, work_on_cpu() cannot handle these scenarios properly.

I just tried handling the return value and noticed that there is already
a log message inside update_max_tr_single() that reports the
ring_buffer_swap_cpu() error.
(I had previously overlooked this error handling and didn't notice it.)

So, it seems that no additional handling is necessary. I will keep the
current implementation unchanged.

Thank you for your accurate catch and thoughtful suggestions.

Best regards,
Tengda
quoted
quoted
+	local_irq_enable();
+	return 0;
 }
[ ... ]
quoted
@@ -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);
Can this result in swapping the wrong CPU's trace ring buffer if
iter->cpu_file is an offline CPU, or if the CPU goes offline concurrently?

Because cpus_read_lock() is not held, if the target CPU is offline, the
workqueue subsystem may execute the work on a fallback online CPU.

When tracing_swap_cpu_buffer() then calls smp_processor_id(), it will
evaluate to the fallback CPU's ID rather than the intended target CPU.

This could potentially modify an unrelated online CPU's trace buffer while
leaving the requested offline CPU's buffer unchanged.
This too looks to be a valid concern.
quoted
quoted
 		}
 		tracing_disarm_snapshot(tr);
 		break;
-- Steve
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help