diff options
-rw-r--r-- | include/linux/ftrace_event.h | 11 | ||||
-rw-r--r-- | include/trace/ftrace.h | 4 | ||||
-rw-r--r-- | kernel/trace/Makefile | 1 | ||||
-rw-r--r-- | kernel/trace/trace.h | 181 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 21 | ||||
-rw-r--r-- | kernel/trace/trace_events_trigger.c | 278 | ||||
-rw-r--r-- | kernel/trace/trace_syscalls.c | 4 |
7 files changed, 495 insertions, 5 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 | */ |
279 | enum { | 281 | enum { |
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 | ||
288 | struct ftrace_event_file { | 291 | struct 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 | ||
346 | enum event_trigger_type { | ||
347 | ETT_NONE = (0), | ||
348 | }; | ||
349 | |||
340 | extern void destroy_preds(struct ftrace_event_file *file); | 350 | extern void destroy_preds(struct ftrace_event_file *file); |
341 | extern void destroy_call_preds(struct ftrace_event_call *call); | 351 | extern void destroy_call_preds(struct ftrace_event_call *call); |
342 | extern int filter_match_preds(struct event_filter *filter, void *rec); | 352 | extern 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, | |||
347 | extern int call_filter_check_discard(struct ftrace_event_call *call, void *rec, | 357 | extern 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); |
360 | extern void event_triggers_call(struct ftrace_event_file *file); | ||
350 | 361 | ||
351 | enum { | 362 | enum { |
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; \ |
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index d7e2068e4b71..1378e84fbe39 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile | |||
@@ -50,6 +50,7 @@ ifeq ($(CONFIG_PERF_EVENTS),y) | |||
50 | obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o | 50 | obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o |
51 | endif | 51 | endif |
52 | obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o | 52 | obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o |
53 | obj-$(CONFIG_EVENT_TRACING) += trace_events_trigger.o | ||
53 | obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o | 54 | obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o |
54 | obj-$(CONFIG_TRACEPOINTS) += power-traces.o | 55 | obj-$(CONFIG_TRACEPOINTS) += power-traces.o |
55 | ifeq ($(CONFIG_PM_RUNTIME),y) | 56 | ifeq ($(CONFIG_PM_RUNTIME),y) |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index ea189e027b80..9775e518fe77 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -1028,9 +1028,190 @@ extern void trace_event_enable_cmd_record(bool enable); | |||
1028 | extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr); | 1028 | extern int event_trace_add_tracer(struct dentry *parent, struct trace_array *tr); |
1029 | extern int event_trace_del_tracer(struct trace_array *tr); | 1029 | extern int event_trace_del_tracer(struct trace_array *tr); |
1030 | 1030 | ||
1031 | static inline void *event_file_data(struct file *filp) | ||
1032 | { | ||
1033 | return ACCESS_ONCE(file_inode(filp)->i_private); | ||
1034 | } | ||
1035 | |||
1031 | extern struct mutex event_mutex; | 1036 | extern struct mutex event_mutex; |
1032 | extern struct list_head ftrace_events; | 1037 | extern struct list_head ftrace_events; |
1033 | 1038 | ||
1039 | extern const struct file_operations event_trigger_fops; | ||
1040 | |||
1041 | extern int register_trigger_cmds(void); | ||
1042 | extern void clear_event_triggers(struct trace_array *tr); | ||
1043 | |||
1044 | struct event_trigger_data { | ||
1045 | unsigned long count; | ||
1046 | int ref; | ||
1047 | struct event_trigger_ops *ops; | ||
1048 | struct event_command *cmd_ops; | ||
1049 | struct event_filter *filter; | ||
1050 | char *filter_str; | ||
1051 | void *private_data; | ||
1052 | struct list_head list; | ||
1053 | }; | ||
1054 | |||
1055 | /** | ||
1056 | * struct event_trigger_ops - callbacks for trace event triggers | ||
1057 | * | ||
1058 | * The methods in this structure provide per-event trigger hooks for | ||
1059 | * various trigger operations. | ||
1060 | * | ||
1061 | * All the methods below, except for @init() and @free(), must be | ||
1062 | * implemented. | ||
1063 | * | ||
1064 | * @func: The trigger 'probe' function called when the triggering | ||
1065 | * event occurs. The data passed into this callback is the data | ||
1066 | * that was supplied to the event_command @reg() function that | ||
1067 | * registered the trigger (see struct event_command). | ||
1068 | * | ||
1069 | * @init: An optional initialization function called for the trigger | ||
1070 | * when the trigger is registered (via the event_command reg() | ||
1071 | * function). This can be used to perform per-trigger | ||
1072 | * initialization such as incrementing a per-trigger reference | ||
1073 | * count, for instance. This is usually implemented by the | ||
1074 | * generic utility function @event_trigger_init() (see | ||
1075 | * trace_event_triggers.c). | ||
1076 | * | ||
1077 | * @free: An optional de-initialization function called for the | ||
1078 | * trigger when the trigger is unregistered (via the | ||
1079 | * event_command @reg() function). This can be used to perform | ||
1080 | * per-trigger de-initialization such as decrementing a | ||
1081 | * per-trigger reference count and freeing corresponding trigger | ||
1082 | * data, for instance. This is usually implemented by the | ||
1083 | * generic utility function @event_trigger_free() (see | ||
1084 | * trace_event_triggers.c). | ||
1085 | * | ||
1086 | * @print: The callback function invoked to have the trigger print | ||
1087 | * itself. This is usually implemented by a wrapper function | ||
1088 | * that calls the generic utility function @event_trigger_print() | ||
1089 | * (see trace_event_triggers.c). | ||
1090 | */ | ||
1091 | struct event_trigger_ops { | ||
1092 | void (*func)(struct event_trigger_data *data); | ||
1093 | int (*init)(struct event_trigger_ops *ops, | ||
1094 | struct event_trigger_data *data); | ||
1095 | void (*free)(struct event_trigger_ops *ops, | ||
1096 | struct event_trigger_data *data); | ||
1097 | int (*print)(struct seq_file *m, | ||
1098 | struct event_trigger_ops *ops, | ||
1099 | struct event_trigger_data *data); | ||
1100 | }; | ||
1101 | |||
1102 | /** | ||
1103 | * struct event_command - callbacks and data members for event commands | ||
1104 | * | ||
1105 | * Event commands are invoked by users by writing the command name | ||
1106 | * into the 'trigger' file associated with a trace event. The | ||
1107 | * parameters associated with a specific invocation of an event | ||
1108 | * command are used to create an event trigger instance, which is | ||
1109 | * added to the list of trigger instances associated with that trace | ||
1110 | * event. When the event is hit, the set of triggers associated with | ||
1111 | * that event is invoked. | ||
1112 | * | ||
1113 | * The data members in this structure provide per-event command data | ||
1114 | * for various event commands. | ||
1115 | * | ||
1116 | * All the data members below, except for @post_trigger, must be set | ||
1117 | * for each event command. | ||
1118 | * | ||
1119 | * @name: The unique name that identifies the event command. This is | ||
1120 | * the name used when setting triggers via trigger files. | ||
1121 | * | ||
1122 | * @trigger_type: A unique id that identifies the event command | ||
1123 | * 'type'. This value has two purposes, the first to ensure that | ||
1124 | * only one trigger of the same type can be set at a given time | ||
1125 | * for a particular event e.g. it doesn't make sense to have both | ||
1126 | * a traceon and traceoff trigger attached to a single event at | ||
1127 | * the same time, so traceon and traceoff have the same type | ||
1128 | * though they have different names. The @trigger_type value is | ||
1129 | * also used as a bit value for deferring the actual trigger | ||
1130 | * action until after the current event is finished. Some | ||
1131 | * commands need to do this if they themselves log to the trace | ||
1132 | * buffer (see the @post_trigger() member below). @trigger_type | ||
1133 | * values are defined by adding new values to the trigger_type | ||
1134 | * enum in include/linux/ftrace_event.h. | ||
1135 | * | ||
1136 | * @post_trigger: A flag that says whether or not this command needs | ||
1137 | * to have its action delayed until after the current event has | ||
1138 | * been closed. Some triggers need to avoid being invoked while | ||
1139 | * an event is currently in the process of being logged, since | ||
1140 | * the trigger may itself log data into the trace buffer. Thus | ||
1141 | * we make sure the current event is committed before invoking | ||
1142 | * those triggers. To do that, the trigger invocation is split | ||
1143 | * in two - the first part checks the filter using the current | ||
1144 | * trace record; if a command has the @post_trigger flag set, it | ||
1145 | * sets a bit for itself in the return value, otherwise it | ||
1146 | * directly invokes the trigger. Once all commands have been | ||
1147 | * either invoked or set their return flag, the current record is | ||
1148 | * either committed or discarded. At that point, if any commands | ||
1149 | * have deferred their triggers, those commands are finally | ||
1150 | * invoked following the close of the current event. In other | ||
1151 | * words, if the event_trigger_ops @func() probe implementation | ||
1152 | * itself logs to the trace buffer, this flag should be set, | ||
1153 | * otherwise it can be left unspecified. | ||
1154 | * | ||
1155 | * All the methods below, except for @set_filter(), must be | ||
1156 | * implemented. | ||
1157 | * | ||
1158 | * @func: The callback function responsible for parsing and | ||
1159 | * registering the trigger written to the 'trigger' file by the | ||
1160 | * user. It allocates the trigger instance and registers it with | ||
1161 | * the appropriate trace event. It makes use of the other | ||
1162 | * event_command callback functions to orchestrate this, and is | ||
1163 | * usually implemented by the generic utility function | ||
1164 | * @event_trigger_callback() (see trace_event_triggers.c). | ||
1165 | * | ||
1166 | * @reg: Adds the trigger to the list of triggers associated with the | ||
1167 | * event, and enables the event trigger itself, after | ||
1168 | * initializing it (via the event_trigger_ops @init() function). | ||
1169 | * This is also where commands can use the @trigger_type value to | ||
1170 | * make the decision as to whether or not multiple instances of | ||
1171 | * the trigger should be allowed. This is usually implemented by | ||
1172 | * the generic utility function @register_trigger() (see | ||
1173 | * trace_event_triggers.c). | ||
1174 | * | ||
1175 | * @unreg: Removes the trigger from the list of triggers associated | ||
1176 | * with the event, and disables the event trigger itself, after | ||
1177 | * initializing it (via the event_trigger_ops @free() function). | ||
1178 | * This is usually implemented by the generic utility function | ||
1179 | * @unregister_trigger() (see trace_event_triggers.c). | ||
1180 | * | ||
1181 | * @set_filter: An optional function called to parse and set a filter | ||
1182 | * for the trigger. If no @set_filter() method is set for the | ||
1183 | * event command, filters set by the user for the command will be | ||
1184 | * ignored. This is usually implemented by the generic utility | ||
1185 | * function @set_trigger_filter() (see trace_event_triggers.c). | ||
1186 | * | ||
1187 | * @get_trigger_ops: The callback function invoked to retrieve the | ||
1188 | * event_trigger_ops implementation associated with the command. | ||
1189 | */ | ||
1190 | struct event_command { | ||
1191 | struct list_head list; | ||
1192 | char *name; | ||
1193 | enum event_trigger_type trigger_type; | ||
1194 | bool post_trigger; | ||
1195 | int (*func)(struct event_command *cmd_ops, | ||
1196 | struct ftrace_event_file *file, | ||
1197 | char *glob, char *cmd, char *params); | ||
1198 | int (*reg)(char *glob, | ||
1199 | struct event_trigger_ops *ops, | ||
1200 | struct event_trigger_data *data, | ||
1201 | struct ftrace_event_file *file); | ||
1202 | void (*unreg)(char *glob, | ||
1203 | struct event_trigger_ops *ops, | ||
1204 | struct event_trigger_data *data, | ||
1205 | struct ftrace_event_file *file); | ||
1206 | int (*set_filter)(char *filter_str, | ||
1207 | struct event_trigger_data *data, | ||
1208 | struct ftrace_event_file *file); | ||
1209 | struct event_trigger_ops *(*get_trigger_ops)(char *cmd, char *param); | ||
1210 | }; | ||
1211 | |||
1212 | extern int trace_event_enable_disable(struct ftrace_event_file *file, | ||
1213 | int enable, int soft_disable); | ||
1214 | |||
1034 | extern const char *__start___trace_bprintk_fmt[]; | 1215 | extern const char *__start___trace_bprintk_fmt[]; |
1035 | extern const char *__stop___trace_bprintk_fmt[]; | 1216 | extern const char *__stop___trace_bprintk_fmt[]; |
1036 | 1217 | ||
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index a11800ae96de..442775c9dbf3 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -342,6 +342,12 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file, | |||
342 | return ret; | 342 | return ret; |
343 | } | 343 | } |
344 | 344 | ||
345 | int trace_event_enable_disable(struct ftrace_event_file *file, | ||
346 | int enable, int soft_disable) | ||
347 | { | ||
348 | return __ftrace_event_enable_disable(file, enable, soft_disable); | ||
349 | } | ||
350 | |||
345 | static int ftrace_event_enable_disable(struct ftrace_event_file *file, | 351 | static int ftrace_event_enable_disable(struct ftrace_event_file *file, |
346 | int enable) | 352 | int enable) |
347 | { | 353 | { |
@@ -421,11 +427,6 @@ static void remove_subsystem(struct ftrace_subsystem_dir *dir) | |||
421 | } | 427 | } |
422 | } | 428 | } |
423 | 429 | ||
424 | static void *event_file_data(struct file *filp) | ||
425 | { | ||
426 | return ACCESS_ONCE(file_inode(filp)->i_private); | ||
427 | } | ||
428 | |||
429 | static void remove_event_file_dir(struct ftrace_event_file *file) | 430 | static void remove_event_file_dir(struct ftrace_event_file *file) |
430 | { | 431 | { |
431 | struct dentry *dir = file->dir; | 432 | struct dentry *dir = file->dir; |
@@ -1549,6 +1550,9 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file) | |||
1549 | trace_create_file("filter", 0644, file->dir, file, | 1550 | trace_create_file("filter", 0644, file->dir, file, |
1550 | &ftrace_event_filter_fops); | 1551 | &ftrace_event_filter_fops); |
1551 | 1552 | ||
1553 | trace_create_file("trigger", 0644, file->dir, file, | ||
1554 | &event_trigger_fops); | ||
1555 | |||
1552 | trace_create_file("format", 0444, file->dir, call, | 1556 | trace_create_file("format", 0444, file->dir, call, |
1553 | &ftrace_event_format_fops); | 1557 | &ftrace_event_format_fops); |
1554 | 1558 | ||
@@ -1645,6 +1649,8 @@ trace_create_new_event(struct ftrace_event_call *call, | |||
1645 | file->event_call = call; | 1649 | file->event_call = call; |
1646 | file->tr = tr; | 1650 | file->tr = tr; |
1647 | atomic_set(&file->sm_ref, 0); | 1651 | atomic_set(&file->sm_ref, 0); |
1652 | atomic_set(&file->tm_ref, 0); | ||
1653 | INIT_LIST_HEAD(&file->triggers); | ||
1648 | list_add(&file->list, &tr->events); | 1654 | list_add(&file->list, &tr->events); |
1649 | 1655 | ||
1650 | return file; | 1656 | return file; |
@@ -2311,6 +2317,9 @@ int event_trace_del_tracer(struct trace_array *tr) | |||
2311 | { | 2317 | { |
2312 | mutex_lock(&event_mutex); | 2318 | mutex_lock(&event_mutex); |
2313 | 2319 | ||
2320 | /* Disable any event triggers and associated soft-disabled events */ | ||
2321 | clear_event_triggers(tr); | ||
2322 | |||
2314 | /* Disable any running events */ | 2323 | /* Disable any running events */ |
2315 | __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0); | 2324 | __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0); |
2316 | 2325 | ||
@@ -2377,6 +2386,8 @@ static __init int event_trace_enable(void) | |||
2377 | 2386 | ||
2378 | register_event_cmds(); | 2387 | register_event_cmds(); |
2379 | 2388 | ||
2389 | register_trigger_cmds(); | ||
2390 | |||
2380 | return 0; | 2391 | return 0; |
2381 | } | 2392 | } |
2382 | 2393 | ||
diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c new file mode 100644 index 000000000000..60a6a6d66dc0 --- /dev/null +++ b/kernel/trace/trace_events_trigger.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /* | ||
2 | * trace_events_trigger - trace event triggers | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | * | ||
18 | * Copyright (C) 2013 Tom Zanussi <tom.zanussi@linux.intel.com> | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/ctype.h> | ||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/slab.h> | ||
25 | |||
26 | #include "trace.h" | ||
27 | |||
28 | static LIST_HEAD(trigger_commands); | ||
29 | static DEFINE_MUTEX(trigger_cmd_mutex); | ||
30 | |||
31 | /** | ||
32 | * event_triggers_call - Call triggers associated with a trace event | ||
33 | * @file: The ftrace_event_file associated with the event | ||
34 | * | ||
35 | * For each trigger associated with an event, invoke the trigger | ||
36 | * function registered with the associated trigger command. | ||
37 | * | ||
38 | * Called from tracepoint handlers (with rcu_read_lock_sched() held). | ||
39 | * | ||
40 | * Return: an enum event_trigger_type value containing a set bit for | ||
41 | * any trigger that should be deferred, ETT_NONE if nothing to defer. | ||
42 | */ | ||
43 | void event_triggers_call(struct ftrace_event_file *file) | ||
44 | { | ||
45 | struct event_trigger_data *data; | ||
46 | |||
47 | if (list_empty(&file->triggers)) | ||
48 | return; | ||
49 | |||
50 | list_for_each_entry_rcu(data, &file->triggers, list) | ||
51 | data->ops->func(data); | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(event_triggers_call); | ||
54 | |||
55 | static void *trigger_next(struct seq_file *m, void *t, loff_t *pos) | ||
56 | { | ||
57 | struct ftrace_event_file *event_file = event_file_data(m->private); | ||
58 | |||
59 | return seq_list_next(t, &event_file->triggers, pos); | ||
60 | } | ||
61 | |||
62 | static void *trigger_start(struct seq_file *m, loff_t *pos) | ||
63 | { | ||
64 | struct ftrace_event_file *event_file; | ||
65 | |||
66 | /* ->stop() is called even if ->start() fails */ | ||
67 | mutex_lock(&event_mutex); | ||
68 | event_file = event_file_data(m->private); | ||
69 | if (unlikely(!event_file)) | ||
70 | return ERR_PTR(-ENODEV); | ||
71 | |||
72 | return seq_list_start(&event_file->triggers, *pos); | ||
73 | } | ||
74 | |||
75 | static void trigger_stop(struct seq_file *m, void *t) | ||
76 | { | ||
77 | mutex_unlock(&event_mutex); | ||
78 | } | ||
79 | |||
80 | static int trigger_show(struct seq_file *m, void *v) | ||
81 | { | ||
82 | struct event_trigger_data *data; | ||
83 | |||
84 | data = list_entry(v, struct event_trigger_data, list); | ||
85 | data->ops->print(m, data->ops, data); | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static const struct seq_operations event_triggers_seq_ops = { | ||
91 | .start = trigger_start, | ||
92 | .next = trigger_next, | ||
93 | .stop = trigger_stop, | ||
94 | .show = trigger_show, | ||
95 | }; | ||
96 | |||
97 | static int event_trigger_regex_open(struct inode *inode, struct file *file) | ||
98 | { | ||
99 | int ret = 0; | ||
100 | |||
101 | mutex_lock(&event_mutex); | ||
102 | |||
103 | if (unlikely(!event_file_data(file))) { | ||
104 | mutex_unlock(&event_mutex); | ||
105 | return -ENODEV; | ||
106 | } | ||
107 | |||
108 | if (file->f_mode & FMODE_READ) { | ||
109 | ret = seq_open(file, &event_triggers_seq_ops); | ||
110 | if (!ret) { | ||
111 | struct seq_file *m = file->private_data; | ||
112 | m->private = file; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | mutex_unlock(&event_mutex); | ||
117 | |||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int trigger_process_regex(struct ftrace_event_file *file, char *buff) | ||
122 | { | ||
123 | char *command, *next = buff; | ||
124 | struct event_command *p; | ||
125 | int ret = -EINVAL; | ||
126 | |||
127 | command = strsep(&next, ": \t"); | ||
128 | command = (command[0] != '!') ? command : command + 1; | ||
129 | |||
130 | mutex_lock(&trigger_cmd_mutex); | ||
131 | list_for_each_entry(p, &trigger_commands, list) { | ||
132 | if (strcmp(p->name, command) == 0) { | ||
133 | ret = p->func(p, file, buff, command, next); | ||
134 | goto out_unlock; | ||
135 | } | ||
136 | } | ||
137 | out_unlock: | ||
138 | mutex_unlock(&trigger_cmd_mutex); | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | static ssize_t event_trigger_regex_write(struct file *file, | ||
144 | const char __user *ubuf, | ||
145 | size_t cnt, loff_t *ppos) | ||
146 | { | ||
147 | struct ftrace_event_file *event_file; | ||
148 | ssize_t ret; | ||
149 | char *buf; | ||
150 | |||
151 | if (!cnt) | ||
152 | return 0; | ||
153 | |||
154 | if (cnt >= PAGE_SIZE) | ||
155 | return -EINVAL; | ||
156 | |||
157 | buf = (char *)__get_free_page(GFP_TEMPORARY); | ||
158 | if (!buf) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | if (copy_from_user(buf, ubuf, cnt)) { | ||
162 | free_page((unsigned long)buf); | ||
163 | return -EFAULT; | ||
164 | } | ||
165 | buf[cnt] = '\0'; | ||
166 | strim(buf); | ||
167 | |||
168 | mutex_lock(&event_mutex); | ||
169 | event_file = event_file_data(file); | ||
170 | if (unlikely(!event_file)) { | ||
171 | mutex_unlock(&event_mutex); | ||
172 | free_page((unsigned long)buf); | ||
173 | return -ENODEV; | ||
174 | } | ||
175 | ret = trigger_process_regex(event_file, buf); | ||
176 | mutex_unlock(&event_mutex); | ||
177 | |||
178 | free_page((unsigned long)buf); | ||
179 | if (ret < 0) | ||
180 | goto out; | ||
181 | |||
182 | *ppos += cnt; | ||
183 | ret = cnt; | ||
184 | out: | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | static int event_trigger_regex_release(struct inode *inode, struct file *file) | ||
189 | { | ||
190 | mutex_lock(&event_mutex); | ||
191 | |||
192 | if (file->f_mode & FMODE_READ) | ||
193 | seq_release(inode, file); | ||
194 | |||
195 | mutex_unlock(&event_mutex); | ||
196 | |||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static ssize_t | ||
201 | event_trigger_write(struct file *filp, const char __user *ubuf, | ||
202 | size_t cnt, loff_t *ppos) | ||
203 | { | ||
204 | return event_trigger_regex_write(filp, ubuf, cnt, ppos); | ||
205 | } | ||
206 | |||
207 | static int | ||
208 | event_trigger_open(struct inode *inode, struct file *filp) | ||
209 | { | ||
210 | return event_trigger_regex_open(inode, filp); | ||
211 | } | ||
212 | |||
213 | static int | ||
214 | event_trigger_release(struct inode *inode, struct file *file) | ||
215 | { | ||
216 | return event_trigger_regex_release(inode, file); | ||
217 | } | ||
218 | |||
219 | const struct file_operations event_trigger_fops = { | ||
220 | .open = event_trigger_open, | ||
221 | .read = seq_read, | ||
222 | .write = event_trigger_write, | ||
223 | .llseek = ftrace_filter_lseek, | ||
224 | .release = event_trigger_release, | ||
225 | }; | ||
226 | |||
227 | static int trace_event_trigger_enable_disable(struct ftrace_event_file *file, | ||
228 | int trigger_enable) | ||
229 | { | ||
230 | int ret = 0; | ||
231 | |||
232 | if (trigger_enable) { | ||
233 | if (atomic_inc_return(&file->tm_ref) > 1) | ||
234 | return ret; | ||
235 | set_bit(FTRACE_EVENT_FL_TRIGGER_MODE_BIT, &file->flags); | ||
236 | ret = trace_event_enable_disable(file, 1, 1); | ||
237 | } else { | ||
238 | if (atomic_dec_return(&file->tm_ref) > 0) | ||
239 | return ret; | ||
240 | clear_bit(FTRACE_EVENT_FL_TRIGGER_MODE_BIT, &file->flags); | ||
241 | ret = trace_event_enable_disable(file, 0, 1); | ||
242 | } | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * clear_event_triggers - Clear all triggers associated with a trace array | ||
249 | * @tr: The trace array to clear | ||
250 | * | ||
251 | * For each trigger, the triggering event has its tm_ref decremented | ||
252 | * via trace_event_trigger_enable_disable(), and any associated event | ||
253 | * (in the case of enable/disable_event triggers) will have its sm_ref | ||
254 | * decremented via free()->trace_event_enable_disable(). That | ||
255 | * combination effectively reverses the soft-mode/trigger state added | ||
256 | * by trigger registration. | ||
257 | * | ||
258 | * Must be called with event_mutex held. | ||
259 | */ | ||
260 | void | ||
261 | clear_event_triggers(struct trace_array *tr) | ||
262 | { | ||
263 | struct ftrace_event_file *file; | ||
264 | |||
265 | list_for_each_entry(file, &tr->events, list) { | ||
266 | struct event_trigger_data *data; | ||
267 | list_for_each_entry_rcu(data, &file->triggers, list) { | ||
268 | trace_event_trigger_enable_disable(file, 0); | ||
269 | if (data->ops->free) | ||
270 | data->ops->free(data->ops, data); | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | __init int register_trigger_cmds(void) | ||
276 | { | ||
277 | return 0; | ||
278 | } | ||
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index ea90eb5f6f17..936ec3960335 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
@@ -321,6 +321,8 @@ static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id) | |||
321 | if (!ftrace_file) | 321 | if (!ftrace_file) |
322 | return; | 322 | return; |
323 | 323 | ||
324 | if (test_bit(FTRACE_EVENT_FL_TRIGGER_MODE_BIT, &ftrace_file->flags)) | ||
325 | event_triggers_call(ftrace_file); | ||
324 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) | 326 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) |
325 | return; | 327 | return; |
326 | 328 | ||
@@ -369,6 +371,8 @@ static void ftrace_syscall_exit(void *data, struct pt_regs *regs, long ret) | |||
369 | if (!ftrace_file) | 371 | if (!ftrace_file) |
370 | return; | 372 | return; |
371 | 373 | ||
374 | if (test_bit(FTRACE_EVENT_FL_TRIGGER_MODE_BIT, &ftrace_file->flags)) | ||
375 | event_triggers_call(ftrace_file); | ||
372 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) | 376 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) |
373 | return; | 377 | return; |
374 | 378 | ||