Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 1 | ============= |
| 2 | Event Tracing |
| 3 | ============= |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 4 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 5 | :Author: Theodore Ts'o |
| 6 | :Updated: Li Zefan and Tom Zanussi |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 7 | |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 8 | 1. Introduction |
| 9 | =============== |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 10 | |
Mauro Carvalho Chehab | ec15872 | 2018-05-08 18:54:36 -0300 | [diff] [blame] | 11 | Tracepoints (see Documentation/trace/tracepoints.rst) can be used |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 12 | without creating custom kernel modules to register probe functions |
| 13 | using the event tracing infrastructure. |
| 14 | |
| 15 | Not all tracepoints can be traced using the event tracing system; |
| 16 | the kernel developer must provide code snippets which define how the |
| 17 | tracing information is saved into the tracing buffer, and how the |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 18 | tracing information should be printed. |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 19 | |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 20 | 2. Using Event Tracing |
| 21 | ====================== |
| 22 | |
| 23 | 2.1 Via the 'set_event' interface |
| 24 | --------------------------------- |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 25 | |
| 26 | The events which are available for tracing can be found in the file |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 27 | /sys/kernel/debug/tracing/available_events. |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 28 | |
| 29 | To enable a particular event, such as 'sched_wakeup', simply echo it |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 30 | to /sys/kernel/debug/tracing/set_event. For example:: |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 31 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 32 | # echo sched_wakeup >> /sys/kernel/debug/tracing/set_event |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 33 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 34 | .. Note:: '>>' is necessary, otherwise it will firstly disable all the events. |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 35 | |
| 36 | To disable an event, echo the event name to the set_event file prefixed |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 37 | with an exclamation point:: |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 38 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 39 | # echo '!sched_wakeup' >> /sys/kernel/debug/tracing/set_event |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 40 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 41 | To disable all events, echo an empty line to the set_event file:: |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 42 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 43 | # echo > /sys/kernel/debug/tracing/set_event |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 44 | |
Jonathan Corbet | 6234c7b | 2018-03-07 10:44:08 -0700 | [diff] [blame] | 45 | To enable all events, echo ``*:*`` or ``*:`` to the set_event file:: |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 46 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 47 | # echo *:* > /sys/kernel/debug/tracing/set_event |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 48 | |
| 49 | The events are organized into subsystems, such as ext4, irq, sched, |
| 50 | etc., and a full event name looks like this: <subsystem>:<event>. The |
| 51 | subsystem name is optional, but it is displayed in the available_events |
| 52 | file. All of the events in a subsystem can be specified via the syntax |
Jonathan Corbet | 6234c7b | 2018-03-07 10:44:08 -0700 | [diff] [blame] | 53 | ``<subsystem>:*``; for example, to enable all irq events, you can use the |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 54 | command:: |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 55 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 56 | # echo 'irq:*' > /sys/kernel/debug/tracing/set_event |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 57 | |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 58 | 2.2 Via the 'enable' toggle |
| 59 | --------------------------- |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 60 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 61 | The events available are also listed in /sys/kernel/debug/tracing/events/ hierarchy |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 62 | of directories. |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 63 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 64 | To enable event 'sched_wakeup':: |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 65 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 66 | # echo 1 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 67 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 68 | To disable it:: |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 69 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 70 | # echo 0 > /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 71 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 72 | To enable all events in sched subsystem:: |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 73 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 74 | # echo 1 > /sys/kernel/debug/tracing/events/sched/enable |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 75 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 76 | To enable all events:: |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 77 | |
GeunSik Lim | 52ad51e | 2009-09-07 21:37:17 +0900 | [diff] [blame] | 78 | # echo 1 > /sys/kernel/debug/tracing/events/enable |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 79 | |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 80 | When reading one of these enable files, there are four results: |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 81 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 82 | - 0 - all events this file affects are disabled |
| 83 | - 1 - all events this file affects are enabled |
| 84 | - X - there is a mixture of events enabled and disabled |
| 85 | - ? - this file does not affect any event |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 86 | |
Li Zefan | 020e5f8 | 2009-07-01 10:47:05 +0800 | [diff] [blame] | 87 | 2.3 Boot option |
| 88 | --------------- |
| 89 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 90 | In order to facilitate early boot debugging, use boot option:: |
Li Zefan | 020e5f8 | 2009-07-01 10:47:05 +0800 | [diff] [blame] | 91 | |
| 92 | trace_event=[event-list] |
| 93 | |
Li Zefan | 03d646e | 2009-12-21 14:27:24 +0800 | [diff] [blame] | 94 | event-list is a comma separated list of events. See section 2.1 for event |
| 95 | format. |
Li Zefan | 020e5f8 | 2009-07-01 10:47:05 +0800 | [diff] [blame] | 96 | |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 97 | 3. Defining an event-enabled tracepoint |
| 98 | ======================================= |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 99 | |
Li Zefan | 143c145 | 2009-05-19 14:43:15 +0800 | [diff] [blame] | 100 | See The example provided in samples/trace_events |
Theodore Ts'o | abd4144 | 2009-04-11 15:51:18 -0400 | [diff] [blame] | 101 | |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 102 | 4. Event formats |
| 103 | ================ |
| 104 | |
| 105 | Each trace event has a 'format' file associated with it that contains |
| 106 | a description of each field in a logged event. This information can |
| 107 | be used to parse the binary trace stream, and is also the place to |
| 108 | find the field names that can be used in event filters (see section 5). |
| 109 | |
| 110 | It also displays the format string that will be used to print the |
| 111 | event in text mode, along with the event name and ID used for |
| 112 | profiling. |
| 113 | |
Jonathan Corbet | 6234c7b | 2018-03-07 10:44:08 -0700 | [diff] [blame] | 114 | Every event has a set of ``common`` fields associated with it; these are |
| 115 | the fields prefixed with ``common_``. The other fields vary between |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 116 | events and correspond to the fields defined in the TRACE_EVENT |
| 117 | definition for that event. |
| 118 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 119 | Each field in the format has the form:: |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 120 | |
| 121 | field:field-type field-name; offset:N; size:N; |
| 122 | |
| 123 | where offset is the offset of the field in the trace record and size |
| 124 | is the size of the data item, in bytes. |
| 125 | |
| 126 | For example, here's the information displayed for the 'sched_wakeup' |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 127 | event:: |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 128 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 129 | # cat /sys/kernel/debug/tracing/events/sched/sched_wakeup/format |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 130 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 131 | name: sched_wakeup |
| 132 | ID: 60 |
| 133 | format: |
| 134 | field:unsigned short common_type; offset:0; size:2; |
| 135 | field:unsigned char common_flags; offset:2; size:1; |
| 136 | field:unsigned char common_preempt_count; offset:3; size:1; |
| 137 | field:int common_pid; offset:4; size:4; |
| 138 | field:int common_tgid; offset:8; size:4; |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 139 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 140 | field:char comm[TASK_COMM_LEN]; offset:12; size:16; |
| 141 | field:pid_t pid; offset:28; size:4; |
| 142 | field:int prio; offset:32; size:4; |
| 143 | field:int success; offset:36; size:4; |
| 144 | field:int cpu; offset:40; size:4; |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 145 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 146 | print fmt: "task %s:%d [%d] success=%d [%03d]", REC->comm, REC->pid, |
| 147 | REC->prio, REC->success, REC->cpu |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 148 | |
| 149 | This event contains 10 fields, the first 5 common and the remaining 5 |
| 150 | event-specific. All the fields for this event are numeric, except for |
| 151 | 'comm' which is a string, a distinction important for event filtering. |
| 152 | |
| 153 | 5. Event filtering |
| 154 | ================== |
| 155 | |
| 156 | Trace events can be filtered in the kernel by associating boolean |
| 157 | 'filter expressions' with them. As soon as an event is logged into |
| 158 | the trace buffer, its fields are checked against the filter expression |
| 159 | associated with that event type. An event with field values that |
| 160 | 'match' the filter will appear in the trace output, and an event whose |
| 161 | values don't match will be discarded. An event with no filter |
| 162 | associated with it matches everything, and is the default when no |
| 163 | filter has been set for an event. |
| 164 | |
| 165 | 5.1 Expression syntax |
| 166 | --------------------- |
| 167 | |
| 168 | A filter expression consists of one or more 'predicates' that can be |
| 169 | combined using the logical operators '&&' and '||'. A predicate is |
| 170 | simply a clause that compares the value of a field contained within a |
| 171 | logged event with a constant value and returns either 0 or 1 depending |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 172 | on whether the field value matched (1) or didn't match (0):: |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 173 | |
| 174 | field-name relational-operator value |
| 175 | |
| 176 | Parentheses can be used to provide arbitrary logical groupings and |
| 177 | double-quotes can be used to prevent the shell from interpreting |
| 178 | operators as shell metacharacters. |
| 179 | |
| 180 | The field-names available for use in filters can be found in the |
| 181 | 'format' files for trace events (see section 4). |
| 182 | |
| 183 | The relational-operators depend on the type of the field being tested: |
| 184 | |
| 185 | The operators available for numeric fields are: |
| 186 | |
Steven Rostedt | 1a891cf | 2013-06-12 13:16:25 -0400 | [diff] [blame] | 187 | ==, !=, <, <=, >, >=, & |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 188 | |
| 189 | And for string fields they are: |
| 190 | |
Steven Rostedt (Red Hat) | c3e13c7 | 2013-06-17 10:59:17 -0400 | [diff] [blame] | 191 | ==, !=, ~ |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 192 | |
Jonathan Corbet | 6234c7b | 2018-03-07 10:44:08 -0700 | [diff] [blame] | 193 | The glob (~) accepts a wild card character (\*,?) and character classes |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 194 | ([). For example:: |
Steven Rostedt (Red Hat) | c3e13c7 | 2013-06-17 10:59:17 -0400 | [diff] [blame] | 195 | |
| 196 | prev_comm ~ "*sh" |
| 197 | prev_comm ~ "sh*" |
| 198 | prev_comm ~ "*sh*" |
Masami Hiramatsu | 60f1d5e | 2016-10-05 20:58:15 +0900 | [diff] [blame] | 199 | prev_comm ~ "ba*sh" |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 200 | |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 201 | 5.2 Setting filters |
| 202 | ------------------- |
| 203 | |
| 204 | A filter for an individual event is set by writing a filter expression |
| 205 | to the 'filter' file for the given event. |
| 206 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 207 | For example:: |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 208 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 209 | # cd /sys/kernel/debug/tracing/events/sched/sched_wakeup |
| 210 | # echo "common_preempt_count > 4" > filter |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 211 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 212 | A slightly more involved example:: |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 213 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 214 | # cd /sys/kernel/debug/tracing/events/signal/signal_generate |
| 215 | # echo "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 216 | |
| 217 | If there is an error in the expression, you'll get an 'Invalid |
| 218 | argument' error when setting it, and the erroneous string along with |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 219 | an error message can be seen by looking at the filter e.g.:: |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 220 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 221 | # cd /sys/kernel/debug/tracing/events/signal/signal_generate |
| 222 | # echo "((sig >= 10 && sig < 15) || dsig == 17) && comm != bash" > filter |
| 223 | -bash: echo: write error: Invalid argument |
| 224 | # cat filter |
| 225 | ((sig >= 10 && sig < 15) || dsig == 17) && comm != bash |
| 226 | ^ |
| 227 | parse_error: Field not found |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 228 | |
| 229 | Currently the caret ('^') for an error always appears at the beginning of |
| 230 | the filter string; the error message should still be useful though |
| 231 | even without more accurate position info. |
| 232 | |
| 233 | 5.3 Clearing filters |
| 234 | -------------------- |
| 235 | |
| 236 | To clear the filter for an event, write a '0' to the event's filter |
| 237 | file. |
| 238 | |
| 239 | To clear the filters for all events in a subsystem, write a '0' to the |
| 240 | subsystem's filter file. |
| 241 | |
| 242 | 5.3 Subsystem filters |
| 243 | --------------------- |
| 244 | |
| 245 | For convenience, filters for every event in a subsystem can be set or |
| 246 | cleared as a group by writing a filter expression into the filter file |
Thomas Weber | 8839316 | 2010-03-16 11:47:56 +0100 | [diff] [blame] | 247 | at the root of the subsystem. Note however, that if a filter for any |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 248 | event within the subsystem lacks a field specified in the subsystem |
| 249 | filter, or if the filter can't be applied for any other reason, the |
| 250 | filter for that event will retain its previous setting. This can |
| 251 | result in an unintended mixture of filters which could lead to |
| 252 | confusing (to the user who might think different filters are in |
| 253 | effect) trace output. Only filters that reference just the common |
| 254 | fields can be guaranteed to propagate successfully to all events. |
| 255 | |
| 256 | Here are a few subsystem filter examples that also illustrate the |
| 257 | above points: |
| 258 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 259 | Clear the filters on all events in the sched subsystem:: |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 260 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 261 | # cd /sys/kernel/debug/tracing/events/sched |
| 262 | # echo 0 > filter |
| 263 | # cat sched_switch/filter |
| 264 | none |
| 265 | # cat sched_wakeup/filter |
| 266 | none |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 267 | |
| 268 | Set a filter using only common fields for all events in the sched |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 269 | subsystem (all events end up with the same filter):: |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 270 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 271 | # cd /sys/kernel/debug/tracing/events/sched |
| 272 | # echo common_pid == 0 > filter |
| 273 | # cat sched_switch/filter |
| 274 | common_pid == 0 |
| 275 | # cat sched_wakeup/filter |
| 276 | common_pid == 0 |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 277 | |
| 278 | Attempt to set a filter using a non-common field for all events in the |
Thomas Weber | 8839316 | 2010-03-16 11:47:56 +0100 | [diff] [blame] | 279 | sched subsystem (all events but those that have a prev_pid field retain |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 280 | their old filters):: |
Tom Zanussi | 95b6960 | 2009-09-10 23:13:51 -0500 | [diff] [blame] | 281 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 282 | # cd /sys/kernel/debug/tracing/events/sched |
| 283 | # echo prev_pid == 0 > filter |
| 284 | # cat sched_switch/filter |
| 285 | prev_pid == 0 |
| 286 | # cat sched_wakeup/filter |
| 287 | common_pid == 0 |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 288 | |
Steven Rostedt (Red Hat) | 627645f | 2015-11-03 16:37:15 -0500 | [diff] [blame] | 289 | 5.4 PID filtering |
| 290 | ----------------- |
| 291 | |
| 292 | The set_event_pid file in the same directory as the top events directory |
| 293 | exists, will filter all events from tracing any task that does not have the |
| 294 | PID listed in the set_event_pid file. |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 295 | :: |
Steven Rostedt (Red Hat) | 627645f | 2015-11-03 16:37:15 -0500 | [diff] [blame] | 296 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 297 | # cd /sys/kernel/debug/tracing |
| 298 | # echo $$ > set_event_pid |
| 299 | # echo 1 > events/enable |
Steven Rostedt (Red Hat) | 627645f | 2015-11-03 16:37:15 -0500 | [diff] [blame] | 300 | |
| 301 | Will only trace events for the current task. |
| 302 | |
| 303 | To add more PIDs without losing the PIDs already included, use '>>'. |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 304 | :: |
Steven Rostedt (Red Hat) | 627645f | 2015-11-03 16:37:15 -0500 | [diff] [blame] | 305 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 306 | # echo 123 244 1 >> set_event_pid |
Steven Rostedt (Red Hat) | 627645f | 2015-11-03 16:37:15 -0500 | [diff] [blame] | 307 | |
| 308 | |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 309 | 6. Event triggers |
| 310 | ================= |
| 311 | |
| 312 | Trace events can be made to conditionally invoke trigger 'commands' |
| 313 | which can take various forms and are described in detail below; |
| 314 | examples would be enabling or disabling other trace events or invoking |
| 315 | a stack trace whenever the trace event is hit. Whenever a trace event |
| 316 | with attached triggers is invoked, the set of trigger commands |
| 317 | associated with that event is invoked. Any given trigger can |
| 318 | additionally have an event filter of the same form as described in |
| 319 | section 5 (Event filtering) associated with it - the command will only |
| 320 | be invoked if the event being invoked passes the associated filter. |
| 321 | If no filter is associated with the trigger, it always passes. |
| 322 | |
| 323 | Triggers are added to and removed from a particular event by writing |
| 324 | trigger expressions to the 'trigger' file for the given event. |
| 325 | |
| 326 | A given event can have any number of triggers associated with it, |
| 327 | subject to any restrictions that individual commands may have in that |
| 328 | regard. |
| 329 | |
| 330 | Event triggers are implemented on top of "soft" mode, which means that |
| 331 | whenever a trace event has one or more triggers associated with it, |
| 332 | the event is activated even if it isn't actually enabled, but is |
| 333 | disabled in a "soft" mode. That is, the tracepoint will be called, |
| 334 | but just will not be traced, unless of course it's actually enabled. |
| 335 | This scheme allows triggers to be invoked even for events that aren't |
| 336 | enabled, and also allows the current event filter implementation to be |
| 337 | used for conditionally invoking triggers. |
| 338 | |
| 339 | The syntax for event triggers is roughly based on the syntax for |
| 340 | set_ftrace_filter 'ftrace filter commands' (see the 'Filter commands' |
Steven Rostedt (VMware) | d3439f9 | 2018-05-11 15:41:24 -0400 | [diff] [blame] | 341 | section of Documentation/trace/ftrace.rst), but there are major |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 342 | differences and the implementation isn't currently tied to it in any |
| 343 | way, so beware about making generalizations between the two. |
| 344 | |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 345 | .. Note:: |
| 346 | Writing into trace_marker (See Documentation/trace/ftrace.rst) |
Steven Rostedt (VMware) | d3439f9 | 2018-05-11 15:41:24 -0400 | [diff] [blame] | 347 | can also enable triggers that are written into |
| 348 | /sys/kernel/tracing/events/ftrace/print/trigger |
| 349 | |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 350 | 6.1 Expression syntax |
| 351 | --------------------- |
| 352 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 353 | Triggers are added by echoing the command to the 'trigger' file:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 354 | |
| 355 | # echo 'command[:count] [if filter]' > trigger |
| 356 | |
| 357 | Triggers are removed by echoing the same command but starting with '!' |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 358 | to the 'trigger' file:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 359 | |
| 360 | # echo '!command[:count] [if filter]' > trigger |
| 361 | |
| 362 | The [if filter] part isn't used in matching commands when removing, so |
| 363 | leaving that off in a '!' command will accomplish the same thing as |
| 364 | having it in. |
| 365 | |
| 366 | The filter syntax is the same as that described in the 'Event |
| 367 | filtering' section above. |
| 368 | |
| 369 | For ease of use, writing to the trigger file using '>' currently just |
| 370 | adds or removes a single trigger and there's no explicit '>>' support |
| 371 | ('>' actually behaves like '>>') or truncation support to remove all |
| 372 | triggers (you have to use '!' for each one added.) |
| 373 | |
| 374 | 6.2 Supported trigger commands |
| 375 | ------------------------------ |
| 376 | |
| 377 | The following commands are supported: |
| 378 | |
| 379 | - enable_event/disable_event |
| 380 | |
| 381 | These commands can enable or disable another trace event whenever |
| 382 | the triggering event is hit. When these commands are registered, |
| 383 | the other trace event is activated, but disabled in a "soft" mode. |
| 384 | That is, the tracepoint will be called, but just will not be traced. |
| 385 | The event tracepoint stays in this mode as long as there's a trigger |
| 386 | in effect that can trigger it. |
| 387 | |
| 388 | For example, the following trigger causes kmalloc events to be |
| 389 | traced when a read system call is entered, and the :1 at the end |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 390 | specifies that this enablement happens only once:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 391 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 392 | # echo 'enable_event:kmem:kmalloc:1' > \ |
| 393 | /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 394 | |
| 395 | The following trigger causes kmalloc events to stop being traced |
| 396 | when a read system call exits. This disablement happens on every |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 397 | read system call exit:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 398 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 399 | # echo 'disable_event:kmem:kmalloc' > \ |
| 400 | /sys/kernel/debug/tracing/events/syscalls/sys_exit_read/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 401 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 402 | The format is:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 403 | |
| 404 | enable_event:<system>:<event>[:count] |
| 405 | disable_event:<system>:<event>[:count] |
| 406 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 407 | To remove the above commands:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 408 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 409 | # echo '!enable_event:kmem:kmalloc:1' > \ |
| 410 | /sys/kernel/debug/tracing/events/syscalls/sys_enter_read/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 411 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 412 | # echo '!disable_event:kmem:kmalloc' > \ |
| 413 | /sys/kernel/debug/tracing/events/syscalls/sys_exit_read/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 414 | |
| 415 | Note that there can be any number of enable/disable_event triggers |
| 416 | per triggering event, but there can only be one trigger per |
| 417 | triggered event. e.g. sys_enter_read can have triggers enabling both |
| 418 | kmem:kmalloc and sched:sched_switch, but can't have two kmem:kmalloc |
| 419 | versions such as kmem:kmalloc and kmem:kmalloc:1 or 'kmem:kmalloc if |
| 420 | bytes_req == 256' and 'kmem:kmalloc if bytes_alloc == 256' (they |
| 421 | could be combined into a single filter on kmem:kmalloc though). |
| 422 | |
| 423 | - stacktrace |
| 424 | |
| 425 | This command dumps a stacktrace in the trace buffer whenever the |
| 426 | triggering event occurs. |
| 427 | |
| 428 | For example, the following trigger dumps a stacktrace every time the |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 429 | kmalloc tracepoint is hit:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 430 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 431 | # echo 'stacktrace' > \ |
| 432 | /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 433 | |
| 434 | The following trigger dumps a stacktrace the first 5 times a kmalloc |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 435 | request happens with a size >= 64K:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 436 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 437 | # echo 'stacktrace:5 if bytes_req >= 65536' > \ |
| 438 | /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 439 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 440 | The format is:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 441 | |
| 442 | stacktrace[:count] |
| 443 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 444 | To remove the above commands:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 445 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 446 | # echo '!stacktrace' > \ |
| 447 | /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 448 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 449 | # echo '!stacktrace:5 if bytes_req >= 65536' > \ |
| 450 | /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 451 | |
| 452 | The latter can also be removed more simply by the following (without |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 453 | the filter):: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 454 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 455 | # echo '!stacktrace:5' > \ |
| 456 | /sys/kernel/debug/tracing/events/kmem/kmalloc/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 457 | |
| 458 | Note that there can be only one stacktrace trigger per triggering |
| 459 | event. |
| 460 | |
| 461 | - snapshot |
| 462 | |
| 463 | This command causes a snapshot to be triggered whenever the |
| 464 | triggering event occurs. |
| 465 | |
| 466 | The following command creates a snapshot every time a block request |
| 467 | queue is unplugged with a depth > 1. If you were tracing a set of |
| 468 | events or functions at the time, the snapshot trace buffer would |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 469 | capture those events when the trigger event occurred:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 470 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 471 | # echo 'snapshot if nr_rq > 1' > \ |
| 472 | /sys/kernel/debug/tracing/events/block/block_unplug/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 473 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 474 | To only snapshot once:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 475 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 476 | # echo 'snapshot:1 if nr_rq > 1' > \ |
| 477 | /sys/kernel/debug/tracing/events/block/block_unplug/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 478 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 479 | To remove the above commands:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 480 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 481 | # echo '!snapshot if nr_rq > 1' > \ |
| 482 | /sys/kernel/debug/tracing/events/block/block_unplug/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 483 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 484 | # echo '!snapshot:1 if nr_rq > 1' > \ |
| 485 | /sys/kernel/debug/tracing/events/block/block_unplug/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 486 | |
| 487 | Note that there can be only one snapshot trigger per triggering |
| 488 | event. |
| 489 | |
| 490 | - traceon/traceoff |
| 491 | |
| 492 | These commands turn tracing on and off when the specified events are |
| 493 | hit. The parameter determines how many times the tracing system is |
| 494 | turned on and off. If unspecified, there is no limit. |
| 495 | |
| 496 | The following command turns tracing off the first time a block |
| 497 | request queue is unplugged with a depth > 1. If you were tracing a |
| 498 | set of events or functions at the time, you could then examine the |
| 499 | trace buffer to see the sequence of events that led up to the |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 500 | trigger event:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 501 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 502 | # echo 'traceoff:1 if nr_rq > 1' > \ |
| 503 | /sys/kernel/debug/tracing/events/block/block_unplug/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 504 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 505 | To always disable tracing when nr_rq > 1:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 506 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 507 | # echo 'traceoff if nr_rq > 1' > \ |
| 508 | /sys/kernel/debug/tracing/events/block/block_unplug/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 509 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 510 | To remove the above commands:: |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 511 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 512 | # echo '!traceoff:1 if nr_rq > 1' > \ |
| 513 | /sys/kernel/debug/tracing/events/block/block_unplug/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 514 | |
Changbin Du | 73d9812 | 2018-02-17 13:39:42 +0800 | [diff] [blame] | 515 | # echo '!traceoff if nr_rq > 1' > \ |
| 516 | /sys/kernel/debug/tracing/events/block/block_unplug/trigger |
Tom Zanussi | ac38fb8 | 2013-10-24 08:59:30 -0500 | [diff] [blame] | 517 | |
| 518 | Note that there can be only one traceon or traceoff trigger per |
| 519 | triggering event. |
Tom Zanussi | 0fc3813 | 2016-03-03 12:54:56 -0600 | [diff] [blame] | 520 | |
| 521 | - hist |
| 522 | |
| 523 | This command aggregates event hits into a hash table keyed on one or |
| 524 | more trace event format fields (or stacktrace) and a set of running |
| 525 | totals derived from one or more trace event format fields and/or |
| 526 | event counts (hitcount). |
| 527 | |
Mauro Carvalho Chehab | ea27225 | 2018-06-26 06:49:11 -0300 | [diff] [blame] | 528 | See Documentation/trace/histogram.rst for details and examples. |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 529 | |
Tom Zanussi | b8170fa | 2020-05-18 13:29:24 -0500 | [diff] [blame] | 530 | 7. In-kernel trace event API |
| 531 | ============================ |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 532 | |
| 533 | In most cases, the command-line interface to trace events is more than |
| 534 | sufficient. Sometimes, however, applications might find the need for |
| 535 | more complex relationships than can be expressed through a simple |
| 536 | series of linked command-line expressions, or putting together sets of |
| 537 | commands may be simply too cumbersome. An example might be an |
| 538 | application that needs to 'listen' to the trace stream in order to |
| 539 | maintain an in-kernel state machine detecting, for instance, when an |
| 540 | illegal kernel state occurs in the scheduler. |
| 541 | |
| 542 | The trace event subsystem provides an in-kernel API allowing modules |
| 543 | or other kernel code to generate user-defined 'synthetic' events at |
| 544 | will, which can be used to either augment the existing trace stream |
| 545 | and/or signal that a particular important state has occurred. |
| 546 | |
| 547 | A similar in-kernel API is also available for creating kprobe and |
| 548 | kretprobe events. |
| 549 | |
| 550 | Both the synthetic event and k/ret/probe event APIs are built on top |
| 551 | of a lower-level "dynevent_cmd" event command API, which is also |
| 552 | available for more specialized applications, or as the basis of other |
| 553 | higher-level trace event APIs. |
| 554 | |
| 555 | The API provided for these purposes is describe below and allows the |
| 556 | following: |
| 557 | |
| 558 | - dynamically creating synthetic event definitions |
| 559 | - dynamically creating kprobe and kretprobe event definitions |
| 560 | - tracing synthetic events from in-kernel code |
| 561 | - the low-level "dynevent_cmd" API |
| 562 | |
Tom Zanussi | b8170fa | 2020-05-18 13:29:24 -0500 | [diff] [blame] | 563 | 7.1 Dyamically creating synthetic event definitions |
| 564 | --------------------------------------------------- |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 565 | |
| 566 | There are a couple ways to create a new synthetic event from a kernel |
| 567 | module or other kernel code. |
| 568 | |
| 569 | The first creates the event in one step, using synth_event_create(). |
| 570 | In this method, the name of the event to create and an array defining |
| 571 | the fields is supplied to synth_event_create(). If successful, a |
| 572 | synthetic event with that name and fields will exist following that |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 573 | call. For example, to create a new "schedtest" synthetic event:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 574 | |
| 575 | ret = synth_event_create("schedtest", sched_fields, |
| 576 | ARRAY_SIZE(sched_fields), THIS_MODULE); |
| 577 | |
| 578 | The sched_fields param in this example points to an array of struct |
| 579 | synth_field_desc, each of which describes an event field by type and |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 580 | name:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 581 | |
| 582 | static struct synth_field_desc sched_fields[] = { |
| 583 | { .type = "pid_t", .name = "next_pid_field" }, |
| 584 | { .type = "char[16]", .name = "next_comm_field" }, |
| 585 | { .type = "u64", .name = "ts_ns" }, |
| 586 | { .type = "u64", .name = "ts_ms" }, |
| 587 | { .type = "unsigned int", .name = "cpu" }, |
| 588 | { .type = "char[64]", .name = "my_string_field" }, |
| 589 | { .type = "int", .name = "my_int_field" }, |
| 590 | }; |
| 591 | |
Tom Zanussi | bd82631 | 2020-10-04 17:14:06 -0500 | [diff] [blame] | 592 | See synth_field_size() for available types. |
| 593 | |
| 594 | If field_name contains [n], the field is considered to be a static array. |
| 595 | |
| 596 | If field_names contains[] (no subscript), the field is considered to |
| 597 | be a dynamic array, which will only take as much space in the event as |
| 598 | is required to hold the array. |
| 599 | |
| 600 | Because space for an event is reserved before assigning field values |
| 601 | to the event, using dynamic arrays implies that the piecewise |
| 602 | in-kernel API described below can't be used with dynamic arrays. The |
| 603 | other non-piecewise in-kernel APIs can, however, be used with dynamic |
| 604 | arrays. |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 605 | |
| 606 | If the event is created from within a module, a pointer to the module |
| 607 | must be passed to synth_event_create(). This will ensure that the |
| 608 | trace buffer won't contain unreadable events when the module is |
| 609 | removed. |
| 610 | |
| 611 | At this point, the event object is ready to be used for generating new |
| 612 | events. |
| 613 | |
| 614 | In the second method, the event is created in several steps. This |
| 615 | allows events to be created dynamically and without the need to create |
| 616 | and populate an array of fields beforehand. |
| 617 | |
| 618 | To use this method, an empty or partially empty synthetic event should |
| 619 | first be created using synth_event_gen_cmd_start() or |
| 620 | synth_event_gen_cmd_array_start(). For synth_event_gen_cmd_start(), |
| 621 | the name of the event along with one or more pairs of args each pair |
| 622 | representing a 'type field_name;' field specification should be |
| 623 | supplied. For synth_event_gen_cmd_array_start(), the name of the |
| 624 | event along with an array of struct synth_field_desc should be |
| 625 | supplied. Before calling synth_event_gen_cmd_start() or |
| 626 | synth_event_gen_cmd_array_start(), the user should create and |
| 627 | initialize a dynevent_cmd object using synth_event_cmd_init(). |
| 628 | |
| 629 | For example, to create a new "schedtest" synthetic event with two |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 630 | fields:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 631 | |
| 632 | struct dynevent_cmd cmd; |
| 633 | char *buf; |
| 634 | |
| 635 | /* Create a buffer to hold the generated command */ |
| 636 | buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL); |
| 637 | |
| 638 | /* Before generating the command, initialize the cmd object */ |
| 639 | synth_event_cmd_init(&cmd, buf, MAX_DYNEVENT_CMD_LEN); |
| 640 | |
| 641 | ret = synth_event_gen_cmd_start(&cmd, "schedtest", THIS_MODULE, |
| 642 | "pid_t", "next_pid_field", |
| 643 | "u64", "ts_ns"); |
| 644 | |
| 645 | Alternatively, using an array of struct synth_field_desc fields |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 646 | containing the same information:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 647 | |
| 648 | ret = synth_event_gen_cmd_array_start(&cmd, "schedtest", THIS_MODULE, |
| 649 | fields, n_fields); |
| 650 | |
| 651 | Once the synthetic event object has been created, it can then be |
| 652 | populated with more fields. Fields are added one by one using |
| 653 | synth_event_add_field(), supplying the dynevent_cmd object, a field |
| 654 | type, and a field name. For example, to add a new int field named |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 655 | "intfield", the following call should be made:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 656 | |
| 657 | ret = synth_event_add_field(&cmd, "int", "intfield"); |
| 658 | |
| 659 | See synth_field_size() for available types. If field_name contains [n] |
| 660 | the field is considered to be an array. |
| 661 | |
| 662 | A group of fields can also be added all at once using an array of |
| 663 | synth_field_desc with add_synth_fields(). For example, this would add |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 664 | just the first four sched_fields:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 665 | |
| 666 | ret = synth_event_add_fields(&cmd, sched_fields, 4); |
| 667 | |
| 668 | If you already have a string of the form 'type field_name', |
| 669 | synth_event_add_field_str() can be used to add it as-is; it will |
| 670 | also automatically append a ';' to the string. |
| 671 | |
| 672 | Once all the fields have been added, the event should be finalized and |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 673 | registered by calling the synth_event_gen_cmd_end() function:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 674 | |
| 675 | ret = synth_event_gen_cmd_end(&cmd); |
| 676 | |
| 677 | At this point, the event object is ready to be used for tracing new |
| 678 | events. |
| 679 | |
Tom Zanussi | b8170fa | 2020-05-18 13:29:24 -0500 | [diff] [blame] | 680 | 7.2 Tracing synthetic events from in-kernel code |
| 681 | ------------------------------------------------ |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 682 | |
| 683 | To trace a synthetic event, there are several options. The first |
| 684 | option is to trace the event in one call, using synth_event_trace() |
| 685 | with a variable number of values, or synth_event_trace_array() with an |
| 686 | array of values to be set. A second option can be used to avoid the |
| 687 | need for a pre-formed array of values or list of arguments, via |
| 688 | synth_event_trace_start() and synth_event_trace_end() along with |
| 689 | synth_event_add_next_val() or synth_event_add_val() to add the values |
| 690 | piecewise. |
| 691 | |
Tom Zanussi | b8170fa | 2020-05-18 13:29:24 -0500 | [diff] [blame] | 692 | 7.2.1 Tracing a synthetic event all at once |
| 693 | ------------------------------------------- |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 694 | |
| 695 | To trace a synthetic event all at once, the synth_event_trace() or |
| 696 | synth_event_trace_array() functions can be used. |
| 697 | |
| 698 | The synth_event_trace() function is passed the trace_event_file |
| 699 | representing the synthetic event (which can be retrieved using |
| 700 | trace_get_event_file() using the synthetic event name, "synthetic" as |
| 701 | the system name, and the trace instance name (NULL if using the global |
| 702 | trace array)), along with an variable number of u64 args, one for each |
| 703 | synthetic event field, and the number of values being passed. |
| 704 | |
| 705 | So, to trace an event corresponding to the synthetic event definition |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 706 | above, code like the following could be used:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 707 | |
| 708 | ret = synth_event_trace(create_synth_test, 7, /* number of values */ |
| 709 | 444, /* next_pid_field */ |
| 710 | (u64)"clackers", /* next_comm_field */ |
| 711 | 1000000, /* ts_ns */ |
| 712 | 1000, /* ts_ms */ |
| 713 | smp_processor_id(),/* cpu */ |
| 714 | (u64)"Thneed", /* my_string_field */ |
| 715 | 999); /* my_int_field */ |
| 716 | |
| 717 | All vals should be cast to u64, and string vals are just pointers to |
| 718 | strings, cast to u64. Strings will be copied into space reserved in |
| 719 | the event for the string, using these pointers. |
| 720 | |
| 721 | Alternatively, the synth_event_trace_array() function can be used to |
| 722 | accomplish the same thing. It is passed the trace_event_file |
| 723 | representing the synthetic event (which can be retrieved using |
| 724 | trace_get_event_file() using the synthetic event name, "synthetic" as |
| 725 | the system name, and the trace instance name (NULL if using the global |
| 726 | trace array)), along with an array of u64, one for each synthetic |
| 727 | event field. |
| 728 | |
| 729 | To trace an event corresponding to the synthetic event definition |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 730 | above, code like the following could be used:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 731 | |
| 732 | u64 vals[7]; |
| 733 | |
| 734 | vals[0] = 777; /* next_pid_field */ |
| 735 | vals[1] = (u64)"tiddlywinks"; /* next_comm_field */ |
| 736 | vals[2] = 1000000; /* ts_ns */ |
| 737 | vals[3] = 1000; /* ts_ms */ |
| 738 | vals[4] = smp_processor_id(); /* cpu */ |
| 739 | vals[5] = (u64)"thneed"; /* my_string_field */ |
| 740 | vals[6] = 398; /* my_int_field */ |
| 741 | |
| 742 | The 'vals' array is just an array of u64, the number of which must |
| 743 | match the number of field in the synthetic event, and which must be in |
| 744 | the same order as the synthetic event fields. |
| 745 | |
| 746 | All vals should be cast to u64, and string vals are just pointers to |
| 747 | strings, cast to u64. Strings will be copied into space reserved in |
| 748 | the event for the string, using these pointers. |
| 749 | |
| 750 | In order to trace a synthetic event, a pointer to the trace event file |
| 751 | is needed. The trace_get_event_file() function can be used to get |
| 752 | it - it will find the file in the given trace instance (in this case |
| 753 | NULL since the top trace array is being used) while at the same time |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 754 | preventing the instance containing it from going away:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 755 | |
| 756 | schedtest_event_file = trace_get_event_file(NULL, "synthetic", |
| 757 | "schedtest"); |
| 758 | |
| 759 | Before tracing the event, it should be enabled in some way, otherwise |
| 760 | the synthetic event won't actually show up in the trace buffer. |
| 761 | |
| 762 | To enable a synthetic event from the kernel, trace_array_set_clr_event() |
| 763 | can be used (which is not specific to synthetic events, so does need |
| 764 | the "synthetic" system name to be specified explicitly). |
| 765 | |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 766 | To enable the event, pass 'true' to it:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 767 | |
| 768 | trace_array_set_clr_event(schedtest_event_file->tr, |
| 769 | "synthetic", "schedtest", true); |
| 770 | |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 771 | To disable it pass false:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 772 | |
| 773 | trace_array_set_clr_event(schedtest_event_file->tr, |
| 774 | "synthetic", "schedtest", false); |
| 775 | |
| 776 | Finally, synth_event_trace_array() can be used to actually trace the |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 777 | event, which should be visible in the trace buffer afterwards:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 778 | |
| 779 | ret = synth_event_trace_array(schedtest_event_file, vals, |
| 780 | ARRAY_SIZE(vals)); |
| 781 | |
| 782 | To remove the synthetic event, the event should be disabled, and the |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 783 | trace instance should be 'put' back using trace_put_event_file():: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 784 | |
| 785 | trace_array_set_clr_event(schedtest_event_file->tr, |
| 786 | "synthetic", "schedtest", false); |
| 787 | trace_put_event_file(schedtest_event_file); |
| 788 | |
| 789 | If those have been successful, synth_event_delete() can be called to |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 790 | remove the event:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 791 | |
| 792 | ret = synth_event_delete("schedtest"); |
| 793 | |
Tom Zanussi | b8170fa | 2020-05-18 13:29:24 -0500 | [diff] [blame] | 794 | 7.2.2 Tracing a synthetic event piecewise |
| 795 | ----------------------------------------- |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 796 | |
| 797 | To trace a synthetic using the piecewise method described above, the |
| 798 | synth_event_trace_start() function is used to 'open' the synthetic |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 799 | event trace:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 800 | |
Artem Bityutskiy | 301de54 | 2020-11-04 14:21:13 +0200 | [diff] [blame] | 801 | struct synth_event_trace_state trace_state; |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 802 | |
| 803 | ret = synth_event_trace_start(schedtest_event_file, &trace_state); |
| 804 | |
| 805 | It's passed the trace_event_file representing the synthetic event |
| 806 | using the same methods as described above, along with a pointer to a |
Artem Bityutskiy | 301de54 | 2020-11-04 14:21:13 +0200 | [diff] [blame] | 807 | struct synth_event_trace_state object, which will be zeroed before use and |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 808 | used to maintain state between this and following calls. |
| 809 | |
| 810 | Once the event has been opened, which means space for it has been |
| 811 | reserved in the trace buffer, the individual fields can be set. There |
| 812 | are two ways to do that, either one after another for each field in |
| 813 | the event, which requires no lookups, or by name, which does. The |
| 814 | tradeoff is flexibility in doing the assignments vs the cost of a |
| 815 | lookup per field. |
| 816 | |
| 817 | To assign the values one after the other without lookups, |
| 818 | synth_event_add_next_val() should be used. Each call is passed the |
Artem Bityutskiy | 301de54 | 2020-11-04 14:21:13 +0200 | [diff] [blame] | 819 | same synth_event_trace_state object used in the synth_event_trace_start(), |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 820 | along with the value to set the next field in the event. After each |
| 821 | field is set, the 'cursor' points to the next field, which will be set |
| 822 | by the subsequent call, continuing until all the fields have been set |
| 823 | in order. The same sequence of calls as in the above examples using |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 824 | this method would be (without error-handling code):: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 825 | |
| 826 | /* next_pid_field */ |
| 827 | ret = synth_event_add_next_val(777, &trace_state); |
| 828 | |
| 829 | /* next_comm_field */ |
| 830 | ret = synth_event_add_next_val((u64)"slinky", &trace_state); |
| 831 | |
| 832 | /* ts_ns */ |
| 833 | ret = synth_event_add_next_val(1000000, &trace_state); |
| 834 | |
| 835 | /* ts_ms */ |
| 836 | ret = synth_event_add_next_val(1000, &trace_state); |
| 837 | |
| 838 | /* cpu */ |
| 839 | ret = synth_event_add_next_val(smp_processor_id(), &trace_state); |
| 840 | |
| 841 | /* my_string_field */ |
| 842 | ret = synth_event_add_next_val((u64)"thneed_2.01", &trace_state); |
| 843 | |
| 844 | /* my_int_field */ |
| 845 | ret = synth_event_add_next_val(395, &trace_state); |
| 846 | |
| 847 | To assign the values in any order, synth_event_add_val() should be |
Artem Bityutskiy | 301de54 | 2020-11-04 14:21:13 +0200 | [diff] [blame] | 848 | used. Each call is passed the same synth_event_trace_state object used in |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 849 | the synth_event_trace_start(), along with the field name of the field |
| 850 | to set and the value to set it to. The same sequence of calls as in |
| 851 | the above examples using this method would be (without error-handling |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 852 | code):: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 853 | |
| 854 | ret = synth_event_add_val("next_pid_field", 777, &trace_state); |
| 855 | ret = synth_event_add_val("next_comm_field", (u64)"silly putty", |
| 856 | &trace_state); |
| 857 | ret = synth_event_add_val("ts_ns", 1000000, &trace_state); |
| 858 | ret = synth_event_add_val("ts_ms", 1000, &trace_state); |
| 859 | ret = synth_event_add_val("cpu", smp_processor_id(), &trace_state); |
| 860 | ret = synth_event_add_val("my_string_field", (u64)"thneed_9", |
| 861 | &trace_state); |
| 862 | ret = synth_event_add_val("my_int_field", 3999, &trace_state); |
| 863 | |
| 864 | Note that synth_event_add_next_val() and synth_event_add_val() are |
| 865 | incompatible if used within the same trace of an event - either one |
| 866 | can be used but not both at the same time. |
| 867 | |
| 868 | Finally, the event won't be actually traced until it's 'closed', |
| 869 | which is done using synth_event_trace_end(), which takes only the |
Artem Bityutskiy | 301de54 | 2020-11-04 14:21:13 +0200 | [diff] [blame] | 870 | struct synth_event_trace_state object used in the previous calls:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 871 | |
| 872 | ret = synth_event_trace_end(&trace_state); |
| 873 | |
| 874 | Note that synth_event_trace_end() must be called at the end regardless |
| 875 | of whether any of the add calls failed (say due to a bad field name |
| 876 | being passed in). |
| 877 | |
Tom Zanussi | b8170fa | 2020-05-18 13:29:24 -0500 | [diff] [blame] | 878 | 7.3 Dyamically creating kprobe and kretprobe event definitions |
| 879 | -------------------------------------------------------------- |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 880 | |
| 881 | To create a kprobe or kretprobe trace event from kernel code, the |
| 882 | kprobe_event_gen_cmd_start() or kretprobe_event_gen_cmd_start() |
| 883 | functions can be used. |
| 884 | |
| 885 | To create a kprobe event, an empty or partially empty kprobe event |
| 886 | should first be created using kprobe_event_gen_cmd_start(). The name |
| 887 | of the event and the probe location should be specfied along with one |
| 888 | or args each representing a probe field should be supplied to this |
| 889 | function. Before calling kprobe_event_gen_cmd_start(), the user |
| 890 | should create and initialize a dynevent_cmd object using |
| 891 | kprobe_event_cmd_init(). |
| 892 | |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 893 | For example, to create a new "schedtest" kprobe event with two fields:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 894 | |
| 895 | struct dynevent_cmd cmd; |
| 896 | char *buf; |
| 897 | |
| 898 | /* Create a buffer to hold the generated command */ |
| 899 | buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL); |
| 900 | |
| 901 | /* Before generating the command, initialize the cmd object */ |
| 902 | kprobe_event_cmd_init(&cmd, buf, MAX_DYNEVENT_CMD_LEN); |
| 903 | |
| 904 | /* |
| 905 | * Define the gen_kprobe_test event with the first 2 kprobe |
| 906 | * fields. |
| 907 | */ |
| 908 | ret = kprobe_event_gen_cmd_start(&cmd, "gen_kprobe_test", "do_sys_open", |
| 909 | "dfd=%ax", "filename=%dx"); |
| 910 | |
| 911 | Once the kprobe event object has been created, it can then be |
| 912 | populated with more fields. Fields can be added using |
| 913 | kprobe_event_add_fields(), supplying the dynevent_cmd object along |
| 914 | with a variable arg list of probe fields. For example, to add a |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 915 | couple additional fields, the following call could be made:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 916 | |
| 917 | ret = kprobe_event_add_fields(&cmd, "flags=%cx", "mode=+4($stack)"); |
| 918 | |
| 919 | Once all the fields have been added, the event should be finalized and |
| 920 | registered by calling the kprobe_event_gen_cmd_end() or |
| 921 | kretprobe_event_gen_cmd_end() functions, depending on whether a kprobe |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 922 | or kretprobe command was started:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 923 | |
| 924 | ret = kprobe_event_gen_cmd_end(&cmd); |
| 925 | |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 926 | or:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 927 | |
| 928 | ret = kretprobe_event_gen_cmd_end(&cmd); |
| 929 | |
| 930 | At this point, the event object is ready to be used for tracing new |
| 931 | events. |
| 932 | |
| 933 | Similarly, a kretprobe event can be created using |
| 934 | kretprobe_event_gen_cmd_start() with a probe name and location and |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 935 | additional params such as $retval:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 936 | |
| 937 | ret = kretprobe_event_gen_cmd_start(&cmd, "gen_kretprobe_test", |
| 938 | "do_sys_open", "$retval"); |
| 939 | |
| 940 | Similar to the synthetic event case, code like the following can be |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 941 | used to enable the newly created kprobe event:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 942 | |
| 943 | gen_kprobe_test = trace_get_event_file(NULL, "kprobes", "gen_kprobe_test"); |
| 944 | |
| 945 | ret = trace_array_set_clr_event(gen_kprobe_test->tr, |
| 946 | "kprobes", "gen_kprobe_test", true); |
| 947 | |
| 948 | Finally, also similar to synthetic events, the following code can be |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 949 | used to give the kprobe event file back and delete the event:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 950 | |
| 951 | trace_put_event_file(gen_kprobe_test); |
| 952 | |
| 953 | ret = kprobe_event_delete("gen_kprobe_test"); |
| 954 | |
Tom Zanussi | b8170fa | 2020-05-18 13:29:24 -0500 | [diff] [blame] | 955 | 7.4 The "dynevent_cmd" low-level API |
| 956 | ------------------------------------ |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 957 | |
| 958 | Both the in-kernel synthetic event and kprobe interfaces are built on |
| 959 | top of a lower-level "dynevent_cmd" interface. This interface is |
| 960 | meant to provide the basis for higher-level interfaces such as the |
| 961 | synthetic and kprobe interfaces, which can be used as examples. |
| 962 | |
| 963 | The basic idea is simple and amounts to providing a general-purpose |
| 964 | layer that can be used to generate trace event commands. The |
| 965 | generated command strings can then be passed to the command-parsing |
| 966 | and event creation code that already exists in the trace event |
| 967 | subystem for creating the corresponding trace events. |
| 968 | |
| 969 | In a nutshell, the way it works is that the higher-level interface |
| 970 | code creates a struct dynevent_cmd object, then uses a couple |
| 971 | functions, dynevent_arg_add() and dynevent_arg_pair_add() to build up |
| 972 | a command string, which finally causes the command to be executed |
| 973 | using the dynevent_create() function. The details of the interface |
| 974 | are described below. |
| 975 | |
| 976 | The first step in building a new command string is to create and |
| 977 | initialize an instance of a dynevent_cmd. Here, for instance, we |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 978 | create a dynevent_cmd on the stack and initialize it:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 979 | |
| 980 | struct dynevent_cmd cmd; |
| 981 | char *buf; |
| 982 | int ret; |
| 983 | |
| 984 | buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL); |
| 985 | |
| 986 | dynevent_cmd_init(cmd, buf, maxlen, DYNEVENT_TYPE_FOO, |
| 987 | foo_event_run_command); |
| 988 | |
| 989 | The dynevent_cmd initialization needs to be given a user-specified |
| 990 | buffer and the length of the buffer (MAX_DYNEVENT_CMD_LEN can be used |
| 991 | for this purpose - at 2k it's generally too big to be comfortably put |
| 992 | on the stack, so is dynamically allocated), a dynevent type id, which |
| 993 | is meant to be used to check that further API calls are for the |
| 994 | correct command type, and a pointer to an event-specific run_command() |
| 995 | callback that will be called to actually execute the event-specific |
| 996 | command function. |
| 997 | |
| 998 | Once that's done, the command string can by built up by successive |
| 999 | calls to argument-adding functions. |
| 1000 | |
| 1001 | To add a single argument, define and initialize a struct dynevent_arg |
| 1002 | or struct dynevent_arg_pair object. Here's an example of the simplest |
| 1003 | possible arg addition, which is simply to append the given string as |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 1004 | a whitespace-separated argument to the command:: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 1005 | |
| 1006 | struct dynevent_arg arg; |
| 1007 | |
| 1008 | dynevent_arg_init(&arg, NULL, 0); |
| 1009 | |
| 1010 | arg.str = name; |
| 1011 | |
| 1012 | ret = dynevent_arg_add(cmd, &arg); |
| 1013 | |
| 1014 | The arg object is first initialized using dynevent_arg_init() and in |
| 1015 | this case the parameters are NULL or 0, which means there's no |
| 1016 | optional sanity-checking function or separator appended to the end of |
| 1017 | the arg. |
| 1018 | |
| 1019 | Here's another more complicated example using an 'arg pair', which is |
| 1020 | used to create an argument that consists of a couple components added |
| 1021 | together as a unit, for example, a 'type field_name;' arg or a simple |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 1022 | expression arg e.g. 'flags=%cx':: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 1023 | |
| 1024 | struct dynevent_arg_pair arg_pair; |
| 1025 | |
| 1026 | dynevent_arg_pair_init(&arg_pair, dynevent_foo_check_arg_fn, 0, ';'); |
| 1027 | |
| 1028 | arg_pair.lhs = type; |
| 1029 | arg_pair.rhs = name; |
| 1030 | |
| 1031 | ret = dynevent_arg_pair_add(cmd, &arg_pair); |
| 1032 | |
| 1033 | Again, the arg_pair is first initialized, in this case with a callback |
| 1034 | function used to check the sanity of the args (for example, that |
| 1035 | neither part of the pair is NULL), along with a character to be used |
| 1036 | to add an operator between the pair (here none) and a separator to be |
| 1037 | appended onto the end of the arg pair (here ';'). |
| 1038 | |
| 1039 | There's also a dynevent_str_add() function that can be used to simply |
| 1040 | add a string as-is, with no spaces, delimeters, or arg check. |
| 1041 | |
| 1042 | Any number of dynevent_*_add() calls can be made to build up the string |
| 1043 | (until its length surpasses cmd->maxlen). When all the arguments have |
| 1044 | been added and the command string is complete, the only thing left to |
| 1045 | do is run the command, which happens by simply calling |
Mauro Carvalho Chehab | 8206de7 | 2020-03-03 16:50:31 +0100 | [diff] [blame] | 1046 | dynevent_create():: |
Tom Zanussi | 34ed635 | 2020-01-29 12:59:32 -0600 | [diff] [blame] | 1047 | |
| 1048 | ret = dynevent_create(&cmd); |
| 1049 | |
| 1050 | At that point, if the return value is 0, the dynamic event has been |
| 1051 | created and is ready to use. |
| 1052 | |
| 1053 | See the dynevent_cmd function definitions themselves for the details |
| 1054 | of the API. |