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
> 
> 
>> --- Patch [2]: [PATCH v2 2/2] tracing/snapshot: Use work_on_cpu to avoid 
>> -EBUSY during snapshot swap ---
>> commit b61ca8359fdea427c80a410f6d4052c68af5eae3
>> Author: Tengda Wu <[email protected]>
>>
>> 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.
>>
>>> 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
>>
>> [ ... ]
>>
>>> -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

>>
>>> +   local_irq_enable();
>>> +   return 0;
>>>  }
>>
>> [ ... ]
>>
>>> @@ -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.
> 
>>
>>>             }
>>>             tracing_disarm_snapshot(tr);
>>>             break;
> 
> -- Steve


Reply via email to