Commit 788fa4b4 authored by Steven Rostedt's avatar Steven Rostedt Committed by Steven Rostedt (Google)
Browse files

tracing: Add guard(ring_buffer_nest)

Some calls to the tracing ring buffer can happen when the ring buffer is
already being written to by the same context (for example, a
trace_printk() in between a ring_buffer_lock_reserve() and a
ring_buffer_unlock_commit()).

In order to not trigger the recursion detection, these functions use
ring_buffer_nest_start() and ring_buffer_nest_end(). Create a guard() for
these functions so that their use cases can be simplified and not need to
use goto for the release.

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/20250801203857.710501021@kernel.org


Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
parent c89504a7
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -144,6 +144,9 @@ int ring_buffer_write(struct trace_buffer *buffer,
void ring_buffer_nest_start(struct trace_buffer *buffer);
void ring_buffer_nest_end(struct trace_buffer *buffer);

DEFINE_GUARD(ring_buffer_nest, struct trace_buffer *,
	     ring_buffer_nest_start(_T), ring_buffer_nest_end(_T))

struct ring_buffer_event *
ring_buffer_peek(struct trace_buffer *buffer, int cpu, u64 *ts,
		 unsigned long *lost_events);
+29 −40
Original line number Diff line number Diff line
@@ -1160,13 +1160,11 @@ int __trace_array_puts(struct trace_array *tr, unsigned long ip,

	trace_ctx = tracing_gen_ctx();
	buffer = tr->array_buffer.buffer;
	ring_buffer_nest_start(buffer);
	guard(ring_buffer_nest)(buffer);
	event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, alloc,
					    trace_ctx);
	if (!event) {
		size = 0;
		goto out;
	}
	if (!event)
		return 0;

	entry = ring_buffer_event_data(event);
	entry->ip = ip;
@@ -1182,8 +1180,6 @@ int __trace_array_puts(struct trace_array *tr, unsigned long ip,

	__buffer_unlock_commit(buffer, event);
	ftrace_trace_stack(tr, buffer, trace_ctx, 4, NULL);
 out:
	ring_buffer_nest_end(buffer);
	return size;
}
EXPORT_SYMBOL_GPL(__trace_array_puts);
@@ -1213,7 +1209,6 @@ int __trace_bputs(unsigned long ip, const char *str)
	struct bputs_entry *entry;
	unsigned int trace_ctx;
	int size = sizeof(struct bputs_entry);
	int ret = 0;

	if (!printk_binsafe(tr))
		return __trace_puts(ip, str, strlen(str));
@@ -1227,11 +1222,11 @@ int __trace_bputs(unsigned long ip, const char *str)
	trace_ctx = tracing_gen_ctx();
	buffer = tr->array_buffer.buffer;

	ring_buffer_nest_start(buffer);
	guard(ring_buffer_nest)(buffer);
	event = __trace_buffer_lock_reserve(buffer, TRACE_BPUTS, size,
					    trace_ctx);
	if (!event)
		goto out;
		return 0;

	entry = ring_buffer_event_data(event);
	entry->ip			= ip;
@@ -1240,10 +1235,7 @@ int __trace_bputs(unsigned long ip, const char *str)
	__buffer_unlock_commit(buffer, event);
	ftrace_trace_stack(tr, buffer, trace_ctx, 4, NULL);

	ret = 1;
 out:
	ring_buffer_nest_end(buffer);
	return ret;
	return 1;
}
EXPORT_SYMBOL_GPL(__trace_bputs);

@@ -3397,11 +3389,11 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)

	size = sizeof(*entry) + sizeof(u32) * len;
	buffer = tr->array_buffer.buffer;
	ring_buffer_nest_start(buffer);
	scoped_guard(ring_buffer_nest, buffer) {
		event = __trace_buffer_lock_reserve(buffer, TRACE_BPRINT, size,
						    trace_ctx);
		if (!event)
		goto out;
			goto out_put;
		entry = ring_buffer_event_data(event);
		entry->ip			= ip;
		entry->fmt			= fmt;
@@ -3409,9 +3401,7 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args)
		memcpy(entry->buf, tbuffer, sizeof(u32) * len);
		__buffer_unlock_commit(buffer, event);
		ftrace_trace_stack(tr, buffer, trace_ctx, 6, NULL);

out:
	ring_buffer_nest_end(buffer);
	}
out_put:
	put_trace_buf();

@@ -3452,7 +3442,7 @@ int __trace_array_vprintk(struct trace_buffer *buffer,
	len = vscnprintf(tbuffer, TRACE_BUF_SIZE, fmt, args);

	size = sizeof(*entry) + len + 1;
	ring_buffer_nest_start(buffer);
	scoped_guard(ring_buffer_nest, buffer) {
		event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, size,
						    trace_ctx);
		if (!event)
@@ -3463,9 +3453,8 @@ int __trace_array_vprintk(struct trace_buffer *buffer,
		memcpy(&entry->buf, tbuffer, len + 1);
		__buffer_unlock_commit(buffer, event);
		ftrace_trace_stack(printk_trace, buffer, trace_ctx, 6, NULL);

	}
out:
	ring_buffer_nest_end(buffer);
	put_trace_buf();

out_nobuffer:
+2 −4
Original line number Diff line number Diff line
@@ -536,12 +536,12 @@ static notrace void trace_event_raw_event_synth(void *__data,
	 * is being performed within another event.
	 */
	buffer = trace_file->tr->array_buffer.buffer;
	ring_buffer_nest_start(buffer);
	guard(ring_buffer_nest)(buffer);

	entry = trace_event_buffer_reserve(&fbuffer, trace_file,
					   sizeof(*entry) + fields_size);
	if (!entry)
		goto out;
		return;

	for (i = 0, n_u64 = 0; i < event->n_fields; i++) {
		val_idx = var_ref_idx[i];
@@ -584,8 +584,6 @@ static notrace void trace_event_raw_event_synth(void *__data,
	}

	trace_event_buffer_commit(&fbuffer);
out:
	ring_buffer_nest_end(buffer);
}

static void free_synth_event_print_fmt(struct trace_event_call *call)