Commit e8744fbc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tracing updates from Steven Rostedt:

 - Cleanup with guard() and free() helpers

   There were several places in the code that had a lot of "goto out" in
   the error paths to either unlock a lock or free some memory that was
   allocated. But this is error prone. Convert the code over to use the
   guard() and free() helpers that let the compiler unlock locks or free
   memory when the function exits.

 - Update the Rust tracepoint code to use the C code too

   There was some duplication of the tracepoint code for Rust that did
   the same logic as the C code. Add a helper that makes it possible for
   both algorithms to use the same logic in one place.

 - Add poll to trace event hist files

   It is useful to know when an event is triggered, or even with some
   filtering. Since hist files of events get updated when active and the
   event is triggered, allow applications to poll the hist file and wake
   up when an event is triggered. This will let the application know
   that the event it is waiting for happened.

 - Add :mod: command to enable events for current or future modules

   The function tracer already has a way to enable functions to be
   traced in modules by writing ":mod:<module>" into set_ftrace_filter.
   That will enable either all the functions for the module if it is
   loaded, or if it is not, it will cache that command, and when the
   module is loaded that matches <module>, its functions will be
   enabled. This also allows init functions to be traced. But currently
   events do not have that feature.

   Add the command where if ':mod:<module>' is written into set_event,
   then either all the modules events are enabled if it is loaded, or
   cache it so that the module's events are enabled when it is loaded.
   This also works from the kernel command line, where
   "trace_event=:mod:<module>", when the module is loaded at boot up,
   its events will be enabled then.

* tag 'trace-v6.14-3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: (26 commits)
  tracing: Fix output of set_event for some cached module events
  tracing: Fix allocation of printing set_event file content
  tracing: Rename update_cache() to update_mod_cache()
  tracing: Fix #if CONFIG_MODULES to #ifdef CONFIG_MODULES
  selftests/ftrace: Add test that tests event :mod: commands
  tracing: Cache ":mod:" events for modules not loaded yet
  tracing: Add :mod: command to enabled module events
  selftests/tracing: Add hist poll() support test
  tracing/hist: Support POLLPRI event for poll on histogram
  tracing/hist: Add poll(POLLIN) support on hist file
  tracing: Fix using ret variable in tracing_set_tracer()
  tracepoint: Reduce duplication of __DO_TRACE_CALL
  tracing/string: Create and use __free(argv_free) in trace_dynevent.c
  tracing: Switch trace_stat.c code over to use guard()
  tracing: Switch trace_stack.c code over to use guard()
  tracing: Switch trace_osnoise.c code over to use guard() and __free()
  tracing: Switch trace_events_synth.c code over to use guard()
  tracing: Switch trace_events_filter.c code over to use guard()
  tracing: Switch trace_events_trigger.c code over to use guard()
  tracing: Switch trace_events_hist.c code over to use guard()
  ...
parents 7f71554b 8f21943e
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -7161,6 +7161,14 @@
			comma-separated list of trace events to enable. See
			also Documentation/trace/events.rst

			To enable modules, use :mod: keyword:

			trace_event=:mod:<module>

			The value before :mod: will only enable specific events
			that are part of the module. See the above mentioned
			document for more information.

	trace_instance=[instance-info]
			[FTRACE] Create a ring buffer instance early in boot up.
			This will be listed in:
+24 −0
Original line number Diff line number Diff line
@@ -55,6 +55,30 @@ command::

	# echo 'irq:*' > /sys/kernel/tracing/set_event

The set_event file may also be used to enable events associated to only
a specific module::

	# echo ':mod:<module>' > /sys/kernel/tracing/set_event

Will enable all events in the module ``<module>``.  If the module is not yet
loaded, the string will be saved and when a module is that matches ``<module>``
is loaded, then it will apply the enabling of events then.

The text before ``:mod:`` will be parsed to specify specific events that the
module creates::

	# echo '<match>:mod:<module>' > /sys/kernel/tracing/set_event

The above will enable any system or event that ``<match>`` matches. If
``<match>`` is ``"*"`` then it will match all events.

To enable only a specific event within a system::

	# echo '<system>:<event>:mod:<module>' > /sys/kernel/tracing/set_event

If ``<event>`` is ``"*"`` then it will match all events within the system
for a given module.

2.2 Via the 'enable' toggle
---------------------------

+3 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@

#include <linux/args.h>
#include <linux/array_size.h>
#include <linux/cleanup.h>	/* for DEFINE_FREE() */
#include <linux/compiler.h>	/* for inline */
#include <linux/types.h>	/* for size_t */
#include <linux/stddef.h>	/* for NULL */
@@ -312,6 +313,8 @@ extern void *kmemdup_array(const void *src, size_t count, size_t element_size, g
extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
extern void argv_free(char **argv);

DEFINE_FREE(argv_free, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))

/* lib/cmdline.c */
extern int get_option(char **str, int *pint);
extern char *get_options(const char *str, int nints, int *ints);
+14 −0
Original line number Diff line number Diff line
@@ -673,6 +673,20 @@ struct trace_event_file {
	atomic_t		tm_ref;	/* trigger-mode reference counter */
};

#ifdef CONFIG_HIST_TRIGGERS
extern struct irq_work hist_poll_work;
extern wait_queue_head_t hist_poll_wq;

static inline void hist_poll_wakeup(void)
{
	if (wq_has_sleeper(&hist_poll_wq))
		irq_work_queue(&hist_poll_work);
}

#define hist_poll_wait(file, wait)	\
	poll_wait(file, &hist_poll_wq, wait)
#endif

#define __TRACE_EVENT_FLAGS(name, value)				\
	static int __init trace_init_flags_##name(void)			\
	{								\
+7 −13
Original line number Diff line number Diff line
@@ -218,7 +218,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
#define __DEFINE_RUST_DO_TRACE(name, proto, args)			\
	notrace void rust_do_trace_##name(proto)			\
	{								\
		__rust_do_trace_##name(args);				\
		__do_trace_##name(args);				\
	}

/*
@@ -268,7 +268,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)

#define __DECLARE_TRACE(name, proto, args, cond, data_proto)		\
	__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto)) \
	static inline void __rust_do_trace_##name(proto)		\
	static inline void __do_trace_##name(proto)			\
	{								\
		if (cond) {						\
			guard(preempt_notrace)();			\
@@ -277,12 +277,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
	}								\
	static inline void trace_##name(proto)				\
	{								\
		if (static_branch_unlikely(&__tracepoint_##name.key)) { \
			if (cond) {					\
				guard(preempt_notrace)();		\
				__DO_TRACE_CALL(name, TP_ARGS(args));	\
			}						\
		}							\
		if (static_branch_unlikely(&__tracepoint_##name.key))	\
			__do_trace_##name(args);			\
		if (IS_ENABLED(CONFIG_LOCKDEP) && (cond)) {		\
			WARN_ONCE(!rcu_is_watching(),			\
				  "RCU not watching for tracepoint");	\
@@ -291,7 +287,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)

#define __DECLARE_TRACE_SYSCALL(name, proto, args, data_proto)		\
	__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto)) \
	static inline void __rust_do_trace_##name(proto)		\
	static inline void __do_trace_##name(proto)			\
	{								\
		guard(rcu_tasks_trace)();				\
		__DO_TRACE_CALL(name, TP_ARGS(args));			\
@@ -299,10 +295,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
	static inline void trace_##name(proto)				\
	{								\
		might_fault();						\
		if (static_branch_unlikely(&__tracepoint_##name.key)) {	\
			guard(rcu_tasks_trace)();			\
			__DO_TRACE_CALL(name, TP_ARGS(args));		\
		}							\
		if (static_branch_unlikely(&__tracepoint_##name.key))	\
			__do_trace_##name(args);			\
		if (IS_ENABLED(CONFIG_LOCKDEP)) {			\
			WARN_ONCE(!rcu_is_watching(),			\
				  "RCU not watching for tracepoint");	\
Loading