aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorTom Zanussi <tom.zanussi@linux.intel.com>2013-10-24 09:59:24 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-12-20 18:40:22 -0500
commit85f2b08268c014e290b600ba49fa85530600eaa1 (patch)
tree911b2e24ac56434fc04e8ecafe6251536b6f06a0 /include
parent319e2e3f63c348a9b66db4667efa73178e18b17d (diff)
tracing: Add basic event trigger framework
Add a 'trigger' file for each trace event, enabling 'trace event triggers' to be set for trace events. 'trace event triggers' are patterned after the existing 'ftrace function triggers' implementation except that triggers are written to per-event 'trigger' files instead of to a single file such as the 'set_ftrace_filter' used for ftrace function triggers. The implementation is meant to be entirely separate from ftrace function triggers, in order to keep the respective implementations relatively simple and to allow them to diverge. The event trigger functionality is built on top of SOFT_DISABLE functionality. It adds a TRIGGER_MODE bit to the ftrace_event_file flags which is checked when any trace event fires. Triggers set for a particular event need to be checked regardless of whether that event is actually enabled or not - getting an event to fire even if it's not enabled is what's already implemented by SOFT_DISABLE mode, so trigger mode directly reuses that. Event trigger essentially inherit the soft disable logic in __ftrace_event_enable_disable() while adding a bit of logic and trigger reference counting via tm_ref on top of that in a new trace_event_trigger_enable_disable() function. Because the base __ftrace_event_enable_disable() code now needs to be invoked from outside trace_events.c, a wrapper is also added for those usages. The triggers for an event are actually invoked via a new function, event_triggers_call(), and code is also added to invoke them for ftrace_raw_event calls as well as syscall events. The main part of the patch creates a new trace_events_trigger.c file to contain the trace event triggers implementation. The standard open, read, and release file operations are implemented here. The open() implementation sets up for the various open modes of the 'trigger' file. It creates and attaches the trigger iterator and sets up the command parser. If opened for reading set up the trigger seq_ops. The read() implementation parses the event trigger written to the 'trigger' file, looks up the trigger command, and passes it along to that event_command's func() implementation for command-specific processing. The release() implementation does whatever cleanup is needed to release the 'trigger' file, like releasing the parser and trigger iterator, etc. A couple of functions for event command registration and unregistration are added, along with a list to add them to and a mutex to protect them, as well as an (initially empty) registration function to add the set of commands that will be added by future commits, and call to it from the trace event initialization code. also added are a couple trigger-specific data structures needed for these implementations such as a trigger iterator and a struct for trigger-specific data. A couple structs consisting mostly of function meant to be implemented in command-specific ways, event_command and event_trigger_ops, are used by the generic event trigger command implementations. They're being put into trace.h alongside the other trace_event data structures and functions, in the expectation that they'll be needed in several trace_event-related files such as trace_events_trigger.c and trace_events.c. The event_command.func() function is meant to be called by the trigger parsing code in order to add a trigger instance to the corresponding event. It essentially coordinates adding a live trigger instance to the event, and arming the triggering the event. Every event_command func() implementation essentially does the same thing for any command: - choose ops - use the value of param to choose either a number or count version of event_trigger_ops specific to the command - do the register or unregister of those ops - associate a filter, if specified, with the triggering event The reg() and unreg() ops allow command-specific implementations for event_trigger_op registration and unregistration, and the get_trigger_ops() op allows command-specific event_trigger_ops selection to be parameterized. When a trigger instance is added, the reg() op essentially adds that trigger to the triggering event and arms it, while unreg() does the opposite. The set_filter() function is used to associate a filter with the trigger - if the command doesn't specify a set_filter() implementation, the command will ignore filters. Each command has an associated trigger_type, which serves double duty, both as a unique identifier for the command as well as a value that can be used for setting a trigger mode bit during trigger invocation. The signature of func() adds a pointer to the event_command struct, used to invoke those functions, along with a command_data param that can be passed to the reg/unreg functions. This allows func() implementations to use command-specific blobs and supports code re-use. The event_trigger_ops.func() command corrsponds to the trigger 'probe' function that gets called when the triggering event is actually invoked. The other functions are used to list the trigger when needed, along with a couple mundane book-keeping functions. This also moves event_file_data() into trace.h so it can be used outside of trace_events.c. Link: http://lkml.kernel.org/r/316d95061accdee070aac8e5750afba0192fa5b9.1382622043.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com> Idea-by: Steve Rostedt <rostedt@goodmis.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/ftrace_event.h11
-rw-r--r--include/trace/ftrace.h4
2 files changed, 15 insertions, 0 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 8c9b7a1c4138..211e7ad2baf5 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -264,6 +264,7 @@ enum {
264 FTRACE_EVENT_FL_NO_SET_FILTER_BIT, 264 FTRACE_EVENT_FL_NO_SET_FILTER_BIT,
265 FTRACE_EVENT_FL_SOFT_MODE_BIT, 265 FTRACE_EVENT_FL_SOFT_MODE_BIT,
266 FTRACE_EVENT_FL_SOFT_DISABLED_BIT, 266 FTRACE_EVENT_FL_SOFT_DISABLED_BIT,
267 FTRACE_EVENT_FL_TRIGGER_MODE_BIT,
267}; 268};
268 269
269/* 270/*
@@ -275,6 +276,7 @@ enum {
275 * SOFT_MODE - The event is enabled/disabled by SOFT_DISABLED 276 * SOFT_MODE - The event is enabled/disabled by SOFT_DISABLED
276 * SOFT_DISABLED - When set, do not trace the event (even though its 277 * SOFT_DISABLED - When set, do not trace the event (even though its
277 * tracepoint may be enabled) 278 * tracepoint may be enabled)
279 * TRIGGER_MODE - When set, invoke the triggers associated with the event
278 */ 280 */
279enum { 281enum {
280 FTRACE_EVENT_FL_ENABLED = (1 << FTRACE_EVENT_FL_ENABLED_BIT), 282 FTRACE_EVENT_FL_ENABLED = (1 << FTRACE_EVENT_FL_ENABLED_BIT),
@@ -283,6 +285,7 @@ enum {
283 FTRACE_EVENT_FL_NO_SET_FILTER = (1 << FTRACE_EVENT_FL_NO_SET_FILTER_BIT), 285 FTRACE_EVENT_FL_NO_SET_FILTER = (1 << FTRACE_EVENT_FL_NO_SET_FILTER_BIT),
284 FTRACE_EVENT_FL_SOFT_MODE = (1 << FTRACE_EVENT_FL_SOFT_MODE_BIT), 286 FTRACE_EVENT_FL_SOFT_MODE = (1 << FTRACE_EVENT_FL_SOFT_MODE_BIT),
285 FTRACE_EVENT_FL_SOFT_DISABLED = (1 << FTRACE_EVENT_FL_SOFT_DISABLED_BIT), 287 FTRACE_EVENT_FL_SOFT_DISABLED = (1 << FTRACE_EVENT_FL_SOFT_DISABLED_BIT),
288 FTRACE_EVENT_FL_TRIGGER_MODE = (1 << FTRACE_EVENT_FL_TRIGGER_MODE_BIT),
286}; 289};
287 290
288struct ftrace_event_file { 291struct ftrace_event_file {
@@ -292,6 +295,7 @@ struct ftrace_event_file {
292 struct dentry *dir; 295 struct dentry *dir;
293 struct trace_array *tr; 296 struct trace_array *tr;
294 struct ftrace_subsystem_dir *system; 297 struct ftrace_subsystem_dir *system;
298 struct list_head triggers;
295 299
296 /* 300 /*
297 * 32 bit flags: 301 * 32 bit flags:
@@ -299,6 +303,7 @@ struct ftrace_event_file {
299 * bit 1: enabled cmd record 303 * bit 1: enabled cmd record
300 * bit 2: enable/disable with the soft disable bit 304 * bit 2: enable/disable with the soft disable bit
301 * bit 3: soft disabled 305 * bit 3: soft disabled
306 * bit 4: trigger enabled
302 * 307 *
303 * Note: The bits must be set atomically to prevent races 308 * Note: The bits must be set atomically to prevent races
304 * from other writers. Reads of flags do not need to be in 309 * from other writers. Reads of flags do not need to be in
@@ -310,6 +315,7 @@ struct ftrace_event_file {
310 */ 315 */
311 unsigned long flags; 316 unsigned long flags;
312 atomic_t sm_ref; /* soft-mode reference counter */ 317 atomic_t sm_ref; /* soft-mode reference counter */
318 atomic_t tm_ref; /* trigger-mode reference counter */
313}; 319};
314 320
315#define __TRACE_EVENT_FLAGS(name, value) \ 321#define __TRACE_EVENT_FLAGS(name, value) \
@@ -337,6 +343,10 @@ struct ftrace_event_file {
337 343
338#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ 344#define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */
339 345
346enum event_trigger_type {
347 ETT_NONE = (0),
348};
349
340extern void destroy_preds(struct ftrace_event_file *file); 350extern void destroy_preds(struct ftrace_event_file *file);
341extern void destroy_call_preds(struct ftrace_event_call *call); 351extern void destroy_call_preds(struct ftrace_event_call *call);
342extern int filter_match_preds(struct event_filter *filter, void *rec); 352extern int filter_match_preds(struct event_filter *filter, void *rec);
@@ -347,6 +357,7 @@ extern int filter_check_discard(struct ftrace_event_file *file, void *rec,
347extern int call_filter_check_discard(struct ftrace_event_call *call, void *rec, 357extern int call_filter_check_discard(struct ftrace_event_call *call, void *rec,
348 struct ring_buffer *buffer, 358 struct ring_buffer *buffer,
349 struct ring_buffer_event *event); 359 struct ring_buffer_event *event);
360extern void event_triggers_call(struct ftrace_event_file *file);
350 361
351enum { 362enum {
352 FILTER_OTHER = 0, 363 FILTER_OTHER = 0,
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 5c38606613d8..0a48bff964bd 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -539,6 +539,10 @@ ftrace_raw_event_##call(void *__data, proto) \
539 int __data_size; \ 539 int __data_size; \
540 int pc; \ 540 int pc; \
541 \ 541 \
542 if (test_bit(FTRACE_EVENT_FL_TRIGGER_MODE_BIT, \
543 &ftrace_file->flags)) \
544 event_triggers_call(ftrace_file); \
545 \
542 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, \ 546 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, \
543 &ftrace_file->flags)) \ 547 &ftrace_file->flags)) \
544 return; \ 548 return; \