Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

tracing: Use atomic_inc_return() for updating "disabled" counter in irqsoff tracer

The irqsoff tracer uses the per CPU "disabled" field to prevent corruption
of the accounting when it starts to trace interrupts disabled, but there's
a slight race that could happen if for some reason it was called twice.
Use atomic_inc_return() instead.

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>
Link: https://lore.kernel.org/20250505212236.567884756@goodmis.org
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

+18 -11
+18 -11
kernel/trace/trace_irqsoff.c
··· 397 397 int cpu; 398 398 struct trace_array *tr = irqsoff_trace; 399 399 struct trace_array_cpu *data; 400 + long disabled; 400 401 401 402 if (!tracer_enabled || !tracing_is_enabled()) 402 403 return; ··· 412 411 if (unlikely(!data) || local_read(&data->disabled)) 413 412 return; 414 413 415 - local_inc(&data->disabled); 414 + disabled = local_inc_return(&data->disabled); 416 415 417 - data->critical_sequence = max_sequence; 418 - data->preempt_timestamp = ftrace_now(cpu); 419 - data->critical_start = parent_ip ? : ip; 416 + if (disabled == 1) { 417 + data->critical_sequence = max_sequence; 418 + data->preempt_timestamp = ftrace_now(cpu); 419 + data->critical_start = parent_ip ? : ip; 420 420 421 - __trace_function(tr, ip, parent_ip, tracing_gen_ctx()); 421 + __trace_function(tr, ip, parent_ip, tracing_gen_ctx()); 422 422 423 - per_cpu(tracing_cpu, cpu) = 1; 423 + per_cpu(tracing_cpu, cpu) = 1; 424 + } 424 425 425 426 local_dec(&data->disabled); 426 427 } ··· 434 431 struct trace_array *tr = irqsoff_trace; 435 432 struct trace_array_cpu *data; 436 433 unsigned int trace_ctx; 434 + long disabled; 437 435 438 436 cpu = raw_smp_processor_id(); 439 437 /* Always clear the tracing cpu on stopping the trace */ ··· 452 448 !data->critical_start || local_read(&data->disabled)) 453 449 return; 454 450 455 - local_inc(&data->disabled); 451 + disabled = local_inc_return(&data->disabled); 456 452 457 - trace_ctx = tracing_gen_ctx(); 458 - __trace_function(tr, ip, parent_ip, trace_ctx); 459 - check_critical_timing(tr, data, parent_ip ? : ip, cpu); 460 - data->critical_start = 0; 453 + if (disabled == 1) { 454 + trace_ctx = tracing_gen_ctx(); 455 + __trace_function(tr, ip, parent_ip, trace_ctx); 456 + check_critical_timing(tr, data, parent_ip ? : ip, cpu); 457 + data->critical_start = 0; 458 + } 459 + 461 460 local_dec(&data->disabled); 462 461 } 463 462