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

tracing: Add option to set an instance to be the trace_printk destination

Add a option "trace_printk_dest" that will make the tracing instance the
location that trace_printk() will go to. This is useful if the
trace_printk or one of the top level tracers is too noisy and there's a
need to separate the two. Then an instance can be created, the
trace_printk can be set to go there instead, where it will not be lost in
the noise of the top level tracer.

Note, only one instance can be the destination of trace_printk at a time.
If an instance sets this flag, the instance that had it set will have it
cleared. There is always one instance that has this set. By default, that
is the top instance. This flag cannot be cleared from the top instance.
Doing so will result in an -EINVAL. The only way this flag can be cleared
from the top instance is by another instance setting it.

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>
Cc: Vincent Donnefort <vdonnefort@google.com>
Cc: Joel Fernandes <joel@joelfernandes.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vineeth Pillai <vineeth@bitbyteword.org>
Cc: Beau Belgrave <beaub@linux.microsoft.com>
Cc: Alexander Graf <graf@amazon.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: "Paul E. McKenney" <paulmck@kernel.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Ross Zwisler <zwisler@google.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Alexander Aring <aahringo@redhat.com>
Cc: "Luis Claudio R. Goncalves" <lgoncalv@redhat.com>
Cc: Tomas Glozar <tglozar@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: "Jonathan Corbet" <corbet@lwn.net>
Link: https://lore.kernel.org/20240823014019.545459018@goodmis.org


Signed-off-by: default avatarSteven Rostedt (Google) <rostedt@goodmis.org>
parent 9b7bdf6f
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1186,6 +1186,18 @@ Here are the available options:
  trace_printk
	Can disable trace_printk() from writing into the buffer.

  trace_printk_dest
	Set to have trace_printk() and similar internal tracing functions
	write into this instance. Note, only one trace instance can have
	this set. By setting this flag, it clears the trace_printk_dest flag
	of the instance that had it set previously. By default, the top
	level trace has this set, and will get it set again if another
	instance has it set then clears it.

	This flag cannot be cleared by the top level instance, as it is the
	default instance. The only way the top level instance has this flag
	cleared, is by it being set in another instance.

  annotate
	It is sometimes confusing when the CPU buffers are full
	and one CPU buffer had a lot of events recently, thus
+35 −5
Original line number Diff line number Diff line
@@ -482,7 +482,7 @@ EXPORT_SYMBOL_GPL(unregister_ftrace_export);
	 TRACE_ITER_ANNOTATE | TRACE_ITER_CONTEXT_INFO |		\
	 TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE |			\
	 TRACE_ITER_IRQ_INFO | TRACE_ITER_MARKERS |			\
	 TRACE_ITER_HASH_PTR)
	 TRACE_ITER_HASH_PTR | TRACE_ITER_TRACE_PRINTK)

/* trace_options that are only supported by global_trace */
#define TOP_LEVEL_TRACE_FLAGS (TRACE_ITER_PRINTK |			\
@@ -490,7 +490,7 @@ EXPORT_SYMBOL_GPL(unregister_ftrace_export);

/* trace_flags that are default zero for instances */
#define ZEROED_TRACE_FLAGS \
	(TRACE_ITER_EVENT_FORK | TRACE_ITER_FUNC_FORK)
	(TRACE_ITER_EVENT_FORK | TRACE_ITER_FUNC_FORK | TRACE_ITER_TRACE_PRINTK)

/*
 * The global_trace is the descriptor that holds the top-level tracing
@@ -513,6 +513,16 @@ static __always_inline bool printk_binsafe(struct trace_array *tr)
	return !(tr->flags & TRACE_ARRAY_FL_BOOT);
}

static void update_printk_trace(struct trace_array *tr)
{
	if (printk_trace == tr)
		return;

	printk_trace->trace_flags &= ~TRACE_ITER_TRACE_PRINTK;
	printk_trace = tr;
	tr->trace_flags |= TRACE_ITER_TRACE_PRINTK;
}

void trace_set_ring_buffer_expanded(struct trace_array *tr)
{
	if (!tr)
@@ -5300,7 +5310,8 @@ int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled)
{
	if ((mask == TRACE_ITER_RECORD_TGID) ||
	    (mask == TRACE_ITER_RECORD_CMD))
	    (mask == TRACE_ITER_RECORD_CMD) ||
	    (mask == TRACE_ITER_TRACE_PRINTK))
		lockdep_assert_held(&event_mutex);

	/* do nothing if flag is already set */
@@ -5312,6 +5323,25 @@ int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled)
		if (tr->current_trace->flag_changed(tr, mask, !!enabled))
			return -EINVAL;

	if (mask == TRACE_ITER_TRACE_PRINTK) {
		if (enabled) {
			update_printk_trace(tr);
		} else {
			/*
			 * The global_trace cannot clear this.
			 * It's flag only gets cleared if another instance sets it.
			 */
			if (printk_trace == &global_trace)
				return -EINVAL;
			/*
			 * An instance must always have it set.
			 * by default, that's the global_trace instane.
			 */
			if (printk_trace == tr)
				update_printk_trace(&global_trace);
		}
	}

	if (enabled)
		tr->trace_flags |= mask;
	else
@@ -9687,7 +9717,7 @@ static int __remove_instance(struct trace_array *tr)
	}

	if (printk_trace == tr)
		printk_trace = &global_trace;
		update_printk_trace(&global_trace);

	tracing_set_nop(tr);
	clear_ftrace_function_probes(tr);
@@ -10578,7 +10608,7 @@ __init static void enable_instances(void)
			tracer_tracing_off(tr);

		if (traceprintk)
			printk_trace = tr;
			update_printk_trace(tr);

		/*
		 * If start is set, then this is a mapped buffer, and
+1 −0
Original line number Diff line number Diff line
@@ -1321,6 +1321,7 @@ extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
		C(IRQ_INFO,		"irq-info"),		\
		C(MARKERS,		"markers"),		\
		C(EVENT_FORK,		"event-fork"),		\
		C(TRACE_PRINTK,		"trace_printk_dest"),	\
		C(PAUSE_ON_TRACE,	"pause-on-trace"),	\
		C(HASH_PTR,		"hash-ptr"),	/* Print hashed pointer */ \
		FUNCTION_FLAGS					\