Commit | Line | Data |
---|---|---|
726721a5 TZ |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * trace_events_synth - synthetic trace events | |
4 | * | |
5 | * Copyright (C) 2015, 2020 Tom Zanussi <tom.zanussi@linux.intel.com> | |
6 | */ | |
7 | ||
8 | #include <linux/module.h> | |
9 | #include <linux/kallsyms.h> | |
10 | #include <linux/security.h> | |
11 | #include <linux/mutex.h> | |
12 | #include <linux/slab.h> | |
13 | #include <linux/stacktrace.h> | |
14 | #include <linux/rculist.h> | |
15 | #include <linux/tracefs.h> | |
16 | ||
17 | /* for gfp flag names */ | |
18 | #include <linux/trace_events.h> | |
19 | #include <trace/events/mmflags.h> | |
20 | ||
21 | #include "trace_synth.h" | |
22 | ||
d4d70463 TZ |
23 | #undef ERRORS |
24 | #define ERRORS \ | |
25 | C(BAD_NAME, "Illegal name"), \ | |
26 | C(CMD_INCOMPLETE, "Incomplete command"), \ | |
27 | C(EVENT_EXISTS, "Event already exists"), \ | |
28 | C(TOO_MANY_FIELDS, "Too many fields"), \ | |
29 | C(INCOMPLETE_TYPE, "Incomplete type"), \ | |
30 | C(INVALID_TYPE, "Invalid type"), \ | |
31 | C(INVALID_FIELD, "Invalid field"), \ | |
32 | C(CMD_TOO_LONG, "Command too long"), | |
33 | ||
34 | #undef C | |
35 | #define C(a, b) SYNTH_ERR_##a | |
36 | ||
37 | enum { ERRORS }; | |
38 | ||
39 | #undef C | |
40 | #define C(a, b) b | |
41 | ||
42 | static const char *err_text[] = { ERRORS }; | |
43 | ||
44 | static char last_cmd[MAX_FILTER_STR_VAL]; | |
45 | ||
46 | static int errpos(const char *str) | |
47 | { | |
48 | return err_pos(last_cmd, str); | |
49 | } | |
50 | ||
51 | static void last_cmd_set(char *str) | |
52 | { | |
53 | if (!str) | |
54 | return; | |
55 | ||
56 | strncpy(last_cmd, str, MAX_FILTER_STR_VAL - 1); | |
57 | } | |
58 | ||
59 | static void synth_err(u8 err_type, u8 err_pos) | |
60 | { | |
61 | tracing_log_err(NULL, "synthetic_events", last_cmd, err_text, | |
62 | err_type, err_pos); | |
63 | } | |
64 | ||
726721a5 TZ |
65 | static int create_synth_event(int argc, const char **argv); |
66 | static int synth_event_show(struct seq_file *m, struct dyn_event *ev); | |
67 | static int synth_event_release(struct dyn_event *ev); | |
68 | static bool synth_event_is_busy(struct dyn_event *ev); | |
69 | static bool synth_event_match(const char *system, const char *event, | |
70 | int argc, const char **argv, struct dyn_event *ev); | |
71 | ||
72 | static struct dyn_event_operations synth_event_ops = { | |
73 | .create = create_synth_event, | |
74 | .show = synth_event_show, | |
75 | .is_busy = synth_event_is_busy, | |
76 | .free = synth_event_release, | |
77 | .match = synth_event_match, | |
78 | }; | |
79 | ||
80 | static bool is_synth_event(struct dyn_event *ev) | |
81 | { | |
82 | return ev->ops == &synth_event_ops; | |
83 | } | |
84 | ||
85 | static struct synth_event *to_synth_event(struct dyn_event *ev) | |
86 | { | |
87 | return container_of(ev, struct synth_event, devent); | |
88 | } | |
89 | ||
90 | static bool synth_event_is_busy(struct dyn_event *ev) | |
91 | { | |
92 | struct synth_event *event = to_synth_event(ev); | |
93 | ||
94 | return event->ref != 0; | |
95 | } | |
96 | ||
97 | static bool synth_event_match(const char *system, const char *event, | |
98 | int argc, const char **argv, struct dyn_event *ev) | |
99 | { | |
100 | struct synth_event *sev = to_synth_event(ev); | |
101 | ||
102 | return strcmp(sev->name, event) == 0 && | |
103 | (!system || strcmp(system, SYNTH_SYSTEM) == 0); | |
104 | } | |
105 | ||
106 | struct synth_trace_event { | |
107 | struct trace_entry ent; | |
108 | u64 fields[]; | |
109 | }; | |
110 | ||
111 | static int synth_event_define_fields(struct trace_event_call *call) | |
112 | { | |
113 | struct synth_trace_event trace; | |
114 | int offset = offsetof(typeof(trace), fields); | |
115 | struct synth_event *event = call->data; | |
116 | unsigned int i, size, n_u64; | |
117 | char *name, *type; | |
118 | bool is_signed; | |
119 | int ret = 0; | |
120 | ||
121 | for (i = 0, n_u64 = 0; i < event->n_fields; i++) { | |
122 | size = event->fields[i]->size; | |
123 | is_signed = event->fields[i]->is_signed; | |
124 | type = event->fields[i]->type; | |
125 | name = event->fields[i]->name; | |
126 | ret = trace_define_field(call, type, name, offset, size, | |
127 | is_signed, FILTER_OTHER); | |
128 | if (ret) | |
129 | break; | |
130 | ||
131 | event->fields[i]->offset = n_u64; | |
132 | ||
bd82631d | 133 | if (event->fields[i]->is_string && !event->fields[i]->is_dynamic) { |
726721a5 TZ |
134 | offset += STR_VAR_LEN_MAX; |
135 | n_u64 += STR_VAR_LEN_MAX / sizeof(u64); | |
136 | } else { | |
137 | offset += sizeof(u64); | |
138 | n_u64++; | |
139 | } | |
140 | } | |
141 | ||
142 | event->n_u64 = n_u64; | |
143 | ||
144 | return ret; | |
145 | } | |
146 | ||
147 | static bool synth_field_signed(char *type) | |
148 | { | |
149 | if (str_has_prefix(type, "u")) | |
150 | return false; | |
151 | if (strcmp(type, "gfp_t") == 0) | |
152 | return false; | |
153 | ||
154 | return true; | |
155 | } | |
156 | ||
157 | static int synth_field_is_string(char *type) | |
158 | { | |
159 | if (strstr(type, "char[") != NULL) | |
160 | return true; | |
161 | ||
162 | return false; | |
163 | } | |
164 | ||
165 | static int synth_field_string_size(char *type) | |
166 | { | |
167 | char buf[4], *end, *start; | |
168 | unsigned int len; | |
169 | int size, err; | |
170 | ||
171 | start = strstr(type, "char["); | |
172 | if (start == NULL) | |
173 | return -EINVAL; | |
174 | start += sizeof("char[") - 1; | |
175 | ||
176 | end = strchr(type, ']'); | |
10819e25 | 177 | if (!end || end < start || type + strlen(type) > end + 1) |
726721a5 TZ |
178 | return -EINVAL; |
179 | ||
180 | len = end - start; | |
181 | if (len > 3) | |
182 | return -EINVAL; | |
183 | ||
bd82631d TZ |
184 | if (len == 0) |
185 | return 0; /* variable-length string */ | |
186 | ||
726721a5 TZ |
187 | strncpy(buf, start, len); |
188 | buf[len] = '\0'; | |
189 | ||
190 | err = kstrtouint(buf, 0, &size); | |
191 | if (err) | |
192 | return err; | |
193 | ||
194 | if (size > STR_VAR_LEN_MAX) | |
195 | return -EINVAL; | |
196 | ||
197 | return size; | |
198 | } | |
199 | ||
200 | static int synth_field_size(char *type) | |
201 | { | |
202 | int size = 0; | |
203 | ||
204 | if (strcmp(type, "s64") == 0) | |
205 | size = sizeof(s64); | |
206 | else if (strcmp(type, "u64") == 0) | |
207 | size = sizeof(u64); | |
208 | else if (strcmp(type, "s32") == 0) | |
209 | size = sizeof(s32); | |
210 | else if (strcmp(type, "u32") == 0) | |
211 | size = sizeof(u32); | |
212 | else if (strcmp(type, "s16") == 0) | |
213 | size = sizeof(s16); | |
214 | else if (strcmp(type, "u16") == 0) | |
215 | size = sizeof(u16); | |
216 | else if (strcmp(type, "s8") == 0) | |
217 | size = sizeof(s8); | |
218 | else if (strcmp(type, "u8") == 0) | |
219 | size = sizeof(u8); | |
220 | else if (strcmp(type, "char") == 0) | |
221 | size = sizeof(char); | |
222 | else if (strcmp(type, "unsigned char") == 0) | |
223 | size = sizeof(unsigned char); | |
224 | else if (strcmp(type, "int") == 0) | |
225 | size = sizeof(int); | |
226 | else if (strcmp(type, "unsigned int") == 0) | |
227 | size = sizeof(unsigned int); | |
228 | else if (strcmp(type, "long") == 0) | |
229 | size = sizeof(long); | |
230 | else if (strcmp(type, "unsigned long") == 0) | |
231 | size = sizeof(unsigned long); | |
6107742d AR |
232 | else if (strcmp(type, "bool") == 0) |
233 | size = sizeof(bool); | |
726721a5 TZ |
234 | else if (strcmp(type, "pid_t") == 0) |
235 | size = sizeof(pid_t); | |
236 | else if (strcmp(type, "gfp_t") == 0) | |
237 | size = sizeof(gfp_t); | |
238 | else if (synth_field_is_string(type)) | |
239 | size = synth_field_string_size(type); | |
240 | ||
241 | return size; | |
242 | } | |
243 | ||
244 | static const char *synth_field_fmt(char *type) | |
245 | { | |
246 | const char *fmt = "%llu"; | |
247 | ||
248 | if (strcmp(type, "s64") == 0) | |
249 | fmt = "%lld"; | |
250 | else if (strcmp(type, "u64") == 0) | |
251 | fmt = "%llu"; | |
252 | else if (strcmp(type, "s32") == 0) | |
253 | fmt = "%d"; | |
254 | else if (strcmp(type, "u32") == 0) | |
255 | fmt = "%u"; | |
256 | else if (strcmp(type, "s16") == 0) | |
257 | fmt = "%d"; | |
258 | else if (strcmp(type, "u16") == 0) | |
259 | fmt = "%u"; | |
260 | else if (strcmp(type, "s8") == 0) | |
261 | fmt = "%d"; | |
262 | else if (strcmp(type, "u8") == 0) | |
263 | fmt = "%u"; | |
264 | else if (strcmp(type, "char") == 0) | |
265 | fmt = "%d"; | |
266 | else if (strcmp(type, "unsigned char") == 0) | |
267 | fmt = "%u"; | |
268 | else if (strcmp(type, "int") == 0) | |
269 | fmt = "%d"; | |
270 | else if (strcmp(type, "unsigned int") == 0) | |
271 | fmt = "%u"; | |
272 | else if (strcmp(type, "long") == 0) | |
273 | fmt = "%ld"; | |
274 | else if (strcmp(type, "unsigned long") == 0) | |
275 | fmt = "%lu"; | |
6107742d AR |
276 | else if (strcmp(type, "bool") == 0) |
277 | fmt = "%d"; | |
726721a5 TZ |
278 | else if (strcmp(type, "pid_t") == 0) |
279 | fmt = "%d"; | |
280 | else if (strcmp(type, "gfp_t") == 0) | |
281 | fmt = "%x"; | |
282 | else if (synth_field_is_string(type)) | |
8db4d6bf | 283 | fmt = "%.*s"; |
726721a5 TZ |
284 | |
285 | return fmt; | |
286 | } | |
287 | ||
288 | static void print_synth_event_num_val(struct trace_seq *s, | |
289 | char *print_fmt, char *name, | |
290 | int size, u64 val, char *space) | |
291 | { | |
292 | switch (size) { | |
293 | case 1: | |
294 | trace_seq_printf(s, print_fmt, name, (u8)val, space); | |
295 | break; | |
296 | ||
297 | case 2: | |
298 | trace_seq_printf(s, print_fmt, name, (u16)val, space); | |
299 | break; | |
300 | ||
301 | case 4: | |
302 | trace_seq_printf(s, print_fmt, name, (u32)val, space); | |
303 | break; | |
304 | ||
305 | default: | |
306 | trace_seq_printf(s, print_fmt, name, val, space); | |
307 | break; | |
308 | } | |
309 | } | |
310 | ||
311 | static enum print_line_t print_synth_event(struct trace_iterator *iter, | |
312 | int flags, | |
313 | struct trace_event *event) | |
314 | { | |
315 | struct trace_array *tr = iter->tr; | |
316 | struct trace_seq *s = &iter->seq; | |
317 | struct synth_trace_event *entry; | |
318 | struct synth_event *se; | |
319 | unsigned int i, n_u64; | |
320 | char print_fmt[32]; | |
321 | const char *fmt; | |
322 | ||
323 | entry = (struct synth_trace_event *)iter->ent; | |
324 | se = container_of(event, struct synth_event, call.event); | |
325 | ||
326 | trace_seq_printf(s, "%s: ", se->name); | |
327 | ||
328 | for (i = 0, n_u64 = 0; i < se->n_fields; i++) { | |
329 | if (trace_seq_has_overflowed(s)) | |
330 | goto end; | |
331 | ||
332 | fmt = synth_field_fmt(se->fields[i]->type); | |
333 | ||
334 | /* parameter types */ | |
335 | if (tr && tr->trace_flags & TRACE_ITER_VERBOSE) | |
336 | trace_seq_printf(s, "%s ", fmt); | |
337 | ||
338 | snprintf(print_fmt, sizeof(print_fmt), "%%s=%s%%s", fmt); | |
339 | ||
340 | /* parameter values */ | |
341 | if (se->fields[i]->is_string) { | |
bd82631d TZ |
342 | if (se->fields[i]->is_dynamic) { |
343 | u32 offset, data_offset; | |
344 | char *str_field; | |
345 | ||
346 | offset = (u32)entry->fields[n_u64]; | |
347 | data_offset = offset & 0xffff; | |
348 | ||
349 | str_field = (char *)entry + data_offset; | |
350 | ||
351 | trace_seq_printf(s, print_fmt, se->fields[i]->name, | |
8db4d6bf | 352 | STR_VAR_LEN_MAX, |
bd82631d TZ |
353 | str_field, |
354 | i == se->n_fields - 1 ? "" : " "); | |
355 | n_u64++; | |
356 | } else { | |
357 | trace_seq_printf(s, print_fmt, se->fields[i]->name, | |
8db4d6bf | 358 | STR_VAR_LEN_MAX, |
bd82631d TZ |
359 | (char *)&entry->fields[n_u64], |
360 | i == se->n_fields - 1 ? "" : " "); | |
361 | n_u64 += STR_VAR_LEN_MAX / sizeof(u64); | |
362 | } | |
726721a5 TZ |
363 | } else { |
364 | struct trace_print_flags __flags[] = { | |
365 | __def_gfpflag_names, {-1, NULL} }; | |
366 | char *space = (i == se->n_fields - 1 ? "" : " "); | |
367 | ||
368 | print_synth_event_num_val(s, print_fmt, | |
369 | se->fields[i]->name, | |
370 | se->fields[i]->size, | |
371 | entry->fields[n_u64], | |
372 | space); | |
373 | ||
374 | if (strcmp(se->fields[i]->type, "gfp_t") == 0) { | |
375 | trace_seq_puts(s, " ("); | |
376 | trace_print_flags_seq(s, "|", | |
377 | entry->fields[n_u64], | |
378 | __flags); | |
379 | trace_seq_putc(s, ')'); | |
380 | } | |
381 | n_u64++; | |
382 | } | |
383 | } | |
384 | end: | |
385 | trace_seq_putc(s, '\n'); | |
386 | ||
387 | return trace_handle_return(s); | |
388 | } | |
389 | ||
390 | static struct trace_event_functions synth_event_funcs = { | |
391 | .trace = print_synth_event | |
392 | }; | |
393 | ||
bd82631d TZ |
394 | static unsigned int trace_string(struct synth_trace_event *entry, |
395 | struct synth_event *event, | |
396 | char *str_val, | |
397 | bool is_dynamic, | |
398 | unsigned int data_size, | |
399 | unsigned int *n_u64) | |
400 | { | |
401 | unsigned int len = 0; | |
402 | char *str_field; | |
403 | ||
404 | if (is_dynamic) { | |
405 | u32 data_offset; | |
406 | ||
407 | data_offset = offsetof(typeof(*entry), fields); | |
408 | data_offset += event->n_u64 * sizeof(u64); | |
409 | data_offset += data_size; | |
410 | ||
411 | str_field = (char *)entry + data_offset; | |
412 | ||
413 | len = strlen(str_val) + 1; | |
414 | strscpy(str_field, str_val, len); | |
415 | ||
416 | data_offset |= len << 16; | |
417 | *(u32 *)&entry->fields[*n_u64] = data_offset; | |
418 | ||
419 | (*n_u64)++; | |
420 | } else { | |
421 | str_field = (char *)&entry->fields[*n_u64]; | |
422 | ||
423 | strscpy(str_field, str_val, STR_VAR_LEN_MAX); | |
424 | (*n_u64) += STR_VAR_LEN_MAX / sizeof(u64); | |
425 | } | |
426 | ||
427 | return len; | |
428 | } | |
429 | ||
726721a5 TZ |
430 | static notrace void trace_event_raw_event_synth(void *__data, |
431 | u64 *var_ref_vals, | |
432 | unsigned int *var_ref_idx) | |
433 | { | |
bd82631d | 434 | unsigned int i, n_u64, val_idx, len, data_size = 0; |
726721a5 TZ |
435 | struct trace_event_file *trace_file = __data; |
436 | struct synth_trace_event *entry; | |
437 | struct trace_event_buffer fbuffer; | |
438 | struct trace_buffer *buffer; | |
439 | struct synth_event *event; | |
726721a5 TZ |
440 | int fields_size = 0; |
441 | ||
442 | event = trace_file->event_call->data; | |
443 | ||
444 | if (trace_trigger_soft_disabled(trace_file)) | |
445 | return; | |
446 | ||
447 | fields_size = event->n_u64 * sizeof(u64); | |
448 | ||
bd82631d TZ |
449 | for (i = 0; i < event->n_dynamic_fields; i++) { |
450 | unsigned int field_pos = event->dynamic_fields[i]->field_pos; | |
451 | char *str_val; | |
452 | ||
453 | val_idx = var_ref_idx[field_pos]; | |
454 | str_val = (char *)(long)var_ref_vals[val_idx]; | |
455 | ||
456 | len = strlen(str_val) + 1; | |
457 | ||
458 | fields_size += len; | |
459 | } | |
460 | ||
726721a5 TZ |
461 | /* |
462 | * Avoid ring buffer recursion detection, as this event | |
463 | * is being performed within another event. | |
464 | */ | |
465 | buffer = trace_file->tr->array_buffer.buffer; | |
466 | ring_buffer_nest_start(buffer); | |
467 | ||
468 | entry = trace_event_buffer_reserve(&fbuffer, trace_file, | |
469 | sizeof(*entry) + fields_size); | |
470 | if (!entry) | |
471 | goto out; | |
472 | ||
473 | for (i = 0, n_u64 = 0; i < event->n_fields; i++) { | |
474 | val_idx = var_ref_idx[i]; | |
475 | if (event->fields[i]->is_string) { | |
476 | char *str_val = (char *)(long)var_ref_vals[val_idx]; | |
726721a5 | 477 | |
bd82631d TZ |
478 | len = trace_string(entry, event, str_val, |
479 | event->fields[i]->is_dynamic, | |
480 | data_size, &n_u64); | |
481 | data_size += len; /* only dynamic string increments */ | |
726721a5 TZ |
482 | } else { |
483 | struct synth_field *field = event->fields[i]; | |
484 | u64 val = var_ref_vals[val_idx]; | |
485 | ||
486 | switch (field->size) { | |
487 | case 1: | |
488 | *(u8 *)&entry->fields[n_u64] = (u8)val; | |
489 | break; | |
490 | ||
491 | case 2: | |
492 | *(u16 *)&entry->fields[n_u64] = (u16)val; | |
493 | break; | |
494 | ||
495 | case 4: | |
496 | *(u32 *)&entry->fields[n_u64] = (u32)val; | |
497 | break; | |
498 | ||
499 | default: | |
500 | entry->fields[n_u64] = val; | |
501 | break; | |
502 | } | |
503 | n_u64++; | |
504 | } | |
505 | } | |
506 | ||
507 | trace_event_buffer_commit(&fbuffer); | |
508 | out: | |
509 | ring_buffer_nest_end(buffer); | |
510 | } | |
511 | ||
512 | static void free_synth_event_print_fmt(struct trace_event_call *call) | |
513 | { | |
514 | if (call) { | |
515 | kfree(call->print_fmt); | |
516 | call->print_fmt = NULL; | |
517 | } | |
518 | } | |
519 | ||
520 | static int __set_synth_event_print_fmt(struct synth_event *event, | |
521 | char *buf, int len) | |
522 | { | |
523 | const char *fmt; | |
524 | int pos = 0; | |
525 | int i; | |
526 | ||
527 | /* When len=0, we just calculate the needed length */ | |
528 | #define LEN_OR_ZERO (len ? len - pos : 0) | |
529 | ||
530 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\""); | |
531 | for (i = 0; i < event->n_fields; i++) { | |
532 | fmt = synth_field_fmt(event->fields[i]->type); | |
533 | pos += snprintf(buf + pos, LEN_OR_ZERO, "%s=%s%s", | |
534 | event->fields[i]->name, fmt, | |
535 | i == event->n_fields - 1 ? "" : ", "); | |
536 | } | |
537 | pos += snprintf(buf + pos, LEN_OR_ZERO, "\""); | |
538 | ||
539 | for (i = 0; i < event->n_fields; i++) { | |
84818355 | 540 | if (event->fields[i]->is_string && |
bd82631d TZ |
541 | event->fields[i]->is_dynamic) |
542 | pos += snprintf(buf + pos, LEN_OR_ZERO, | |
543 | ", __get_str(%s)", event->fields[i]->name); | |
544 | else | |
545 | pos += snprintf(buf + pos, LEN_OR_ZERO, | |
546 | ", REC->%s", event->fields[i]->name); | |
726721a5 TZ |
547 | } |
548 | ||
549 | #undef LEN_OR_ZERO | |
550 | ||
551 | /* return the length of print_fmt */ | |
552 | return pos; | |
553 | } | |
554 | ||
555 | static int set_synth_event_print_fmt(struct trace_event_call *call) | |
556 | { | |
557 | struct synth_event *event = call->data; | |
558 | char *print_fmt; | |
559 | int len; | |
560 | ||
561 | /* First: called with 0 length to calculate the needed length */ | |
562 | len = __set_synth_event_print_fmt(event, NULL, 0); | |
563 | ||
564 | print_fmt = kmalloc(len + 1, GFP_KERNEL); | |
565 | if (!print_fmt) | |
566 | return -ENOMEM; | |
567 | ||
568 | /* Second: actually write the @print_fmt */ | |
569 | __set_synth_event_print_fmt(event, print_fmt, len + 1); | |
570 | call->print_fmt = print_fmt; | |
571 | ||
572 | return 0; | |
573 | } | |
574 | ||
575 | static void free_synth_field(struct synth_field *field) | |
576 | { | |
577 | kfree(field->type); | |
578 | kfree(field->name); | |
579 | kfree(field); | |
580 | } | |
581 | ||
582 | static struct synth_field *parse_synth_field(int argc, const char **argv, | |
583 | int *consumed) | |
584 | { | |
585 | struct synth_field *field; | |
586 | const char *prefix = NULL, *field_type = argv[0], *field_name, *array; | |
587 | int len, ret = 0; | |
8fbeb52a | 588 | ssize_t size; |
726721a5 TZ |
589 | |
590 | if (field_type[0] == ';') | |
591 | field_type++; | |
592 | ||
593 | if (!strcmp(field_type, "unsigned")) { | |
d4d70463 TZ |
594 | if (argc < 3) { |
595 | synth_err(SYNTH_ERR_INCOMPLETE_TYPE, errpos(field_type)); | |
726721a5 | 596 | return ERR_PTR(-EINVAL); |
d4d70463 | 597 | } |
726721a5 TZ |
598 | prefix = "unsigned "; |
599 | field_type = argv[1]; | |
600 | field_name = argv[2]; | |
601 | *consumed = 3; | |
602 | } else { | |
603 | field_name = argv[1]; | |
604 | *consumed = 2; | |
605 | } | |
606 | ||
607 | field = kzalloc(sizeof(*field), GFP_KERNEL); | |
608 | if (!field) | |
609 | return ERR_PTR(-ENOMEM); | |
610 | ||
611 | len = strlen(field_name); | |
612 | array = strchr(field_name, '['); | |
613 | if (array) | |
614 | len -= strlen(array); | |
615 | else if (field_name[len - 1] == ';') | |
616 | len--; | |
617 | ||
618 | field->name = kmemdup_nul(field_name, len, GFP_KERNEL); | |
619 | if (!field->name) { | |
620 | ret = -ENOMEM; | |
621 | goto free; | |
622 | } | |
9bbb3329 | 623 | if (!is_good_name(field->name)) { |
d4d70463 | 624 | synth_err(SYNTH_ERR_BAD_NAME, errpos(field_name)); |
9bbb3329 TZ |
625 | ret = -EINVAL; |
626 | goto free; | |
627 | } | |
726721a5 TZ |
628 | |
629 | if (field_type[0] == ';') | |
630 | field_type++; | |
631 | len = strlen(field_type) + 1; | |
10819e25 TZ |
632 | |
633 | if (array) { | |
634 | int l = strlen(array); | |
635 | ||
636 | if (l && array[l - 1] == ';') | |
637 | l--; | |
638 | len += l; | |
639 | } | |
726721a5 TZ |
640 | if (prefix) |
641 | len += strlen(prefix); | |
642 | ||
643 | field->type = kzalloc(len, GFP_KERNEL); | |
644 | if (!field->type) { | |
645 | ret = -ENOMEM; | |
646 | goto free; | |
647 | } | |
648 | if (prefix) | |
649 | strcat(field->type, prefix); | |
650 | strcat(field->type, field_type); | |
651 | if (array) { | |
652 | strcat(field->type, array); | |
653 | if (field->type[len - 1] == ';') | |
654 | field->type[len - 1] = '\0'; | |
655 | } | |
656 | ||
8fbeb52a | 657 | size = synth_field_size(field->type); |
bd82631d | 658 | if (size < 0) { |
d4d70463 | 659 | synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type)); |
726721a5 TZ |
660 | ret = -EINVAL; |
661 | goto free; | |
bd82631d TZ |
662 | } else if (size == 0) { |
663 | if (synth_field_is_string(field->type)) { | |
664 | char *type; | |
665 | ||
666 | type = kzalloc(sizeof("__data_loc ") + strlen(field->type) + 1, GFP_KERNEL); | |
667 | if (!type) { | |
668 | ret = -ENOMEM; | |
669 | goto free; | |
670 | } | |
671 | ||
672 | strcat(type, "__data_loc "); | |
673 | strcat(type, field->type); | |
674 | kfree(field->type); | |
675 | field->type = type; | |
676 | ||
677 | field->is_dynamic = true; | |
678 | size = sizeof(u64); | |
679 | } else { | |
d4d70463 | 680 | synth_err(SYNTH_ERR_INVALID_TYPE, errpos(field_type)); |
bd82631d TZ |
681 | ret = -EINVAL; |
682 | goto free; | |
683 | } | |
726721a5 | 684 | } |
8fbeb52a | 685 | field->size = size; |
726721a5 TZ |
686 | |
687 | if (synth_field_is_string(field->type)) | |
688 | field->is_string = true; | |
689 | ||
690 | field->is_signed = synth_field_signed(field->type); | |
726721a5 TZ |
691 | out: |
692 | return field; | |
693 | free: | |
694 | free_synth_field(field); | |
695 | field = ERR_PTR(ret); | |
696 | goto out; | |
697 | } | |
698 | ||
699 | static void free_synth_tracepoint(struct tracepoint *tp) | |
700 | { | |
701 | if (!tp) | |
702 | return; | |
703 | ||
704 | kfree(tp->name); | |
705 | kfree(tp); | |
706 | } | |
707 | ||
708 | static struct tracepoint *alloc_synth_tracepoint(char *name) | |
709 | { | |
710 | struct tracepoint *tp; | |
711 | ||
712 | tp = kzalloc(sizeof(*tp), GFP_KERNEL); | |
713 | if (!tp) | |
714 | return ERR_PTR(-ENOMEM); | |
715 | ||
716 | tp->name = kstrdup(name, GFP_KERNEL); | |
717 | if (!tp->name) { | |
718 | kfree(tp); | |
719 | return ERR_PTR(-ENOMEM); | |
720 | } | |
721 | ||
722 | return tp; | |
723 | } | |
724 | ||
725 | struct synth_event *find_synth_event(const char *name) | |
726 | { | |
727 | struct dyn_event *pos; | |
728 | struct synth_event *event; | |
729 | ||
730 | for_each_dyn_event(pos) { | |
731 | if (!is_synth_event(pos)) | |
732 | continue; | |
733 | event = to_synth_event(pos); | |
734 | if (strcmp(event->name, name) == 0) | |
735 | return event; | |
736 | } | |
737 | ||
738 | return NULL; | |
739 | } | |
740 | ||
741 | static struct trace_event_fields synth_event_fields_array[] = { | |
742 | { .type = TRACE_FUNCTION_TYPE, | |
743 | .define_fields = synth_event_define_fields }, | |
744 | {} | |
745 | }; | |
746 | ||
747 | static int register_synth_event(struct synth_event *event) | |
748 | { | |
749 | struct trace_event_call *call = &event->call; | |
750 | int ret = 0; | |
751 | ||
752 | event->call.class = &event->class; | |
753 | event->class.system = kstrdup(SYNTH_SYSTEM, GFP_KERNEL); | |
754 | if (!event->class.system) { | |
755 | ret = -ENOMEM; | |
756 | goto out; | |
757 | } | |
758 | ||
759 | event->tp = alloc_synth_tracepoint(event->name); | |
760 | if (IS_ERR(event->tp)) { | |
761 | ret = PTR_ERR(event->tp); | |
762 | event->tp = NULL; | |
763 | goto out; | |
764 | } | |
765 | ||
766 | INIT_LIST_HEAD(&call->class->fields); | |
767 | call->event.funcs = &synth_event_funcs; | |
768 | call->class->fields_array = synth_event_fields_array; | |
769 | ||
770 | ret = register_trace_event(&call->event); | |
771 | if (!ret) { | |
772 | ret = -ENODEV; | |
773 | goto out; | |
774 | } | |
775 | call->flags = TRACE_EVENT_FL_TRACEPOINT; | |
776 | call->class->reg = trace_event_reg; | |
777 | call->class->probe = trace_event_raw_event_synth; | |
778 | call->data = event; | |
779 | call->tp = event->tp; | |
780 | ||
781 | ret = trace_add_event_call(call); | |
782 | if (ret) { | |
783 | pr_warn("Failed to register synthetic event: %s\n", | |
784 | trace_event_name(call)); | |
785 | goto err; | |
786 | } | |
787 | ||
788 | ret = set_synth_event_print_fmt(call); | |
789 | if (ret < 0) { | |
790 | trace_remove_event_call(call); | |
791 | goto err; | |
792 | } | |
793 | out: | |
794 | return ret; | |
795 | err: | |
796 | unregister_trace_event(&call->event); | |
797 | goto out; | |
798 | } | |
799 | ||
800 | static int unregister_synth_event(struct synth_event *event) | |
801 | { | |
802 | struct trace_event_call *call = &event->call; | |
803 | int ret; | |
804 | ||
805 | ret = trace_remove_event_call(call); | |
806 | ||
807 | return ret; | |
808 | } | |
809 | ||
810 | static void free_synth_event(struct synth_event *event) | |
811 | { | |
812 | unsigned int i; | |
813 | ||
814 | if (!event) | |
815 | return; | |
816 | ||
817 | for (i = 0; i < event->n_fields; i++) | |
818 | free_synth_field(event->fields[i]); | |
819 | ||
820 | kfree(event->fields); | |
bd82631d | 821 | kfree(event->dynamic_fields); |
726721a5 TZ |
822 | kfree(event->name); |
823 | kfree(event->class.system); | |
824 | free_synth_tracepoint(event->tp); | |
825 | free_synth_event_print_fmt(&event->call); | |
826 | kfree(event); | |
827 | } | |
828 | ||
829 | static struct synth_event *alloc_synth_event(const char *name, int n_fields, | |
830 | struct synth_field **fields) | |
831 | { | |
bd82631d | 832 | unsigned int i, j, n_dynamic_fields = 0; |
726721a5 | 833 | struct synth_event *event; |
726721a5 TZ |
834 | |
835 | event = kzalloc(sizeof(*event), GFP_KERNEL); | |
836 | if (!event) { | |
837 | event = ERR_PTR(-ENOMEM); | |
838 | goto out; | |
839 | } | |
840 | ||
841 | event->name = kstrdup(name, GFP_KERNEL); | |
842 | if (!event->name) { | |
843 | kfree(event); | |
844 | event = ERR_PTR(-ENOMEM); | |
845 | goto out; | |
846 | } | |
847 | ||
848 | event->fields = kcalloc(n_fields, sizeof(*event->fields), GFP_KERNEL); | |
849 | if (!event->fields) { | |
850 | free_synth_event(event); | |
851 | event = ERR_PTR(-ENOMEM); | |
852 | goto out; | |
853 | } | |
854 | ||
bd82631d TZ |
855 | for (i = 0; i < n_fields; i++) |
856 | if (fields[i]->is_dynamic) | |
857 | n_dynamic_fields++; | |
858 | ||
859 | if (n_dynamic_fields) { | |
860 | event->dynamic_fields = kcalloc(n_dynamic_fields, | |
861 | sizeof(*event->dynamic_fields), | |
862 | GFP_KERNEL); | |
863 | if (!event->dynamic_fields) { | |
864 | free_synth_event(event); | |
865 | event = ERR_PTR(-ENOMEM); | |
866 | goto out; | |
867 | } | |
868 | } | |
869 | ||
726721a5 TZ |
870 | dyn_event_init(&event->devent, &synth_event_ops); |
871 | ||
bd82631d | 872 | for (i = 0, j = 0; i < n_fields; i++) { |
726721a5 TZ |
873 | event->fields[i] = fields[i]; |
874 | ||
bd82631d TZ |
875 | if (fields[i]->is_dynamic) { |
876 | event->dynamic_fields[j] = fields[i]; | |
877 | event->dynamic_fields[j]->field_pos = i; | |
878 | event->dynamic_fields[j++] = fields[i]; | |
879 | event->n_dynamic_fields++; | |
880 | } | |
881 | } | |
726721a5 TZ |
882 | event->n_fields = n_fields; |
883 | out: | |
884 | return event; | |
885 | } | |
886 | ||
887 | static int synth_event_check_arg_fn(void *data) | |
888 | { | |
889 | struct dynevent_arg_pair *arg_pair = data; | |
890 | int size; | |
891 | ||
892 | size = synth_field_size((char *)arg_pair->lhs); | |
bd82631d TZ |
893 | if (size == 0) { |
894 | if (strstr((char *)arg_pair->lhs, "[")) | |
895 | return 0; | |
896 | } | |
726721a5 TZ |
897 | |
898 | return size ? 0 : -EINVAL; | |
899 | } | |
900 | ||
901 | /** | |
902 | * synth_event_add_field - Add a new field to a synthetic event cmd | |
903 | * @cmd: A pointer to the dynevent_cmd struct representing the new event | |
904 | * @type: The type of the new field to add | |
905 | * @name: The name of the new field to add | |
906 | * | |
907 | * Add a new field to a synthetic event cmd object. Field ordering is in | |
908 | * the same order the fields are added. | |
909 | * | |
910 | * See synth_field_size() for available types. If field_name contains | |
911 | * [n] the field is considered to be an array. | |
912 | * | |
913 | * Return: 0 if successful, error otherwise. | |
914 | */ | |
915 | int synth_event_add_field(struct dynevent_cmd *cmd, const char *type, | |
916 | const char *name) | |
917 | { | |
918 | struct dynevent_arg_pair arg_pair; | |
919 | int ret; | |
920 | ||
921 | if (cmd->type != DYNEVENT_TYPE_SYNTH) | |
922 | return -EINVAL; | |
923 | ||
924 | if (!type || !name) | |
925 | return -EINVAL; | |
926 | ||
927 | dynevent_arg_pair_init(&arg_pair, 0, ';'); | |
928 | ||
929 | arg_pair.lhs = type; | |
930 | arg_pair.rhs = name; | |
931 | ||
932 | ret = dynevent_arg_pair_add(cmd, &arg_pair, synth_event_check_arg_fn); | |
933 | if (ret) | |
934 | return ret; | |
935 | ||
936 | if (++cmd->n_fields > SYNTH_FIELDS_MAX) | |
937 | ret = -EINVAL; | |
938 | ||
939 | return ret; | |
940 | } | |
941 | EXPORT_SYMBOL_GPL(synth_event_add_field); | |
942 | ||
943 | /** | |
944 | * synth_event_add_field_str - Add a new field to a synthetic event cmd | |
945 | * @cmd: A pointer to the dynevent_cmd struct representing the new event | |
946 | * @type_name: The type and name of the new field to add, as a single string | |
947 | * | |
948 | * Add a new field to a synthetic event cmd object, as a single | |
949 | * string. The @type_name string is expected to be of the form 'type | |
950 | * name', which will be appended by ';'. No sanity checking is done - | |
951 | * what's passed in is assumed to already be well-formed. Field | |
952 | * ordering is in the same order the fields are added. | |
953 | * | |
954 | * See synth_field_size() for available types. If field_name contains | |
955 | * [n] the field is considered to be an array. | |
956 | * | |
957 | * Return: 0 if successful, error otherwise. | |
958 | */ | |
959 | int synth_event_add_field_str(struct dynevent_cmd *cmd, const char *type_name) | |
960 | { | |
961 | struct dynevent_arg arg; | |
962 | int ret; | |
963 | ||
964 | if (cmd->type != DYNEVENT_TYPE_SYNTH) | |
965 | return -EINVAL; | |
966 | ||
967 | if (!type_name) | |
968 | return -EINVAL; | |
969 | ||
970 | dynevent_arg_init(&arg, ';'); | |
971 | ||
972 | arg.str = type_name; | |
973 | ||
974 | ret = dynevent_arg_add(cmd, &arg, NULL); | |
975 | if (ret) | |
976 | return ret; | |
977 | ||
978 | if (++cmd->n_fields > SYNTH_FIELDS_MAX) | |
979 | ret = -EINVAL; | |
980 | ||
981 | return ret; | |
982 | } | |
983 | EXPORT_SYMBOL_GPL(synth_event_add_field_str); | |
984 | ||
985 | /** | |
986 | * synth_event_add_fields - Add multiple fields to a synthetic event cmd | |
987 | * @cmd: A pointer to the dynevent_cmd struct representing the new event | |
988 | * @fields: An array of type/name field descriptions | |
989 | * @n_fields: The number of field descriptions contained in the fields array | |
990 | * | |
991 | * Add a new set of fields to a synthetic event cmd object. The event | |
992 | * fields that will be defined for the event should be passed in as an | |
993 | * array of struct synth_field_desc, and the number of elements in the | |
994 | * array passed in as n_fields. Field ordering will retain the | |
995 | * ordering given in the fields array. | |
996 | * | |
997 | * See synth_field_size() for available types. If field_name contains | |
998 | * [n] the field is considered to be an array. | |
999 | * | |
1000 | * Return: 0 if successful, error otherwise. | |
1001 | */ | |
1002 | int synth_event_add_fields(struct dynevent_cmd *cmd, | |
1003 | struct synth_field_desc *fields, | |
1004 | unsigned int n_fields) | |
1005 | { | |
1006 | unsigned int i; | |
1007 | int ret = 0; | |
1008 | ||
1009 | for (i = 0; i < n_fields; i++) { | |
1010 | if (fields[i].type == NULL || fields[i].name == NULL) { | |
1011 | ret = -EINVAL; | |
1012 | break; | |
1013 | } | |
1014 | ||
1015 | ret = synth_event_add_field(cmd, fields[i].type, fields[i].name); | |
1016 | if (ret) | |
1017 | break; | |
1018 | } | |
1019 | ||
1020 | return ret; | |
1021 | } | |
1022 | EXPORT_SYMBOL_GPL(synth_event_add_fields); | |
1023 | ||
1024 | /** | |
1025 | * __synth_event_gen_cmd_start - Start a synthetic event command from arg list | |
1026 | * @cmd: A pointer to the dynevent_cmd struct representing the new event | |
1027 | * @name: The name of the synthetic event | |
1028 | * @mod: The module creating the event, NULL if not created from a module | |
1029 | * @args: Variable number of arg (pairs), one pair for each field | |
1030 | * | |
1031 | * NOTE: Users normally won't want to call this function directly, but | |
1032 | * rather use the synth_event_gen_cmd_start() wrapper, which | |
1033 | * automatically adds a NULL to the end of the arg list. If this | |
1034 | * function is used directly, make sure the last arg in the variable | |
1035 | * arg list is NULL. | |
1036 | * | |
1037 | * Generate a synthetic event command to be executed by | |
1038 | * synth_event_gen_cmd_end(). This function can be used to generate | |
1039 | * the complete command or only the first part of it; in the latter | |
1040 | * case, synth_event_add_field(), synth_event_add_field_str(), or | |
1041 | * synth_event_add_fields() can be used to add more fields following | |
1042 | * this. | |
1043 | * | |
1044 | * There should be an even number variable args, each pair consisting | |
1045 | * of a type followed by a field name. | |
1046 | * | |
1047 | * See synth_field_size() for available types. If field_name contains | |
1048 | * [n] the field is considered to be an array. | |
1049 | * | |
1050 | * Return: 0 if successful, error otherwise. | |
1051 | */ | |
1052 | int __synth_event_gen_cmd_start(struct dynevent_cmd *cmd, const char *name, | |
1053 | struct module *mod, ...) | |
1054 | { | |
1055 | struct dynevent_arg arg; | |
1056 | va_list args; | |
1057 | int ret; | |
1058 | ||
1059 | cmd->event_name = name; | |
1060 | cmd->private_data = mod; | |
1061 | ||
1062 | if (cmd->type != DYNEVENT_TYPE_SYNTH) | |
1063 | return -EINVAL; | |
1064 | ||
1065 | dynevent_arg_init(&arg, 0); | |
1066 | arg.str = name; | |
1067 | ret = dynevent_arg_add(cmd, &arg, NULL); | |
1068 | if (ret) | |
1069 | return ret; | |
1070 | ||
1071 | va_start(args, mod); | |
1072 | for (;;) { | |
1073 | const char *type, *name; | |
1074 | ||
1075 | type = va_arg(args, const char *); | |
1076 | if (!type) | |
1077 | break; | |
1078 | name = va_arg(args, const char *); | |
1079 | if (!name) | |
1080 | break; | |
1081 | ||
1082 | if (++cmd->n_fields > SYNTH_FIELDS_MAX) { | |
1083 | ret = -EINVAL; | |
1084 | break; | |
1085 | } | |
1086 | ||
1087 | ret = synth_event_add_field(cmd, type, name); | |
1088 | if (ret) | |
1089 | break; | |
1090 | } | |
1091 | va_end(args); | |
1092 | ||
1093 | return ret; | |
1094 | } | |
1095 | EXPORT_SYMBOL_GPL(__synth_event_gen_cmd_start); | |
1096 | ||
1097 | /** | |
1098 | * synth_event_gen_cmd_array_start - Start synthetic event command from an array | |
1099 | * @cmd: A pointer to the dynevent_cmd struct representing the new event | |
1100 | * @name: The name of the synthetic event | |
1101 | * @fields: An array of type/name field descriptions | |
1102 | * @n_fields: The number of field descriptions contained in the fields array | |
1103 | * | |
1104 | * Generate a synthetic event command to be executed by | |
1105 | * synth_event_gen_cmd_end(). This function can be used to generate | |
1106 | * the complete command or only the first part of it; in the latter | |
1107 | * case, synth_event_add_field(), synth_event_add_field_str(), or | |
1108 | * synth_event_add_fields() can be used to add more fields following | |
1109 | * this. | |
1110 | * | |
1111 | * The event fields that will be defined for the event should be | |
1112 | * passed in as an array of struct synth_field_desc, and the number of | |
1113 | * elements in the array passed in as n_fields. Field ordering will | |
1114 | * retain the ordering given in the fields array. | |
1115 | * | |
1116 | * See synth_field_size() for available types. If field_name contains | |
1117 | * [n] the field is considered to be an array. | |
1118 | * | |
1119 | * Return: 0 if successful, error otherwise. | |
1120 | */ | |
1121 | int synth_event_gen_cmd_array_start(struct dynevent_cmd *cmd, const char *name, | |
1122 | struct module *mod, | |
1123 | struct synth_field_desc *fields, | |
1124 | unsigned int n_fields) | |
1125 | { | |
1126 | struct dynevent_arg arg; | |
1127 | unsigned int i; | |
1128 | int ret = 0; | |
1129 | ||
1130 | cmd->event_name = name; | |
1131 | cmd->private_data = mod; | |
1132 | ||
1133 | if (cmd->type != DYNEVENT_TYPE_SYNTH) | |
1134 | return -EINVAL; | |
1135 | ||
1136 | if (n_fields > SYNTH_FIELDS_MAX) | |
1137 | return -EINVAL; | |
1138 | ||
1139 | dynevent_arg_init(&arg, 0); | |
1140 | arg.str = name; | |
1141 | ret = dynevent_arg_add(cmd, &arg, NULL); | |
1142 | if (ret) | |
1143 | return ret; | |
1144 | ||
1145 | for (i = 0; i < n_fields; i++) { | |
1146 | if (fields[i].type == NULL || fields[i].name == NULL) | |
1147 | return -EINVAL; | |
1148 | ||
1149 | ret = synth_event_add_field(cmd, fields[i].type, fields[i].name); | |
1150 | if (ret) | |
1151 | break; | |
1152 | } | |
1153 | ||
1154 | return ret; | |
1155 | } | |
1156 | EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start); | |
1157 | ||
d4d70463 TZ |
1158 | static int save_cmdstr(int argc, const char *name, const char **argv) |
1159 | { | |
1160 | struct seq_buf s; | |
1161 | char *buf; | |
1162 | int i; | |
1163 | ||
1164 | buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL); | |
1165 | if (!buf) | |
1166 | return -ENOMEM; | |
1167 | ||
1168 | seq_buf_init(&s, buf, MAX_DYNEVENT_CMD_LEN); | |
1169 | ||
1170 | seq_buf_puts(&s, name); | |
1171 | ||
1172 | for (i = 0; i < argc; i++) { | |
1173 | seq_buf_putc(&s, ' '); | |
1174 | seq_buf_puts(&s, argv[i]); | |
1175 | } | |
1176 | ||
1177 | if (!seq_buf_buffer_left(&s)) { | |
1178 | synth_err(SYNTH_ERR_CMD_TOO_LONG, 0); | |
1179 | kfree(buf); | |
1180 | return -EINVAL; | |
1181 | } | |
1182 | buf[s.len] = 0; | |
1183 | last_cmd_set(buf); | |
1184 | ||
1185 | kfree(buf); | |
1186 | return 0; | |
1187 | } | |
1188 | ||
726721a5 TZ |
1189 | static int __create_synth_event(int argc, const char *name, const char **argv) |
1190 | { | |
1191 | struct synth_field *field, *fields[SYNTH_FIELDS_MAX]; | |
1192 | struct synth_event *event = NULL; | |
1193 | int i, consumed = 0, n_fields = 0, ret = 0; | |
1194 | ||
d4d70463 TZ |
1195 | ret = save_cmdstr(argc, name, argv); |
1196 | if (ret) | |
1197 | return ret; | |
1198 | ||
726721a5 TZ |
1199 | /* |
1200 | * Argument syntax: | |
1201 | * - Add synthetic event: <event_name> field[;field] ... | |
1202 | * - Remove synthetic event: !<event_name> field[;field] ... | |
1203 | * where 'field' = type field_name | |
1204 | */ | |
1205 | ||
d4d70463 TZ |
1206 | if (name[0] == '\0' || argc < 1) { |
1207 | synth_err(SYNTH_ERR_CMD_INCOMPLETE, 0); | |
726721a5 | 1208 | return -EINVAL; |
d4d70463 | 1209 | } |
726721a5 TZ |
1210 | |
1211 | mutex_lock(&event_mutex); | |
1212 | ||
9bbb3329 | 1213 | if (!is_good_name(name)) { |
d4d70463 | 1214 | synth_err(SYNTH_ERR_BAD_NAME, errpos(name)); |
9bbb3329 TZ |
1215 | ret = -EINVAL; |
1216 | goto out; | |
1217 | } | |
1218 | ||
726721a5 TZ |
1219 | event = find_synth_event(name); |
1220 | if (event) { | |
d4d70463 | 1221 | synth_err(SYNTH_ERR_EVENT_EXISTS, errpos(name)); |
726721a5 TZ |
1222 | ret = -EEXIST; |
1223 | goto out; | |
1224 | } | |
1225 | ||
1226 | for (i = 0; i < argc - 1; i++) { | |
1227 | if (strcmp(argv[i], ";") == 0) | |
1228 | continue; | |
1229 | if (n_fields == SYNTH_FIELDS_MAX) { | |
d4d70463 | 1230 | synth_err(SYNTH_ERR_TOO_MANY_FIELDS, 0); |
726721a5 TZ |
1231 | ret = -EINVAL; |
1232 | goto err; | |
1233 | } | |
1234 | ||
1235 | field = parse_synth_field(argc - i, &argv[i], &consumed); | |
1236 | if (IS_ERR(field)) { | |
1237 | ret = PTR_ERR(field); | |
1238 | goto err; | |
1239 | } | |
1240 | fields[n_fields++] = field; | |
1241 | i += consumed - 1; | |
1242 | } | |
1243 | ||
1244 | if (i < argc && strcmp(argv[i], ";") != 0) { | |
d4d70463 | 1245 | synth_err(SYNTH_ERR_INVALID_FIELD, errpos(argv[i])); |
726721a5 TZ |
1246 | ret = -EINVAL; |
1247 | goto err; | |
1248 | } | |
1249 | ||
1250 | event = alloc_synth_event(name, n_fields, fields); | |
1251 | if (IS_ERR(event)) { | |
1252 | ret = PTR_ERR(event); | |
1253 | event = NULL; | |
1254 | goto err; | |
1255 | } | |
1256 | ret = register_synth_event(event); | |
1257 | if (!ret) | |
1258 | dyn_event_add(&event->devent); | |
1259 | else | |
1260 | free_synth_event(event); | |
1261 | out: | |
1262 | mutex_unlock(&event_mutex); | |
1263 | ||
1264 | return ret; | |
1265 | err: | |
1266 | for (i = 0; i < n_fields; i++) | |
1267 | free_synth_field(fields[i]); | |
1268 | ||
1269 | goto out; | |
1270 | } | |
1271 | ||
1272 | /** | |
1273 | * synth_event_create - Create a new synthetic event | |
1274 | * @name: The name of the new sythetic event | |
1275 | * @fields: An array of type/name field descriptions | |
1276 | * @n_fields: The number of field descriptions contained in the fields array | |
1277 | * @mod: The module creating the event, NULL if not created from a module | |
1278 | * | |
1279 | * Create a new synthetic event with the given name under the | |
1280 | * trace/events/synthetic/ directory. The event fields that will be | |
1281 | * defined for the event should be passed in as an array of struct | |
1282 | * synth_field_desc, and the number elements in the array passed in as | |
1283 | * n_fields. Field ordering will retain the ordering given in the | |
1284 | * fields array. | |
1285 | * | |
1286 | * If the new synthetic event is being created from a module, the mod | |
1287 | * param must be non-NULL. This will ensure that the trace buffer | |
1288 | * won't contain unreadable events. | |
1289 | * | |
1290 | * The new synth event should be deleted using synth_event_delete() | |
1291 | * function. The new synthetic event can be generated from modules or | |
1292 | * other kernel code using trace_synth_event() and related functions. | |
1293 | * | |
1294 | * Return: 0 if successful, error otherwise. | |
1295 | */ | |
1296 | int synth_event_create(const char *name, struct synth_field_desc *fields, | |
1297 | unsigned int n_fields, struct module *mod) | |
1298 | { | |
1299 | struct dynevent_cmd cmd; | |
1300 | char *buf; | |
1301 | int ret; | |
1302 | ||
1303 | buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL); | |
1304 | if (!buf) | |
1305 | return -ENOMEM; | |
1306 | ||
1307 | synth_event_cmd_init(&cmd, buf, MAX_DYNEVENT_CMD_LEN); | |
1308 | ||
1309 | ret = synth_event_gen_cmd_array_start(&cmd, name, mod, | |
1310 | fields, n_fields); | |
1311 | if (ret) | |
1312 | goto out; | |
1313 | ||
1314 | ret = synth_event_gen_cmd_end(&cmd); | |
1315 | out: | |
1316 | kfree(buf); | |
1317 | ||
1318 | return ret; | |
1319 | } | |
1320 | EXPORT_SYMBOL_GPL(synth_event_create); | |
1321 | ||
1322 | static int destroy_synth_event(struct synth_event *se) | |
1323 | { | |
1324 | int ret; | |
1325 | ||
1326 | if (se->ref) | |
1327 | ret = -EBUSY; | |
1328 | else { | |
1329 | ret = unregister_synth_event(se); | |
1330 | if (!ret) { | |
1331 | dyn_event_remove(&se->devent); | |
1332 | free_synth_event(se); | |
1333 | } | |
1334 | } | |
1335 | ||
1336 | return ret; | |
1337 | } | |
1338 | ||
1339 | /** | |
1340 | * synth_event_delete - Delete a synthetic event | |
1341 | * @event_name: The name of the new sythetic event | |
1342 | * | |
1343 | * Delete a synthetic event that was created with synth_event_create(). | |
1344 | * | |
1345 | * Return: 0 if successful, error otherwise. | |
1346 | */ | |
1347 | int synth_event_delete(const char *event_name) | |
1348 | { | |
1349 | struct synth_event *se = NULL; | |
1350 | struct module *mod = NULL; | |
1351 | int ret = -ENOENT; | |
1352 | ||
1353 | mutex_lock(&event_mutex); | |
1354 | se = find_synth_event(event_name); | |
1355 | if (se) { | |
1356 | mod = se->mod; | |
1357 | ret = destroy_synth_event(se); | |
1358 | } | |
1359 | mutex_unlock(&event_mutex); | |
1360 | ||
1361 | if (mod) { | |
1362 | mutex_lock(&trace_types_lock); | |
1363 | /* | |
1364 | * It is safest to reset the ring buffer if the module | |
1365 | * being unloaded registered any events that were | |
1366 | * used. The only worry is if a new module gets | |
1367 | * loaded, and takes on the same id as the events of | |
1368 | * this module. When printing out the buffer, traced | |
1369 | * events left over from this module may be passed to | |
1370 | * the new module events and unexpected results may | |
1371 | * occur. | |
1372 | */ | |
1373 | tracing_reset_all_online_cpus(); | |
1374 | mutex_unlock(&trace_types_lock); | |
1375 | } | |
1376 | ||
1377 | return ret; | |
1378 | } | |
1379 | EXPORT_SYMBOL_GPL(synth_event_delete); | |
1380 | ||
1381 | static int create_or_delete_synth_event(int argc, char **argv) | |
1382 | { | |
1383 | const char *name = argv[0]; | |
1384 | int ret; | |
1385 | ||
1386 | /* trace_run_command() ensures argc != 0 */ | |
1387 | if (name[0] == '!') { | |
1388 | ret = synth_event_delete(name + 1); | |
1389 | return ret; | |
1390 | } | |
1391 | ||
1392 | ret = __create_synth_event(argc - 1, name, (const char **)argv + 1); | |
1393 | return ret == -ECANCELED ? -EINVAL : ret; | |
1394 | } | |
1395 | ||
1396 | static int synth_event_run_command(struct dynevent_cmd *cmd) | |
1397 | { | |
1398 | struct synth_event *se; | |
1399 | int ret; | |
1400 | ||
1401 | ret = trace_run_command(cmd->seq.buffer, create_or_delete_synth_event); | |
1402 | if (ret) | |
1403 | return ret; | |
1404 | ||
1405 | se = find_synth_event(cmd->event_name); | |
1406 | if (WARN_ON(!se)) | |
1407 | return -ENOENT; | |
1408 | ||
1409 | se->mod = cmd->private_data; | |
1410 | ||
1411 | return ret; | |
1412 | } | |
1413 | ||
1414 | /** | |
1415 | * synth_event_cmd_init - Initialize a synthetic event command object | |
1416 | * @cmd: A pointer to the dynevent_cmd struct representing the new event | |
1417 | * @buf: A pointer to the buffer used to build the command | |
1418 | * @maxlen: The length of the buffer passed in @buf | |
1419 | * | |
1420 | * Initialize a synthetic event command object. Use this before | |
1421 | * calling any of the other dyenvent_cmd functions. | |
1422 | */ | |
1423 | void synth_event_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen) | |
1424 | { | |
1425 | dynevent_cmd_init(cmd, buf, maxlen, DYNEVENT_TYPE_SYNTH, | |
1426 | synth_event_run_command); | |
1427 | } | |
1428 | EXPORT_SYMBOL_GPL(synth_event_cmd_init); | |
1429 | ||
1430 | static inline int | |
bd82631d TZ |
1431 | __synth_event_trace_init(struct trace_event_file *file, |
1432 | struct synth_event_trace_state *trace_state) | |
726721a5 | 1433 | { |
726721a5 TZ |
1434 | int ret = 0; |
1435 | ||
1436 | memset(trace_state, '\0', sizeof(*trace_state)); | |
1437 | ||
1438 | /* | |
1439 | * Normal event tracing doesn't get called at all unless the | |
1440 | * ENABLED bit is set (which attaches the probe thus allowing | |
1441 | * this code to be called, etc). Because this is called | |
1442 | * directly by the user, we don't have that but we still need | |
5c8c206e | 1443 | * to honor not logging when disabled. For the iterated |
726721a5 TZ |
1444 | * trace case, we save the enabed state upon start and just |
1445 | * ignore the following data calls. | |
1446 | */ | |
1447 | if (!(file->flags & EVENT_FILE_FL_ENABLED) || | |
1448 | trace_trigger_soft_disabled(file)) { | |
1449 | trace_state->disabled = true; | |
1450 | ret = -ENOENT; | |
1451 | goto out; | |
1452 | } | |
1453 | ||
1454 | trace_state->event = file->event_call->data; | |
bd82631d TZ |
1455 | out: |
1456 | return ret; | |
1457 | } | |
1458 | ||
1459 | static inline int | |
1460 | __synth_event_trace_start(struct trace_event_file *file, | |
1461 | struct synth_event_trace_state *trace_state, | |
1462 | int dynamic_fields_size) | |
1463 | { | |
1464 | int entry_size, fields_size = 0; | |
1465 | int ret = 0; | |
726721a5 TZ |
1466 | |
1467 | fields_size = trace_state->event->n_u64 * sizeof(u64); | |
bd82631d | 1468 | fields_size += dynamic_fields_size; |
726721a5 TZ |
1469 | |
1470 | /* | |
1471 | * Avoid ring buffer recursion detection, as this event | |
1472 | * is being performed within another event. | |
1473 | */ | |
1474 | trace_state->buffer = file->tr->array_buffer.buffer; | |
1475 | ring_buffer_nest_start(trace_state->buffer); | |
1476 | ||
1477 | entry_size = sizeof(*trace_state->entry) + fields_size; | |
1478 | trace_state->entry = trace_event_buffer_reserve(&trace_state->fbuffer, | |
1479 | file, | |
1480 | entry_size); | |
1481 | if (!trace_state->entry) { | |
1482 | ring_buffer_nest_end(trace_state->buffer); | |
1483 | ret = -EINVAL; | |
1484 | } | |
bd82631d | 1485 | |
726721a5 TZ |
1486 | return ret; |
1487 | } | |
1488 | ||
1489 | static inline void | |
1490 | __synth_event_trace_end(struct synth_event_trace_state *trace_state) | |
1491 | { | |
1492 | trace_event_buffer_commit(&trace_state->fbuffer); | |
1493 | ||
1494 | ring_buffer_nest_end(trace_state->buffer); | |
1495 | } | |
1496 | ||
1497 | /** | |
1498 | * synth_event_trace - Trace a synthetic event | |
1499 | * @file: The trace_event_file representing the synthetic event | |
1500 | * @n_vals: The number of values in vals | |
1501 | * @args: Variable number of args containing the event values | |
1502 | * | |
1503 | * Trace a synthetic event using the values passed in the variable | |
1504 | * argument list. | |
1505 | * | |
1506 | * The argument list should be a list 'n_vals' u64 values. The number | |
1507 | * of vals must match the number of field in the synthetic event, and | |
1508 | * must be in the same order as the synthetic event fields. | |
1509 | * | |
1510 | * All vals should be cast to u64, and string vals are just pointers | |
1511 | * to strings, cast to u64. Strings will be copied into space | |
1512 | * reserved in the event for the string, using these pointers. | |
1513 | * | |
1514 | * Return: 0 on success, err otherwise. | |
1515 | */ | |
1516 | int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...) | |
1517 | { | |
bd82631d | 1518 | unsigned int i, n_u64, len, data_size = 0; |
726721a5 | 1519 | struct synth_event_trace_state state; |
726721a5 TZ |
1520 | va_list args; |
1521 | int ret; | |
1522 | ||
bd82631d | 1523 | ret = __synth_event_trace_init(file, &state); |
726721a5 TZ |
1524 | if (ret) { |
1525 | if (ret == -ENOENT) | |
1526 | ret = 0; /* just disabled, not really an error */ | |
1527 | return ret; | |
1528 | } | |
1529 | ||
bd82631d TZ |
1530 | if (state.event->n_dynamic_fields) { |
1531 | va_start(args, n_vals); | |
1532 | ||
1533 | for (i = 0; i < state.event->n_fields; i++) { | |
1534 | u64 val = va_arg(args, u64); | |
1535 | ||
1536 | if (state.event->fields[i]->is_string && | |
1537 | state.event->fields[i]->is_dynamic) { | |
1538 | char *str_val = (char *)(long)val; | |
1539 | ||
1540 | data_size += strlen(str_val) + 1; | |
1541 | } | |
1542 | } | |
1543 | ||
1544 | va_end(args); | |
1545 | } | |
1546 | ||
1547 | ret = __synth_event_trace_start(file, &state, data_size); | |
1548 | if (ret) | |
1549 | return ret; | |
1550 | ||
726721a5 TZ |
1551 | if (n_vals != state.event->n_fields) { |
1552 | ret = -EINVAL; | |
1553 | goto out; | |
1554 | } | |
1555 | ||
bd82631d TZ |
1556 | data_size = 0; |
1557 | ||
726721a5 TZ |
1558 | va_start(args, n_vals); |
1559 | for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) { | |
1560 | u64 val; | |
1561 | ||
1562 | val = va_arg(args, u64); | |
1563 | ||
1564 | if (state.event->fields[i]->is_string) { | |
1565 | char *str_val = (char *)(long)val; | |
726721a5 | 1566 | |
bd82631d TZ |
1567 | len = trace_string(state.entry, state.event, str_val, |
1568 | state.event->fields[i]->is_dynamic, | |
1569 | data_size, &n_u64); | |
1570 | data_size += len; /* only dynamic string increments */ | |
726721a5 TZ |
1571 | } else { |
1572 | struct synth_field *field = state.event->fields[i]; | |
1573 | ||
1574 | switch (field->size) { | |
1575 | case 1: | |
1576 | *(u8 *)&state.entry->fields[n_u64] = (u8)val; | |
1577 | break; | |
1578 | ||
1579 | case 2: | |
1580 | *(u16 *)&state.entry->fields[n_u64] = (u16)val; | |
1581 | break; | |
1582 | ||
1583 | case 4: | |
1584 | *(u32 *)&state.entry->fields[n_u64] = (u32)val; | |
1585 | break; | |
1586 | ||
1587 | default: | |
1588 | state.entry->fields[n_u64] = val; | |
1589 | break; | |
1590 | } | |
1591 | n_u64++; | |
1592 | } | |
1593 | } | |
1594 | va_end(args); | |
1595 | out: | |
1596 | __synth_event_trace_end(&state); | |
1597 | ||
1598 | return ret; | |
1599 | } | |
1600 | EXPORT_SYMBOL_GPL(synth_event_trace); | |
1601 | ||
1602 | /** | |
1603 | * synth_event_trace_array - Trace a synthetic event from an array | |
1604 | * @file: The trace_event_file representing the synthetic event | |
1605 | * @vals: Array of values | |
1606 | * @n_vals: The number of values in vals | |
1607 | * | |
1608 | * Trace a synthetic event using the values passed in as 'vals'. | |
1609 | * | |
1610 | * The 'vals' array is just an array of 'n_vals' u64. The number of | |
1611 | * vals must match the number of field in the synthetic event, and | |
1612 | * must be in the same order as the synthetic event fields. | |
1613 | * | |
1614 | * All vals should be cast to u64, and string vals are just pointers | |
1615 | * to strings, cast to u64. Strings will be copied into space | |
1616 | * reserved in the event for the string, using these pointers. | |
1617 | * | |
1618 | * Return: 0 on success, err otherwise. | |
1619 | */ | |
1620 | int synth_event_trace_array(struct trace_event_file *file, u64 *vals, | |
1621 | unsigned int n_vals) | |
1622 | { | |
bd82631d | 1623 | unsigned int i, n_u64, field_pos, len, data_size = 0; |
726721a5 | 1624 | struct synth_event_trace_state state; |
bd82631d | 1625 | char *str_val; |
726721a5 TZ |
1626 | int ret; |
1627 | ||
bd82631d | 1628 | ret = __synth_event_trace_init(file, &state); |
726721a5 TZ |
1629 | if (ret) { |
1630 | if (ret == -ENOENT) | |
1631 | ret = 0; /* just disabled, not really an error */ | |
1632 | return ret; | |
1633 | } | |
1634 | ||
bd82631d TZ |
1635 | if (state.event->n_dynamic_fields) { |
1636 | for (i = 0; i < state.event->n_dynamic_fields; i++) { | |
1637 | field_pos = state.event->dynamic_fields[i]->field_pos; | |
1638 | str_val = (char *)(long)vals[field_pos]; | |
1639 | len = strlen(str_val) + 1; | |
1640 | data_size += len; | |
1641 | } | |
1642 | } | |
1643 | ||
1644 | ret = __synth_event_trace_start(file, &state, data_size); | |
1645 | if (ret) | |
1646 | return ret; | |
1647 | ||
726721a5 TZ |
1648 | if (n_vals != state.event->n_fields) { |
1649 | ret = -EINVAL; | |
1650 | goto out; | |
1651 | } | |
1652 | ||
bd82631d TZ |
1653 | data_size = 0; |
1654 | ||
726721a5 TZ |
1655 | for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) { |
1656 | if (state.event->fields[i]->is_string) { | |
1657 | char *str_val = (char *)(long)vals[i]; | |
726721a5 | 1658 | |
bd82631d TZ |
1659 | len = trace_string(state.entry, state.event, str_val, |
1660 | state.event->fields[i]->is_dynamic, | |
1661 | data_size, &n_u64); | |
1662 | data_size += len; /* only dynamic string increments */ | |
726721a5 TZ |
1663 | } else { |
1664 | struct synth_field *field = state.event->fields[i]; | |
1665 | u64 val = vals[i]; | |
1666 | ||
1667 | switch (field->size) { | |
1668 | case 1: | |
1669 | *(u8 *)&state.entry->fields[n_u64] = (u8)val; | |
1670 | break; | |
1671 | ||
1672 | case 2: | |
1673 | *(u16 *)&state.entry->fields[n_u64] = (u16)val; | |
1674 | break; | |
1675 | ||
1676 | case 4: | |
1677 | *(u32 *)&state.entry->fields[n_u64] = (u32)val; | |
1678 | break; | |
1679 | ||
1680 | default: | |
1681 | state.entry->fields[n_u64] = val; | |
1682 | break; | |
1683 | } | |
1684 | n_u64++; | |
1685 | } | |
1686 | } | |
1687 | out: | |
1688 | __synth_event_trace_end(&state); | |
1689 | ||
1690 | return ret; | |
1691 | } | |
1692 | EXPORT_SYMBOL_GPL(synth_event_trace_array); | |
1693 | ||
1694 | /** | |
1695 | * synth_event_trace_start - Start piecewise synthetic event trace | |
1696 | * @file: The trace_event_file representing the synthetic event | |
1697 | * @trace_state: A pointer to object tracking the piecewise trace state | |
1698 | * | |
1699 | * Start the trace of a synthetic event field-by-field rather than all | |
1700 | * at once. | |
1701 | * | |
1702 | * This function 'opens' an event trace, which means space is reserved | |
1703 | * for the event in the trace buffer, after which the event's | |
1704 | * individual field values can be set through either | |
1705 | * synth_event_add_next_val() or synth_event_add_val(). | |
1706 | * | |
1707 | * A pointer to a trace_state object is passed in, which will keep | |
1708 | * track of the current event trace state until the event trace is | |
1709 | * closed (and the event finally traced) using | |
1710 | * synth_event_trace_end(). | |
1711 | * | |
1712 | * Note that synth_event_trace_end() must be called after all values | |
1713 | * have been added for each event trace, regardless of whether adding | |
1714 | * all field values succeeded or not. | |
1715 | * | |
1716 | * Note also that for a given event trace, all fields must be added | |
1717 | * using either synth_event_add_next_val() or synth_event_add_val() | |
1718 | * but not both together or interleaved. | |
1719 | * | |
1720 | * Return: 0 on success, err otherwise. | |
1721 | */ | |
1722 | int synth_event_trace_start(struct trace_event_file *file, | |
1723 | struct synth_event_trace_state *trace_state) | |
1724 | { | |
1725 | int ret; | |
1726 | ||
1727 | if (!trace_state) | |
1728 | return -EINVAL; | |
1729 | ||
bd82631d TZ |
1730 | ret = __synth_event_trace_init(file, trace_state); |
1731 | if (ret) { | |
1732 | if (ret == -ENOENT) | |
1733 | ret = 0; /* just disabled, not really an error */ | |
1734 | return ret; | |
1735 | } | |
1736 | ||
1737 | if (trace_state->event->n_dynamic_fields) | |
1738 | return -ENOTSUPP; | |
1739 | ||
1740 | ret = __synth_event_trace_start(file, trace_state, 0); | |
726721a5 TZ |
1741 | |
1742 | return ret; | |
1743 | } | |
1744 | EXPORT_SYMBOL_GPL(synth_event_trace_start); | |
1745 | ||
1746 | static int __synth_event_add_val(const char *field_name, u64 val, | |
1747 | struct synth_event_trace_state *trace_state) | |
1748 | { | |
1749 | struct synth_field *field = NULL; | |
1750 | struct synth_trace_event *entry; | |
1751 | struct synth_event *event; | |
1752 | int i, ret = 0; | |
1753 | ||
1754 | if (!trace_state) { | |
1755 | ret = -EINVAL; | |
1756 | goto out; | |
1757 | } | |
1758 | ||
1759 | /* can't mix add_next_synth_val() with add_synth_val() */ | |
1760 | if (field_name) { | |
1761 | if (trace_state->add_next) { | |
1762 | ret = -EINVAL; | |
1763 | goto out; | |
1764 | } | |
1765 | trace_state->add_name = true; | |
1766 | } else { | |
1767 | if (trace_state->add_name) { | |
1768 | ret = -EINVAL; | |
1769 | goto out; | |
1770 | } | |
1771 | trace_state->add_next = true; | |
1772 | } | |
1773 | ||
1774 | if (trace_state->disabled) | |
1775 | goto out; | |
1776 | ||
1777 | event = trace_state->event; | |
1778 | if (trace_state->add_name) { | |
1779 | for (i = 0; i < event->n_fields; i++) { | |
1780 | field = event->fields[i]; | |
1781 | if (strcmp(field->name, field_name) == 0) | |
1782 | break; | |
1783 | } | |
1784 | if (!field) { | |
1785 | ret = -EINVAL; | |
1786 | goto out; | |
1787 | } | |
1788 | } else { | |
1789 | if (trace_state->cur_field >= event->n_fields) { | |
1790 | ret = -EINVAL; | |
1791 | goto out; | |
1792 | } | |
1793 | field = event->fields[trace_state->cur_field++]; | |
1794 | } | |
1795 | ||
1796 | entry = trace_state->entry; | |
1797 | if (field->is_string) { | |
1798 | char *str_val = (char *)(long)val; | |
1799 | char *str_field; | |
1800 | ||
bd82631d TZ |
1801 | if (field->is_dynamic) { /* add_val can't do dynamic strings */ |
1802 | ret = -EINVAL; | |
1803 | goto out; | |
1804 | } | |
1805 | ||
726721a5 TZ |
1806 | if (!str_val) { |
1807 | ret = -EINVAL; | |
1808 | goto out; | |
1809 | } | |
1810 | ||
1811 | str_field = (char *)&entry->fields[field->offset]; | |
1812 | strscpy(str_field, str_val, STR_VAR_LEN_MAX); | |
1813 | } else { | |
1814 | switch (field->size) { | |
1815 | case 1: | |
1816 | *(u8 *)&trace_state->entry->fields[field->offset] = (u8)val; | |
1817 | break; | |
1818 | ||
1819 | case 2: | |
1820 | *(u16 *)&trace_state->entry->fields[field->offset] = (u16)val; | |
1821 | break; | |
1822 | ||
1823 | case 4: | |
1824 | *(u32 *)&trace_state->entry->fields[field->offset] = (u32)val; | |
1825 | break; | |
1826 | ||
1827 | default: | |
1828 | trace_state->entry->fields[field->offset] = val; | |
1829 | break; | |
1830 | } | |
1831 | } | |
1832 | out: | |
1833 | return ret; | |
1834 | } | |
1835 | ||
1836 | /** | |
1837 | * synth_event_add_next_val - Add the next field's value to an open synth trace | |
1838 | * @val: The value to set the next field to | |
1839 | * @trace_state: A pointer to object tracking the piecewise trace state | |
1840 | * | |
1841 | * Set the value of the next field in an event that's been opened by | |
1842 | * synth_event_trace_start(). | |
1843 | * | |
1844 | * The val param should be the value cast to u64. If the value points | |
1845 | * to a string, the val param should be a char * cast to u64. | |
1846 | * | |
1847 | * This function assumes all the fields in an event are to be set one | |
1848 | * after another - successive calls to this function are made, one for | |
1849 | * each field, in the order of the fields in the event, until all | |
1850 | * fields have been set. If you'd rather set each field individually | |
1851 | * without regard to ordering, synth_event_add_val() can be used | |
1852 | * instead. | |
1853 | * | |
1854 | * Note however that synth_event_add_next_val() and | |
1855 | * synth_event_add_val() can't be intermixed for a given event trace - | |
1856 | * one or the other but not both can be used at the same time. | |
1857 | * | |
1858 | * Note also that synth_event_trace_end() must be called after all | |
1859 | * values have been added for each event trace, regardless of whether | |
1860 | * adding all field values succeeded or not. | |
1861 | * | |
1862 | * Return: 0 on success, err otherwise. | |
1863 | */ | |
1864 | int synth_event_add_next_val(u64 val, | |
1865 | struct synth_event_trace_state *trace_state) | |
1866 | { | |
1867 | return __synth_event_add_val(NULL, val, trace_state); | |
1868 | } | |
1869 | EXPORT_SYMBOL_GPL(synth_event_add_next_val); | |
1870 | ||
1871 | /** | |
1872 | * synth_event_add_val - Add a named field's value to an open synth trace | |
1873 | * @field_name: The name of the synthetic event field value to set | |
1874 | * @val: The value to set the next field to | |
1875 | * @trace_state: A pointer to object tracking the piecewise trace state | |
1876 | * | |
1877 | * Set the value of the named field in an event that's been opened by | |
1878 | * synth_event_trace_start(). | |
1879 | * | |
1880 | * The val param should be the value cast to u64. If the value points | |
1881 | * to a string, the val param should be a char * cast to u64. | |
1882 | * | |
1883 | * This function looks up the field name, and if found, sets the field | |
1884 | * to the specified value. This lookup makes this function more | |
1885 | * expensive than synth_event_add_next_val(), so use that or the | |
1886 | * none-piecewise synth_event_trace() instead if efficiency is more | |
1887 | * important. | |
1888 | * | |
1889 | * Note however that synth_event_add_next_val() and | |
1890 | * synth_event_add_val() can't be intermixed for a given event trace - | |
1891 | * one or the other but not both can be used at the same time. | |
1892 | * | |
1893 | * Note also that synth_event_trace_end() must be called after all | |
1894 | * values have been added for each event trace, regardless of whether | |
1895 | * adding all field values succeeded or not. | |
1896 | * | |
1897 | * Return: 0 on success, err otherwise. | |
1898 | */ | |
1899 | int synth_event_add_val(const char *field_name, u64 val, | |
1900 | struct synth_event_trace_state *trace_state) | |
1901 | { | |
1902 | return __synth_event_add_val(field_name, val, trace_state); | |
1903 | } | |
1904 | EXPORT_SYMBOL_GPL(synth_event_add_val); | |
1905 | ||
1906 | /** | |
1907 | * synth_event_trace_end - End piecewise synthetic event trace | |
1908 | * @trace_state: A pointer to object tracking the piecewise trace state | |
1909 | * | |
1910 | * End the trace of a synthetic event opened by | |
1911 | * synth_event_trace__start(). | |
1912 | * | |
1913 | * This function 'closes' an event trace, which basically means that | |
1914 | * it commits the reserved event and cleans up other loose ends. | |
1915 | * | |
1916 | * A pointer to a trace_state object is passed in, which will keep | |
1917 | * track of the current event trace state opened with | |
1918 | * synth_event_trace_start(). | |
1919 | * | |
1920 | * Note that this function must be called after all values have been | |
1921 | * added for each event trace, regardless of whether adding all field | |
1922 | * values succeeded or not. | |
1923 | * | |
1924 | * Return: 0 on success, err otherwise. | |
1925 | */ | |
1926 | int synth_event_trace_end(struct synth_event_trace_state *trace_state) | |
1927 | { | |
1928 | if (!trace_state) | |
1929 | return -EINVAL; | |
1930 | ||
1931 | __synth_event_trace_end(trace_state); | |
1932 | ||
1933 | return 0; | |
1934 | } | |
1935 | EXPORT_SYMBOL_GPL(synth_event_trace_end); | |
1936 | ||
1937 | static int create_synth_event(int argc, const char **argv) | |
1938 | { | |
1939 | const char *name = argv[0]; | |
1940 | int len; | |
1941 | ||
1942 | if (name[0] != 's' || name[1] != ':') | |
1943 | return -ECANCELED; | |
1944 | name += 2; | |
1945 | ||
1946 | /* This interface accepts group name prefix */ | |
1947 | if (strchr(name, '/')) { | |
1948 | len = str_has_prefix(name, SYNTH_SYSTEM "/"); | |
1949 | if (len == 0) | |
1950 | return -EINVAL; | |
1951 | name += len; | |
1952 | } | |
1953 | return __create_synth_event(argc - 1, name, argv + 1); | |
1954 | } | |
1955 | ||
1956 | static int synth_event_release(struct dyn_event *ev) | |
1957 | { | |
1958 | struct synth_event *event = to_synth_event(ev); | |
1959 | int ret; | |
1960 | ||
1961 | if (event->ref) | |
1962 | return -EBUSY; | |
1963 | ||
1964 | ret = unregister_synth_event(event); | |
1965 | if (ret) | |
1966 | return ret; | |
1967 | ||
1968 | dyn_event_remove(ev); | |
1969 | free_synth_event(event); | |
1970 | return 0; | |
1971 | } | |
1972 | ||
1973 | static int __synth_event_show(struct seq_file *m, struct synth_event *event) | |
1974 | { | |
1975 | struct synth_field *field; | |
1976 | unsigned int i; | |
7d27adf5 | 1977 | char *type, *t; |
726721a5 TZ |
1978 | |
1979 | seq_printf(m, "%s\t", event->name); | |
1980 | ||
1981 | for (i = 0; i < event->n_fields; i++) { | |
1982 | field = event->fields[i]; | |
1983 | ||
7d27adf5 TZ |
1984 | type = field->type; |
1985 | t = strstr(type, "__data_loc"); | |
1986 | if (t) { /* __data_loc belongs in format but not event desc */ | |
1987 | t += sizeof("__data_loc"); | |
1988 | type = t; | |
1989 | } | |
1990 | ||
726721a5 | 1991 | /* parameter values */ |
7d27adf5 | 1992 | seq_printf(m, "%s %s%s", type, field->name, |
726721a5 TZ |
1993 | i == event->n_fields - 1 ? "" : "; "); |
1994 | } | |
1995 | ||
1996 | seq_putc(m, '\n'); | |
1997 | ||
1998 | return 0; | |
1999 | } | |
2000 | ||
2001 | static int synth_event_show(struct seq_file *m, struct dyn_event *ev) | |
2002 | { | |
2003 | struct synth_event *event = to_synth_event(ev); | |
2004 | ||
2005 | seq_printf(m, "s:%s/", event->class.system); | |
2006 | ||
2007 | return __synth_event_show(m, event); | |
2008 | } | |
2009 | ||
2010 | static int synth_events_seq_show(struct seq_file *m, void *v) | |
2011 | { | |
2012 | struct dyn_event *ev = v; | |
2013 | ||
2014 | if (!is_synth_event(ev)) | |
2015 | return 0; | |
2016 | ||
2017 | return __synth_event_show(m, to_synth_event(ev)); | |
2018 | } | |
2019 | ||
2020 | static const struct seq_operations synth_events_seq_op = { | |
2021 | .start = dyn_event_seq_start, | |
2022 | .next = dyn_event_seq_next, | |
2023 | .stop = dyn_event_seq_stop, | |
2024 | .show = synth_events_seq_show, | |
2025 | }; | |
2026 | ||
2027 | static int synth_events_open(struct inode *inode, struct file *file) | |
2028 | { | |
2029 | int ret; | |
2030 | ||
2031 | ret = security_locked_down(LOCKDOWN_TRACEFS); | |
2032 | if (ret) | |
2033 | return ret; | |
2034 | ||
2035 | if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { | |
2036 | ret = dyn_events_release_all(&synth_event_ops); | |
2037 | if (ret < 0) | |
2038 | return ret; | |
2039 | } | |
2040 | ||
2041 | return seq_open(file, &synth_events_seq_op); | |
2042 | } | |
2043 | ||
2044 | static ssize_t synth_events_write(struct file *file, | |
2045 | const char __user *buffer, | |
2046 | size_t count, loff_t *ppos) | |
2047 | { | |
2048 | return trace_parse_run_command(file, buffer, count, ppos, | |
2049 | create_or_delete_synth_event); | |
2050 | } | |
2051 | ||
2052 | static const struct file_operations synth_events_fops = { | |
2053 | .open = synth_events_open, | |
2054 | .write = synth_events_write, | |
2055 | .read = seq_read, | |
2056 | .llseek = seq_lseek, | |
2057 | .release = seq_release, | |
2058 | }; | |
2059 | ||
ba0fbfbb MH |
2060 | /* |
2061 | * Register dynevent at core_initcall. This allows kernel to setup kprobe | |
2062 | * events in postcore_initcall without tracefs. | |
2063 | */ | |
2064 | static __init int trace_events_synth_init_early(void) | |
726721a5 | 2065 | { |
726721a5 TZ |
2066 | int err = 0; |
2067 | ||
2068 | err = dyn_event_register(&synth_event_ops); | |
ba0fbfbb | 2069 | if (err) |
726721a5 | 2070 | pr_warn("Could not register synth_event_ops\n"); |
726721a5 | 2071 | |
ba0fbfbb MH |
2072 | return err; |
2073 | } | |
2074 | core_initcall(trace_events_synth_init_early); | |
2075 | ||
2076 | static __init int trace_events_synth_init(void) | |
2077 | { | |
2078 | struct dentry *entry = NULL; | |
2079 | int err = 0; | |
22c36b18 WY |
2080 | err = tracing_init_dentry(); |
2081 | if (err) | |
726721a5 | 2082 | goto err; |
726721a5 | 2083 | |
22c36b18 | 2084 | entry = tracefs_create_file("synthetic_events", 0644, NULL, |
726721a5 TZ |
2085 | NULL, &synth_events_fops); |
2086 | if (!entry) { | |
2087 | err = -ENODEV; | |
2088 | goto err; | |
2089 | } | |
2090 | ||
2091 | return err; | |
2092 | err: | |
2093 | pr_warn("Could not create tracefs 'synthetic_events' entry\n"); | |
2094 | ||
2095 | return err; | |
2096 | } | |
2097 | ||
2098 | fs_initcall(trace_events_synth_init); |