linux-stable/kernel/trace
Steven Rostedt (Google) 47ad5c133e ring-buffer: Fix full_waiters_pending in poll
[ Upstream commit 8145f1c35f ]

If a reader of the ring buffer is doing a poll, and waiting for the ring
buffer to hit a specific watermark, there could be a case where it gets
into an infinite ping-pong loop.

The poll code has:

  rbwork->full_waiters_pending = true;
  if (!cpu_buffer->shortest_full ||
      cpu_buffer->shortest_full > full)
         cpu_buffer->shortest_full = full;

The writer will see full_waiters_pending and check if the ring buffer is
filled over the percentage of the shortest_full value. If it is, it calls
an irq_work to wake up all the waiters.

But the code could get into a circular loop:

	CPU 0					CPU 1
	-----					-----
 [ Poll ]
   [ shortest_full = 0 ]
   rbwork->full_waiters_pending = true;
					  if (rbwork->full_waiters_pending &&
					      [ buffer percent ] > shortest_full) {
					         rbwork->wakeup_full = true;
					         [ queue_irqwork ]

   cpu_buffer->shortest_full = full;

					  [ IRQ work ]
					  if (rbwork->wakeup_full) {
					        cpu_buffer->shortest_full = 0;
					        wakeup poll waiters;
  [woken]
   if ([ buffer percent ] > full)
      break;
   rbwork->full_waiters_pending = true;
					  if (rbwork->full_waiters_pending &&
					      [ buffer percent ] > shortest_full) {
					         rbwork->wakeup_full = true;
					         [ queue_irqwork ]

   cpu_buffer->shortest_full = full;

					  [ IRQ work ]
					  if (rbwork->wakeup_full) {
					        cpu_buffer->shortest_full = 0;
					        wakeup poll waiters;
  [woken]

 [ Wash, rinse, repeat! ]

In the poll, the shortest_full needs to be set before the
full_pending_waiters, as once that is set, the writer will compare the
current shortest_full (which is incorrect) to decide to call the irq_work,
which will reset the shortest_full (expecting the readers to update it).

Also move the setting of full_waiters_pending after the check if the ring
buffer has the required percentage filled. There's no reason to tell the
writer to wake up waiters if there are no waiters.

Link: https://lore.kernel.org/linux-trace-kernel/20240312131952.630922155@goodmis.org

Cc: stable@vger.kernel.org
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Fixes: 42fb0a1e84 ("tracing/ring-buffer: Have polling block on watermark")
Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2024-04-13 12:58:34 +02:00
..
blktrace.c blktrace: Fix output non-blktrace event when blk_classic option enabled 2023-01-14 10:15:41 +01:00
bpf_trace.c bpf: Clear the probe_addr for uprobe 2023-09-19 12:20:07 +02:00
bpf_trace.h
fgraph.c
ftrace.c ftrace: Fix possible warning on checking all pages used in ftrace_process_locs() 2023-07-27 08:44:44 +02:00
ftrace_internal.h
Kconfig
kprobe_event_gen_test.c tracing: Fix wrong return in kprobe_event_gen_test.c 2023-04-05 11:23:46 +02:00
Makefile
power-traces.c
preemptirq_delay_test.c
ring_buffer.c ring-buffer: Fix full_waiters_pending in poll 2024-04-13 12:58:34 +02:00
ring_buffer_benchmark.c
rpm-traces.c
synth_event_gen_test.c tracing / synthetic: Disable events after testing in synth_event_gen_test_init() 2024-01-05 15:12:28 +01:00
trace.c tracing: Inform kmemleak of saved_cmdlines allocation 2024-02-23 08:42:30 +01:00
trace.h tracing: Have trace_event_file have ref counters 2023-11-28 16:55:02 +00:00
trace_benchmark.c
trace_benchmark.h
trace_boot.c tracing/boot: Fix a hist trigger dependency for boot time tracing 2021-09-22 12:28:03 +02:00
trace_branch.c
trace_clock.c
trace_dynevent.c tracing: Free buffers when a used dynamic event is removed 2022-12-08 11:23:58 +01:00
trace_dynevent.h
trace_entries.h
trace_event_perf.c
trace_events.c tracing: Have trace_event_file have ref counters 2023-11-28 16:55:02 +00:00
trace_events_filter.c tracing: Have trace_event_file have ref counters 2023-11-28 16:55:02 +00:00
trace_events_filter_test.h
trace_events_hist.c tracing/histograms: Return an error if we fail to add histogram to hist_vars list 2023-07-27 08:44:43 +02:00
trace_events_inject.c tracing: Have event inject files inc the trace array ref count 2023-10-10 21:53:25 +02:00
trace_events_synth.c tracing: Add tracing_reset_all_online_cpus_unlocked() function 2023-06-28 10:28:06 +02:00
trace_events_trigger.c tracing/trigger: Fix to return error if failed to alloc snapshot 2024-02-23 08:42:24 +01:00
trace_export.c
trace_functions.c tracing: Have all levels of checks prevent recursion 2021-10-27 09:56:56 +02:00
trace_functions_graph.c
trace_hwlat.c
trace_irqsoff.c tracing: Fix memleak due to race between current_tracer and trace 2023-08-30 16:23:12 +02:00
trace_kdb.c
trace_kprobe.c tracing/kprobes: Fix the order of argument descriptions 2023-11-20 11:06:57 +01:00
trace_kprobe_selftest.c
trace_kprobe_selftest.h
trace_mmiotrace.c
trace_nop.c
trace_output.c tracing: Add size check when printing trace_marker output 2024-01-25 14:37:37 -08:00
trace_output.h
trace_preemptirq.c tracing: hold caller_addr to hardirq_{enable,disable}_ip 2022-09-23 14:16:58 +02:00
trace_printk.c
trace_probe.c tracing/probes: Have kprobes and uprobes use $COMM too 2022-08-25 11:38:23 +02:00
trace_probe.h tracing/probe: trace_probe_primary_from_call(): checked list_first_entry 2023-06-09 10:30:16 +02:00
trace_probe_tmpl.h tracing/probes: Fix to update dynamic data counter if fetcharg uses it 2023-08-26 15:26:50 +02:00
trace_sched_switch.c
trace_sched_wakeup.c tracing: Fix memleak due to race between current_tracer and trace 2023-08-30 16:23:12 +02:00
trace_selftest.c
trace_selftest_dynamic.c
trace_seq.c
trace_stack.c
trace_stat.c
trace_stat.h
trace_synth.h tracing: Synthetic event field_pos is an index not a boolean 2021-07-28 14:35:45 +02:00
trace_syscalls.c
trace_uprobe.c bpf: Clear the probe_addr for uprobe 2023-09-19 12:20:07 +02:00
tracing_map.c tracing: Ensure visibility when inserting an element into tracing_map 2024-02-23 08:41:56 +01:00
tracing_map.h