blob: 9ac6089b7513d2278d397aa758c9b8572c2135d2 [file] [log] [blame]
Tom Zanussi7ef224d2016-03-03 12:54:42 -06001/*
2 * trace_events_hist - trace event hist triggers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * Copyright (C) 2015 Tom Zanussi <tom.zanussi@linux.intel.com>
15 */
16
17#include <linux/module.h>
18#include <linux/kallsyms.h>
19#include <linux/mutex.h>
20#include <linux/slab.h>
21#include <linux/stacktrace.h>
Ingo Molnarb2d09102017-02-04 01:27:20 +010022#include <linux/rculist.h>
Tom Zanussi4b147932018-01-15 20:51:58 -060023#include <linux/tracefs.h>
Tom Zanussi7ef224d2016-03-03 12:54:42 -060024
25#include "tracing_map.h"
26#include "trace.h"
27
Tom Zanussi4b147932018-01-15 20:51:58 -060028#define SYNTH_SYSTEM "synthetic"
29#define SYNTH_FIELDS_MAX 16
30
31#define STR_VAR_LEN_MAX 32 /* must be multiple of sizeof(u64) */
32
Tom Zanussi7ef224d2016-03-03 12:54:42 -060033struct hist_field;
34
Tom Zanussidf35d932018-01-15 20:51:54 -060035typedef u64 (*hist_field_fn_t) (struct hist_field *field,
36 struct tracing_map_elt *elt,
37 struct ring_buffer_event *rbe,
38 void *event);
Tom Zanussi7ef224d2016-03-03 12:54:42 -060039
Tom Zanussi5819ead2017-09-22 14:58:23 -050040#define HIST_FIELD_OPERANDS_MAX 2
Tom Zanussi30350d62018-01-15 20:51:49 -060041#define HIST_FIELDS_MAX (TRACING_MAP_FIELDS_MAX + TRACING_MAP_VARS_MAX)
Tom Zanussi0212e2a2018-01-15 20:51:57 -060042#define HIST_ACTIONS_MAX 8
Tom Zanussi30350d62018-01-15 20:51:49 -060043
Tom Zanussi100719d2018-01-15 20:51:52 -060044enum field_op_id {
45 FIELD_OP_NONE,
46 FIELD_OP_PLUS,
47 FIELD_OP_MINUS,
48 FIELD_OP_UNARY_MINUS,
49};
50
Tom Zanussi30350d62018-01-15 20:51:49 -060051struct hist_var {
52 char *name;
53 struct hist_trigger_data *hist_data;
54 unsigned int idx;
55};
Tom Zanussi5819ead2017-09-22 14:58:23 -050056
Tom Zanussi7ef224d2016-03-03 12:54:42 -060057struct hist_field {
58 struct ftrace_event_field *field;
59 unsigned long flags;
60 hist_field_fn_t fn;
61 unsigned int size;
Tom Zanussi76a3b0c2016-03-03 12:54:44 -060062 unsigned int offset;
Tom Zanussi5819ead2017-09-22 14:58:23 -050063 unsigned int is_signed;
Tom Zanussi19a9fac2018-01-15 20:51:55 -060064 const char *type;
Tom Zanussi5819ead2017-09-22 14:58:23 -050065 struct hist_field *operands[HIST_FIELD_OPERANDS_MAX];
Tom Zanussib559d003a2018-01-15 20:51:47 -060066 struct hist_trigger_data *hist_data;
Tom Zanussi30350d62018-01-15 20:51:49 -060067 struct hist_var var;
Tom Zanussi100719d2018-01-15 20:51:52 -060068 enum field_op_id operator;
Tom Zanussi067fe032018-01-15 20:51:56 -060069 char *system;
70 char *event_name;
Tom Zanussi100719d2018-01-15 20:51:52 -060071 char *name;
Tom Zanussi067fe032018-01-15 20:51:56 -060072 unsigned int var_idx;
73 unsigned int var_ref_idx;
74 bool read_once;
Tom Zanussi7ef224d2016-03-03 12:54:42 -060075};
76
Tom Zanussidf35d932018-01-15 20:51:54 -060077static u64 hist_field_none(struct hist_field *field,
78 struct tracing_map_elt *elt,
79 struct ring_buffer_event *rbe,
80 void *event)
Tom Zanussi69a02002016-03-03 12:54:52 -060081{
82 return 0;
83}
84
Tom Zanussidf35d932018-01-15 20:51:54 -060085static u64 hist_field_counter(struct hist_field *field,
86 struct tracing_map_elt *elt,
87 struct ring_buffer_event *rbe,
88 void *event)
Tom Zanussi7ef224d2016-03-03 12:54:42 -060089{
90 return 1;
91}
92
Tom Zanussidf35d932018-01-15 20:51:54 -060093static u64 hist_field_string(struct hist_field *hist_field,
94 struct tracing_map_elt *elt,
95 struct ring_buffer_event *rbe,
96 void *event)
Tom Zanussi7ef224d2016-03-03 12:54:42 -060097{
98 char *addr = (char *)(event + hist_field->field->offset);
99
100 return (u64)(unsigned long)addr;
101}
102
Tom Zanussidf35d932018-01-15 20:51:54 -0600103static u64 hist_field_dynstring(struct hist_field *hist_field,
104 struct tracing_map_elt *elt,
105 struct ring_buffer_event *rbe,
106 void *event)
Namhyung Kim79e577c2016-03-03 12:54:53 -0600107{
108 u32 str_item = *(u32 *)(event + hist_field->field->offset);
109 int str_loc = str_item & 0xffff;
110 char *addr = (char *)(event + str_loc);
111
112 return (u64)(unsigned long)addr;
113}
114
Tom Zanussidf35d932018-01-15 20:51:54 -0600115static u64 hist_field_pstring(struct hist_field *hist_field,
116 struct tracing_map_elt *elt,
117 struct ring_buffer_event *rbe,
118 void *event)
Namhyung Kim79e577c2016-03-03 12:54:53 -0600119{
120 char **addr = (char **)(event + hist_field->field->offset);
121
122 return (u64)(unsigned long)*addr;
123}
124
Tom Zanussidf35d932018-01-15 20:51:54 -0600125static u64 hist_field_log2(struct hist_field *hist_field,
126 struct tracing_map_elt *elt,
127 struct ring_buffer_event *rbe,
128 void *event)
Namhyung Kim4b94f5b2016-03-03 12:55:02 -0600129{
Tom Zanussi5819ead2017-09-22 14:58:23 -0500130 struct hist_field *operand = hist_field->operands[0];
131
Tom Zanussidf35d932018-01-15 20:51:54 -0600132 u64 val = operand->fn(operand, elt, rbe, event);
Namhyung Kim4b94f5b2016-03-03 12:55:02 -0600133
134 return (u64) ilog2(roundup_pow_of_two(val));
135}
136
Tom Zanussidf35d932018-01-15 20:51:54 -0600137static u64 hist_field_plus(struct hist_field *hist_field,
138 struct tracing_map_elt *elt,
139 struct ring_buffer_event *rbe,
140 void *event)
Tom Zanussi100719d2018-01-15 20:51:52 -0600141{
142 struct hist_field *operand1 = hist_field->operands[0];
143 struct hist_field *operand2 = hist_field->operands[1];
144
Tom Zanussidf35d932018-01-15 20:51:54 -0600145 u64 val1 = operand1->fn(operand1, elt, rbe, event);
146 u64 val2 = operand2->fn(operand2, elt, rbe, event);
Tom Zanussi100719d2018-01-15 20:51:52 -0600147
148 return val1 + val2;
149}
150
Tom Zanussidf35d932018-01-15 20:51:54 -0600151static u64 hist_field_minus(struct hist_field *hist_field,
152 struct tracing_map_elt *elt,
153 struct ring_buffer_event *rbe,
154 void *event)
Tom Zanussi100719d2018-01-15 20:51:52 -0600155{
156 struct hist_field *operand1 = hist_field->operands[0];
157 struct hist_field *operand2 = hist_field->operands[1];
158
Tom Zanussidf35d932018-01-15 20:51:54 -0600159 u64 val1 = operand1->fn(operand1, elt, rbe, event);
160 u64 val2 = operand2->fn(operand2, elt, rbe, event);
Tom Zanussi100719d2018-01-15 20:51:52 -0600161
162 return val1 - val2;
163}
164
Tom Zanussidf35d932018-01-15 20:51:54 -0600165static u64 hist_field_unary_minus(struct hist_field *hist_field,
166 struct tracing_map_elt *elt,
167 struct ring_buffer_event *rbe,
168 void *event)
Tom Zanussi100719d2018-01-15 20:51:52 -0600169{
170 struct hist_field *operand = hist_field->operands[0];
171
Tom Zanussidf35d932018-01-15 20:51:54 -0600172 s64 sval = (s64)operand->fn(operand, elt, rbe, event);
Tom Zanussi100719d2018-01-15 20:51:52 -0600173 u64 val = (u64)-sval;
174
175 return val;
176}
177
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600178#define DEFINE_HIST_FIELD_FN(type) \
Tom Zanussifbd302c2018-01-15 20:51:43 -0600179 static u64 hist_field_##type(struct hist_field *hist_field, \
Tom Zanussidf35d932018-01-15 20:51:54 -0600180 struct tracing_map_elt *elt, \
181 struct ring_buffer_event *rbe, \
182 void *event) \
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600183{ \
184 type *addr = (type *)(event + hist_field->field->offset); \
185 \
Namhyung Kim79e577c2016-03-03 12:54:53 -0600186 return (u64)(unsigned long)*addr; \
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600187}
188
189DEFINE_HIST_FIELD_FN(s64);
190DEFINE_HIST_FIELD_FN(u64);
191DEFINE_HIST_FIELD_FN(s32);
192DEFINE_HIST_FIELD_FN(u32);
193DEFINE_HIST_FIELD_FN(s16);
194DEFINE_HIST_FIELD_FN(u16);
195DEFINE_HIST_FIELD_FN(s8);
196DEFINE_HIST_FIELD_FN(u8);
197
198#define for_each_hist_field(i, hist_data) \
199 for ((i) = 0; (i) < (hist_data)->n_fields; (i)++)
200
201#define for_each_hist_val_field(i, hist_data) \
202 for ((i) = 0; (i) < (hist_data)->n_vals; (i)++)
203
204#define for_each_hist_key_field(i, hist_data) \
205 for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++)
206
Tom Zanussi69a02002016-03-03 12:54:52 -0600207#define HIST_STACKTRACE_DEPTH 16
208#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long))
209#define HIST_STACKTRACE_SKIP 5
210
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600211#define HITCOUNT_IDX 0
Tom Zanussi69a02002016-03-03 12:54:52 -0600212#define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + HIST_STACKTRACE_SIZE)
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600213
214enum hist_field_flags {
Tom Zanussi0d7a8322017-09-22 14:58:21 -0500215 HIST_FIELD_FL_HITCOUNT = 1 << 0,
216 HIST_FIELD_FL_KEY = 1 << 1,
217 HIST_FIELD_FL_STRING = 1 << 2,
218 HIST_FIELD_FL_HEX = 1 << 3,
219 HIST_FIELD_FL_SYM = 1 << 4,
220 HIST_FIELD_FL_SYM_OFFSET = 1 << 5,
221 HIST_FIELD_FL_EXECNAME = 1 << 6,
222 HIST_FIELD_FL_SYSCALL = 1 << 7,
223 HIST_FIELD_FL_STACKTRACE = 1 << 8,
224 HIST_FIELD_FL_LOG2 = 1 << 9,
Tom Zanussiad42feb2018-01-15 20:51:45 -0600225 HIST_FIELD_FL_TIMESTAMP = 1 << 10,
Tom Zanussi860f9f62018-01-15 20:51:48 -0600226 HIST_FIELD_FL_TIMESTAMP_USECS = 1 << 11,
Tom Zanussi30350d62018-01-15 20:51:49 -0600227 HIST_FIELD_FL_VAR = 1 << 12,
Tom Zanussi100719d2018-01-15 20:51:52 -0600228 HIST_FIELD_FL_EXPR = 1 << 13,
Tom Zanussi067fe032018-01-15 20:51:56 -0600229 HIST_FIELD_FL_VAR_REF = 1 << 14,
Tom Zanussi30350d62018-01-15 20:51:49 -0600230};
231
232struct var_defs {
233 unsigned int n_vars;
234 char *name[TRACING_MAP_VARS_MAX];
235 char *expr[TRACING_MAP_VARS_MAX];
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600236};
237
238struct hist_trigger_attrs {
239 char *keys_str;
Tom Zanussif2606832016-03-03 12:54:43 -0600240 char *vals_str;
Tom Zanussie62347d2016-03-03 12:54:45 -0600241 char *sort_key_str;
Tom Zanussi5463bfd2016-03-03 12:54:59 -0600242 char *name;
Tom Zanussi83e99912016-03-03 12:54:46 -0600243 bool pause;
244 bool cont;
Tom Zanussie86ae9b2016-03-03 12:54:47 -0600245 bool clear;
Tom Zanussi860f9f62018-01-15 20:51:48 -0600246 bool ts_in_usecs;
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600247 unsigned int map_bits;
Tom Zanussi30350d62018-01-15 20:51:49 -0600248
249 char *assignment_str[TRACING_MAP_VARS_MAX];
250 unsigned int n_assignments;
251
Tom Zanussi0212e2a2018-01-15 20:51:57 -0600252 char *action_str[HIST_ACTIONS_MAX];
253 unsigned int n_actions;
254
Tom Zanussi30350d62018-01-15 20:51:49 -0600255 struct var_defs var_defs;
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600256};
257
Tom Zanussi02205a62018-01-15 20:51:59 -0600258struct field_var {
259 struct hist_field *var;
260 struct hist_field *val;
261};
262
263struct field_var_hist {
264 struct hist_trigger_data *hist_data;
265 char *cmd;
266};
267
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600268struct hist_trigger_data {
Tom Zanussi30350d62018-01-15 20:51:49 -0600269 struct hist_field *fields[HIST_FIELDS_MAX];
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600270 unsigned int n_vals;
271 unsigned int n_keys;
272 unsigned int n_fields;
Tom Zanussi30350d62018-01-15 20:51:49 -0600273 unsigned int n_vars;
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600274 unsigned int key_size;
275 struct tracing_map_sort_key sort_keys[TRACING_MAP_SORT_KEYS_MAX];
276 unsigned int n_sort_keys;
277 struct trace_event_file *event_file;
278 struct hist_trigger_attrs *attrs;
279 struct tracing_map *map;
Tom Zanussiad42feb2018-01-15 20:51:45 -0600280 bool enable_timestamps;
Tom Zanussi30350d62018-01-15 20:51:49 -0600281 bool remove;
Tom Zanussi067fe032018-01-15 20:51:56 -0600282 struct hist_field *var_refs[TRACING_MAP_VARS_MAX];
283 unsigned int n_var_refs;
Tom Zanussi0212e2a2018-01-15 20:51:57 -0600284
285 struct action_data *actions[HIST_ACTIONS_MAX];
286 unsigned int n_actions;
Tom Zanussi02205a62018-01-15 20:51:59 -0600287
Tom Zanussic282a382018-01-15 20:52:00 -0600288 struct hist_field *synth_var_refs[SYNTH_FIELDS_MAX];
289 unsigned int n_synth_var_refs;
Tom Zanussi02205a62018-01-15 20:51:59 -0600290 struct field_var *field_vars[SYNTH_FIELDS_MAX];
291 unsigned int n_field_vars;
292 unsigned int n_field_var_str;
293 struct field_var_hist *field_var_hists[SYNTH_FIELDS_MAX];
294 unsigned int n_field_var_hists;
Tom Zanussi0212e2a2018-01-15 20:51:57 -0600295};
296
Tom Zanussi4b147932018-01-15 20:51:58 -0600297struct synth_field {
298 char *type;
299 char *name;
300 size_t size;
301 bool is_signed;
302 bool is_string;
303};
304
305struct synth_event {
306 struct list_head list;
307 int ref;
308 char *name;
309 struct synth_field **fields;
310 unsigned int n_fields;
311 unsigned int n_u64;
312 struct trace_event_class class;
313 struct trace_event_call call;
314 struct tracepoint *tp;
315};
316
Tom Zanussi0212e2a2018-01-15 20:51:57 -0600317struct action_data;
318
319typedef void (*action_fn_t) (struct hist_trigger_data *hist_data,
320 struct tracing_map_elt *elt, void *rec,
321 struct ring_buffer_event *rbe,
322 struct action_data *data, u64 *var_ref_vals);
323
324struct action_data {
325 action_fn_t fn;
Tom Zanussic282a382018-01-15 20:52:00 -0600326 unsigned int n_params;
327 char *params[SYNTH_FIELDS_MAX];
328
329 union {
330 struct {
331 unsigned int var_ref_idx;
332 char *match_event;
333 char *match_event_system;
334 char *synth_event_name;
335 struct synth_event *synth_event;
336 } onmatch;
337 };
Tom Zanussi7ef224d2016-03-03 12:54:42 -0600338};
339
Tom Zanussi4b147932018-01-15 20:51:58 -0600340static LIST_HEAD(synth_event_list);
341static DEFINE_MUTEX(synth_event_mutex);
342
343struct synth_trace_event {
344 struct trace_entry ent;
345 u64 fields[];
346};
347
348static int synth_event_define_fields(struct trace_event_call *call)
349{
350 struct synth_trace_event trace;
351 int offset = offsetof(typeof(trace), fields);
352 struct synth_event *event = call->data;
353 unsigned int i, size, n_u64;
354 char *name, *type;
355 bool is_signed;
356 int ret = 0;
357
358 for (i = 0, n_u64 = 0; i < event->n_fields; i++) {
359 size = event->fields[i]->size;
360 is_signed = event->fields[i]->is_signed;
361 type = event->fields[i]->type;
362 name = event->fields[i]->name;
363 ret = trace_define_field(call, type, name, offset, size,
364 is_signed, FILTER_OTHER);
365 if (ret)
366 break;
367
368 if (event->fields[i]->is_string) {
369 offset += STR_VAR_LEN_MAX;
370 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
371 } else {
372 offset += sizeof(u64);
373 n_u64++;
374 }
375 }
376
377 event->n_u64 = n_u64;
378
379 return ret;
380}
381
382static bool synth_field_signed(char *type)
383{
384 if (strncmp(type, "u", 1) == 0)
385 return false;
386
387 return true;
388}
389
390static int synth_field_is_string(char *type)
391{
392 if (strstr(type, "char[") != NULL)
393 return true;
394
395 return false;
396}
397
398static int synth_field_string_size(char *type)
399{
400 char buf[4], *end, *start;
401 unsigned int len;
402 int size, err;
403
404 start = strstr(type, "char[");
405 if (start == NULL)
406 return -EINVAL;
407 start += strlen("char[");
408
409 end = strchr(type, ']');
410 if (!end || end < start)
411 return -EINVAL;
412
413 len = end - start;
414 if (len > 3)
415 return -EINVAL;
416
417 strncpy(buf, start, len);
418 buf[len] = '\0';
419
420 err = kstrtouint(buf, 0, &size);
421 if (err)
422 return err;
423
424 if (size > STR_VAR_LEN_MAX)
425 return -EINVAL;
426
427 return size;
428}
429
430static int synth_field_size(char *type)
431{
432 int size = 0;
433
434 if (strcmp(type, "s64") == 0)
435 size = sizeof(s64);
436 else if (strcmp(type, "u64") == 0)
437 size = sizeof(u64);
438 else if (strcmp(type, "s32") == 0)
439 size = sizeof(s32);
440 else if (strcmp(type, "u32") == 0)
441 size = sizeof(u32);
442 else if (strcmp(type, "s16") == 0)
443 size = sizeof(s16);
444 else if (strcmp(type, "u16") == 0)
445 size = sizeof(u16);
446 else if (strcmp(type, "s8") == 0)
447 size = sizeof(s8);
448 else if (strcmp(type, "u8") == 0)
449 size = sizeof(u8);
450 else if (strcmp(type, "char") == 0)
451 size = sizeof(char);
452 else if (strcmp(type, "unsigned char") == 0)
453 size = sizeof(unsigned char);
454 else if (strcmp(type, "int") == 0)
455 size = sizeof(int);
456 else if (strcmp(type, "unsigned int") == 0)
457 size = sizeof(unsigned int);
458 else if (strcmp(type, "long") == 0)
459 size = sizeof(long);
460 else if (strcmp(type, "unsigned long") == 0)
461 size = sizeof(unsigned long);
462 else if (strcmp(type, "pid_t") == 0)
463 size = sizeof(pid_t);
464 else if (synth_field_is_string(type))
465 size = synth_field_string_size(type);
466
467 return size;
468}
469
470static const char *synth_field_fmt(char *type)
471{
472 const char *fmt = "%llu";
473
474 if (strcmp(type, "s64") == 0)
475 fmt = "%lld";
476 else if (strcmp(type, "u64") == 0)
477 fmt = "%llu";
478 else if (strcmp(type, "s32") == 0)
479 fmt = "%d";
480 else if (strcmp(type, "u32") == 0)
481 fmt = "%u";
482 else if (strcmp(type, "s16") == 0)
483 fmt = "%d";
484 else if (strcmp(type, "u16") == 0)
485 fmt = "%u";
486 else if (strcmp(type, "s8") == 0)
487 fmt = "%d";
488 else if (strcmp(type, "u8") == 0)
489 fmt = "%u";
490 else if (strcmp(type, "char") == 0)
491 fmt = "%d";
492 else if (strcmp(type, "unsigned char") == 0)
493 fmt = "%u";
494 else if (strcmp(type, "int") == 0)
495 fmt = "%d";
496 else if (strcmp(type, "unsigned int") == 0)
497 fmt = "%u";
498 else if (strcmp(type, "long") == 0)
499 fmt = "%ld";
500 else if (strcmp(type, "unsigned long") == 0)
501 fmt = "%lu";
502 else if (strcmp(type, "pid_t") == 0)
503 fmt = "%d";
504 else if (synth_field_is_string(type))
505 fmt = "%s";
506
507 return fmt;
508}
509
510static enum print_line_t print_synth_event(struct trace_iterator *iter,
511 int flags,
512 struct trace_event *event)
513{
514 struct trace_array *tr = iter->tr;
515 struct trace_seq *s = &iter->seq;
516 struct synth_trace_event *entry;
517 struct synth_event *se;
518 unsigned int i, n_u64;
519 char print_fmt[32];
520 const char *fmt;
521
522 entry = (struct synth_trace_event *)iter->ent;
523 se = container_of(event, struct synth_event, call.event);
524
525 trace_seq_printf(s, "%s: ", se->name);
526
527 for (i = 0, n_u64 = 0; i < se->n_fields; i++) {
528 if (trace_seq_has_overflowed(s))
529 goto end;
530
531 fmt = synth_field_fmt(se->fields[i]->type);
532
533 /* parameter types */
534 if (tr->trace_flags & TRACE_ITER_VERBOSE)
535 trace_seq_printf(s, "%s ", fmt);
536
537 snprintf(print_fmt, sizeof(print_fmt), "%%s=%s%%s", fmt);
538
539 /* parameter values */
540 if (se->fields[i]->is_string) {
541 trace_seq_printf(s, print_fmt, se->fields[i]->name,
542 (char *)&entry->fields[n_u64],
543 i == se->n_fields - 1 ? "" : " ");
544 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
545 } else {
546 trace_seq_printf(s, print_fmt, se->fields[i]->name,
547 entry->fields[n_u64],
548 i == se->n_fields - 1 ? "" : " ");
549 n_u64++;
550 }
551 }
552end:
553 trace_seq_putc(s, '\n');
554
555 return trace_handle_return(s);
556}
557
558static struct trace_event_functions synth_event_funcs = {
559 .trace = print_synth_event
560};
561
562static notrace void trace_event_raw_event_synth(void *__data,
563 u64 *var_ref_vals,
564 unsigned int var_ref_idx)
565{
566 struct trace_event_file *trace_file = __data;
567 struct synth_trace_event *entry;
568 struct trace_event_buffer fbuffer;
569 struct synth_event *event;
570 unsigned int i, n_u64;
571 int fields_size = 0;
572
573 event = trace_file->event_call->data;
574
575 if (trace_trigger_soft_disabled(trace_file))
576 return;
577
578 fields_size = event->n_u64 * sizeof(u64);
579
580 entry = trace_event_buffer_reserve(&fbuffer, trace_file,
581 sizeof(*entry) + fields_size);
582 if (!entry)
583 return;
584
585 for (i = 0, n_u64 = 0; i < event->n_fields; i++) {
586 if (event->fields[i]->is_string) {
587 char *str_val = (char *)(long)var_ref_vals[var_ref_idx + i];
588 char *str_field = (char *)&entry->fields[n_u64];
589
590 strncpy(str_field, str_val, STR_VAR_LEN_MAX);
591 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
592 } else {
593 entry->fields[n_u64] = var_ref_vals[var_ref_idx + i];
594 n_u64++;
595 }
596 }
597
598 trace_event_buffer_commit(&fbuffer);
599}
600
601static void free_synth_event_print_fmt(struct trace_event_call *call)
602{
603 if (call) {
604 kfree(call->print_fmt);
605 call->print_fmt = NULL;
606 }
607}
608
609static int __set_synth_event_print_fmt(struct synth_event *event,
610 char *buf, int len)
611{
612 const char *fmt;
613 int pos = 0;
614 int i;
615
616 /* When len=0, we just calculate the needed length */
617#define LEN_OR_ZERO (len ? len - pos : 0)
618
619 pos += snprintf(buf + pos, LEN_OR_ZERO, "\"");
620 for (i = 0; i < event->n_fields; i++) {
621 fmt = synth_field_fmt(event->fields[i]->type);
622 pos += snprintf(buf + pos, LEN_OR_ZERO, "%s=%s%s",
623 event->fields[i]->name, fmt,
624 i == event->n_fields - 1 ? "" : ", ");
625 }
626 pos += snprintf(buf + pos, LEN_OR_ZERO, "\"");
627
628 for (i = 0; i < event->n_fields; i++) {
629 pos += snprintf(buf + pos, LEN_OR_ZERO,
630 ", REC->%s", event->fields[i]->name);
631 }
632
633#undef LEN_OR_ZERO
634
635 /* return the length of print_fmt */
636 return pos;
637}
638
639static int set_synth_event_print_fmt(struct trace_event_call *call)
640{
641 struct synth_event *event = call->data;
642 char *print_fmt;
643 int len;
644
645 /* First: called with 0 length to calculate the needed length */
646 len = __set_synth_event_print_fmt(event, NULL, 0);
647
648 print_fmt = kmalloc(len + 1, GFP_KERNEL);
649 if (!print_fmt)
650 return -ENOMEM;
651
652 /* Second: actually write the @print_fmt */
653 __set_synth_event_print_fmt(event, print_fmt, len + 1);
654 call->print_fmt = print_fmt;
655
656 return 0;
657}
658
659static void free_synth_field(struct synth_field *field)
660{
661 kfree(field->type);
662 kfree(field->name);
663 kfree(field);
664}
665
666static struct synth_field *parse_synth_field(char *field_type,
667 char *field_name)
668{
669 struct synth_field *field;
670 int len, ret = 0;
671 char *array;
672
673 if (field_type[0] == ';')
674 field_type++;
675
676 len = strlen(field_name);
677 if (field_name[len - 1] == ';')
678 field_name[len - 1] = '\0';
679
680 field = kzalloc(sizeof(*field), GFP_KERNEL);
681 if (!field)
682 return ERR_PTR(-ENOMEM);
683
684 len = strlen(field_type) + 1;
685 array = strchr(field_name, '[');
686 if (array)
687 len += strlen(array);
688 field->type = kzalloc(len, GFP_KERNEL);
689 if (!field->type) {
690 ret = -ENOMEM;
691 goto free;
692 }
693 strcat(field->type, field_type);
694 if (array) {
695 strcat(field->type, array);
696 *array = '\0';
697 }
698
699 field->size = synth_field_size(field->type);
700 if (!field->size) {
701 ret = -EINVAL;
702 goto free;
703 }
704
705 if (synth_field_is_string(field->type))
706 field->is_string = true;
707
708 field->is_signed = synth_field_signed(field->type);
709
710 field->name = kstrdup(field_name, GFP_KERNEL);
711 if (!field->name) {
712 ret = -ENOMEM;
713 goto free;
714 }
715 out:
716 return field;
717 free:
718 free_synth_field(field);
719 field = ERR_PTR(ret);
720 goto out;
721}
722
723static void free_synth_tracepoint(struct tracepoint *tp)
724{
725 if (!tp)
726 return;
727
728 kfree(tp->name);
729 kfree(tp);
730}
731
732static struct tracepoint *alloc_synth_tracepoint(char *name)
733{
734 struct tracepoint *tp;
735
736 tp = kzalloc(sizeof(*tp), GFP_KERNEL);
737 if (!tp)
738 return ERR_PTR(-ENOMEM);
739
740 tp->name = kstrdup(name, GFP_KERNEL);
741 if (!tp->name) {
742 kfree(tp);
743 return ERR_PTR(-ENOMEM);
744 }
745
746 return tp;
747}
748
749typedef void (*synth_probe_func_t) (void *__data, u64 *var_ref_vals,
750 unsigned int var_ref_idx);
751
752static inline void trace_synth(struct synth_event *event, u64 *var_ref_vals,
753 unsigned int var_ref_idx)
754{
755 struct tracepoint *tp = event->tp;
756
757 if (unlikely(atomic_read(&tp->key.enabled) > 0)) {
758 struct tracepoint_func *probe_func_ptr;
759 synth_probe_func_t probe_func;
760 void *__data;
761
762 if (!(cpu_online(raw_smp_processor_id())))
763 return;
764
765 probe_func_ptr = rcu_dereference_sched((tp)->funcs);
766 if (probe_func_ptr) {
767 do {
768 probe_func = probe_func_ptr->func;
769 __data = probe_func_ptr->data;
770 probe_func(__data, var_ref_vals, var_ref_idx);
771 } while ((++probe_func_ptr)->func);
772 }
773 }
774}
775
776static struct synth_event *find_synth_event(const char *name)
777{
778 struct synth_event *event;
779
780 list_for_each_entry(event, &synth_event_list, list) {
781 if (strcmp(event->name, name) == 0)
782 return event;
783 }
784
785 return NULL;
786}
787
788static int register_synth_event(struct synth_event *event)
789{
790 struct trace_event_call *call = &event->call;
791 int ret = 0;
792
793 event->call.class = &event->class;
794 event->class.system = kstrdup(SYNTH_SYSTEM, GFP_KERNEL);
795 if (!event->class.system) {
796 ret = -ENOMEM;
797 goto out;
798 }
799
800 event->tp = alloc_synth_tracepoint(event->name);
801 if (IS_ERR(event->tp)) {
802 ret = PTR_ERR(event->tp);
803 event->tp = NULL;
804 goto out;
805 }
806
807 INIT_LIST_HEAD(&call->class->fields);
808 call->event.funcs = &synth_event_funcs;
809 call->class->define_fields = synth_event_define_fields;
810
811 ret = register_trace_event(&call->event);
812 if (!ret) {
813 ret = -ENODEV;
814 goto out;
815 }
816 call->flags = TRACE_EVENT_FL_TRACEPOINT;
817 call->class->reg = trace_event_reg;
818 call->class->probe = trace_event_raw_event_synth;
819 call->data = event;
820 call->tp = event->tp;
821
822 ret = trace_add_event_call(call);
823 if (ret) {
824 pr_warn("Failed to register synthetic event: %s\n",
825 trace_event_name(call));
826 goto err;
827 }
828
829 ret = set_synth_event_print_fmt(call);
830 if (ret < 0) {
831 trace_remove_event_call(call);
832 goto err;
833 }
834 out:
835 return ret;
836 err:
837 unregister_trace_event(&call->event);
838 goto out;
839}
840
841static int unregister_synth_event(struct synth_event *event)
842{
843 struct trace_event_call *call = &event->call;
844 int ret;
845
846 ret = trace_remove_event_call(call);
847
848 return ret;
849}
850
851static void free_synth_event(struct synth_event *event)
852{
853 unsigned int i;
854
855 if (!event)
856 return;
857
858 for (i = 0; i < event->n_fields; i++)
859 free_synth_field(event->fields[i]);
860
861 kfree(event->fields);
862 kfree(event->name);
863 kfree(event->class.system);
864 free_synth_tracepoint(event->tp);
865 free_synth_event_print_fmt(&event->call);
866 kfree(event);
867}
868
869static struct synth_event *alloc_synth_event(char *event_name, int n_fields,
870 struct synth_field **fields)
871{
872 struct synth_event *event;
873 unsigned int i;
874
875 event = kzalloc(sizeof(*event), GFP_KERNEL);
876 if (!event) {
877 event = ERR_PTR(-ENOMEM);
878 goto out;
879 }
880
881 event->name = kstrdup(event_name, GFP_KERNEL);
882 if (!event->name) {
883 kfree(event);
884 event = ERR_PTR(-ENOMEM);
885 goto out;
886 }
887
888 event->fields = kcalloc(n_fields, sizeof(*event->fields), GFP_KERNEL);
889 if (!event->fields) {
890 free_synth_event(event);
891 event = ERR_PTR(-ENOMEM);
892 goto out;
893 }
894
895 for (i = 0; i < n_fields; i++)
896 event->fields[i] = fields[i];
897
898 event->n_fields = n_fields;
899 out:
900 return event;
901}
902
Tom Zanussic282a382018-01-15 20:52:00 -0600903static void action_trace(struct hist_trigger_data *hist_data,
904 struct tracing_map_elt *elt, void *rec,
905 struct ring_buffer_event *rbe,
906 struct action_data *data, u64 *var_ref_vals)
907{
908 struct synth_event *event = data->onmatch.synth_event;
909
910 trace_synth(event, var_ref_vals, data->onmatch.var_ref_idx);
911}
912
913struct hist_var_data {
914 struct list_head list;
915 struct hist_trigger_data *hist_data;
916};
917
Tom Zanussi4b147932018-01-15 20:51:58 -0600918static void add_or_delete_synth_event(struct synth_event *event, int delete)
919{
920 if (delete)
921 free_synth_event(event);
922 else {
923 mutex_lock(&synth_event_mutex);
924 if (!find_synth_event(event->name))
925 list_add(&event->list, &synth_event_list);
926 else
927 free_synth_event(event);
928 mutex_unlock(&synth_event_mutex);
929 }
930}
931
932static int create_synth_event(int argc, char **argv)
933{
934 struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
935 struct synth_event *event = NULL;
936 bool delete_event = false;
937 int i, n_fields = 0, ret = 0;
938 char *name;
939
940 mutex_lock(&synth_event_mutex);
941
942 /*
943 * Argument syntax:
944 * - Add synthetic event: <event_name> field[;field] ...
945 * - Remove synthetic event: !<event_name> field[;field] ...
946 * where 'field' = type field_name
947 */
948 if (argc < 1) {
949 ret = -EINVAL;
950 goto out;
951 }
952
953 name = argv[0];
954 if (name[0] == '!') {
955 delete_event = true;
956 name++;
957 }
958
959 event = find_synth_event(name);
960 if (event) {
961 if (delete_event) {
962 if (event->ref) {
963 event = NULL;
964 ret = -EBUSY;
965 goto out;
966 }
967 list_del(&event->list);
968 goto out;
969 }
970 event = NULL;
971 ret = -EEXIST;
972 goto out;
973 } else if (delete_event)
974 goto out;
975
976 if (argc < 2) {
977 ret = -EINVAL;
978 goto out;
979 }
980
981 for (i = 1; i < argc - 1; i++) {
982 if (strcmp(argv[i], ";") == 0)
983 continue;
984 if (n_fields == SYNTH_FIELDS_MAX) {
985 ret = -EINVAL;
986 goto err;
987 }
988
989 field = parse_synth_field(argv[i], argv[i + 1]);
990 if (IS_ERR(field)) {
991 ret = PTR_ERR(field);
992 goto err;
993 }
994 fields[n_fields] = field;
995 i++; n_fields++;
996 }
997
998 if (i < argc) {
999 ret = -EINVAL;
1000 goto err;
1001 }
1002
1003 event = alloc_synth_event(name, n_fields, fields);
1004 if (IS_ERR(event)) {
1005 ret = PTR_ERR(event);
1006 event = NULL;
1007 goto err;
1008 }
1009 out:
1010 mutex_unlock(&synth_event_mutex);
1011
1012 if (event) {
1013 if (delete_event) {
1014 ret = unregister_synth_event(event);
1015 add_or_delete_synth_event(event, !ret);
1016 } else {
1017 ret = register_synth_event(event);
1018 add_or_delete_synth_event(event, ret);
1019 }
1020 }
1021
1022 return ret;
1023 err:
1024 mutex_unlock(&synth_event_mutex);
1025
1026 for (i = 0; i < n_fields; i++)
1027 free_synth_field(fields[i]);
1028 free_synth_event(event);
1029
1030 return ret;
1031}
1032
1033static int release_all_synth_events(void)
1034{
1035 struct list_head release_events;
1036 struct synth_event *event, *e;
1037 int ret = 0;
1038
1039 INIT_LIST_HEAD(&release_events);
1040
1041 mutex_lock(&synth_event_mutex);
1042
1043 list_for_each_entry(event, &synth_event_list, list) {
1044 if (event->ref) {
1045 mutex_unlock(&synth_event_mutex);
1046 return -EBUSY;
1047 }
1048 }
1049
1050 list_splice_init(&event->list, &release_events);
1051
1052 mutex_unlock(&synth_event_mutex);
1053
1054 list_for_each_entry_safe(event, e, &release_events, list) {
1055 list_del(&event->list);
1056
1057 ret = unregister_synth_event(event);
1058 add_or_delete_synth_event(event, !ret);
1059 }
1060
1061 return ret;
1062}
1063
1064
1065static void *synth_events_seq_start(struct seq_file *m, loff_t *pos)
1066{
1067 mutex_lock(&synth_event_mutex);
1068
1069 return seq_list_start(&synth_event_list, *pos);
1070}
1071
1072static void *synth_events_seq_next(struct seq_file *m, void *v, loff_t *pos)
1073{
1074 return seq_list_next(v, &synth_event_list, pos);
1075}
1076
1077static void synth_events_seq_stop(struct seq_file *m, void *v)
1078{
1079 mutex_unlock(&synth_event_mutex);
1080}
1081
1082static int synth_events_seq_show(struct seq_file *m, void *v)
1083{
1084 struct synth_field *field;
1085 struct synth_event *event = v;
1086 unsigned int i;
1087
1088 seq_printf(m, "%s\t", event->name);
1089
1090 for (i = 0; i < event->n_fields; i++) {
1091 field = event->fields[i];
1092
1093 /* parameter values */
1094 seq_printf(m, "%s %s%s", field->type, field->name,
1095 i == event->n_fields - 1 ? "" : "; ");
1096 }
1097
1098 seq_putc(m, '\n');
1099
1100 return 0;
1101}
1102
1103static const struct seq_operations synth_events_seq_op = {
1104 .start = synth_events_seq_start,
1105 .next = synth_events_seq_next,
1106 .stop = synth_events_seq_stop,
1107 .show = synth_events_seq_show
1108};
1109
1110static int synth_events_open(struct inode *inode, struct file *file)
1111{
1112 int ret;
1113
1114 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
1115 ret = release_all_synth_events();
1116 if (ret < 0)
1117 return ret;
1118 }
1119
1120 return seq_open(file, &synth_events_seq_op);
1121}
1122
1123static ssize_t synth_events_write(struct file *file,
1124 const char __user *buffer,
1125 size_t count, loff_t *ppos)
1126{
1127 return trace_parse_run_command(file, buffer, count, ppos,
1128 create_synth_event);
1129}
1130
1131static const struct file_operations synth_events_fops = {
1132 .open = synth_events_open,
1133 .write = synth_events_write,
1134 .read = seq_read,
1135 .llseek = seq_lseek,
1136 .release = seq_release,
1137};
1138
Tom Zanussidf35d932018-01-15 20:51:54 -06001139static u64 hist_field_timestamp(struct hist_field *hist_field,
1140 struct tracing_map_elt *elt,
1141 struct ring_buffer_event *rbe,
1142 void *event)
Tom Zanussi860f9f62018-01-15 20:51:48 -06001143{
1144 struct hist_trigger_data *hist_data = hist_field->hist_data;
1145 struct trace_array *tr = hist_data->event_file->tr;
1146
1147 u64 ts = ring_buffer_event_time_stamp(rbe);
1148
1149 if (hist_data->attrs->ts_in_usecs && trace_clock_in_ns(tr))
1150 ts = ns2usecs(ts);
1151
1152 return ts;
1153}
1154
Tom Zanussi067fe032018-01-15 20:51:56 -06001155static struct hist_field *
1156check_field_for_var_ref(struct hist_field *hist_field,
1157 struct hist_trigger_data *var_data,
1158 unsigned int var_idx)
1159{
1160 struct hist_field *found = NULL;
1161
1162 if (hist_field && hist_field->flags & HIST_FIELD_FL_VAR_REF) {
1163 if (hist_field->var.idx == var_idx &&
1164 hist_field->var.hist_data == var_data) {
1165 found = hist_field;
1166 }
1167 }
1168
1169 return found;
1170}
1171
1172static struct hist_field *
1173check_field_for_var_refs(struct hist_trigger_data *hist_data,
1174 struct hist_field *hist_field,
1175 struct hist_trigger_data *var_data,
1176 unsigned int var_idx,
1177 unsigned int level)
1178{
1179 struct hist_field *found = NULL;
1180 unsigned int i;
1181
1182 if (level > 3)
1183 return found;
1184
1185 if (!hist_field)
1186 return found;
1187
1188 found = check_field_for_var_ref(hist_field, var_data, var_idx);
1189 if (found)
1190 return found;
1191
1192 for (i = 0; i < HIST_FIELD_OPERANDS_MAX; i++) {
1193 struct hist_field *operand;
1194
1195 operand = hist_field->operands[i];
1196 found = check_field_for_var_refs(hist_data, operand, var_data,
1197 var_idx, level + 1);
1198 if (found)
1199 return found;
1200 }
1201
1202 return found;
1203}
1204
1205static struct hist_field *find_var_ref(struct hist_trigger_data *hist_data,
1206 struct hist_trigger_data *var_data,
1207 unsigned int var_idx)
1208{
1209 struct hist_field *hist_field, *found = NULL;
1210 unsigned int i;
1211
1212 for_each_hist_field(i, hist_data) {
1213 hist_field = hist_data->fields[i];
1214 found = check_field_for_var_refs(hist_data, hist_field,
1215 var_data, var_idx, 0);
1216 if (found)
1217 return found;
1218 }
1219
Tom Zanussic282a382018-01-15 20:52:00 -06001220 for (i = 0; i < hist_data->n_synth_var_refs; i++) {
1221 hist_field = hist_data->synth_var_refs[i];
1222 found = check_field_for_var_refs(hist_data, hist_field,
1223 var_data, var_idx, 0);
1224 if (found)
1225 return found;
1226 }
1227
Tom Zanussi067fe032018-01-15 20:51:56 -06001228 return found;
1229}
1230
1231static struct hist_field *find_any_var_ref(struct hist_trigger_data *hist_data,
1232 unsigned int var_idx)
1233{
1234 struct trace_array *tr = hist_data->event_file->tr;
1235 struct hist_field *found = NULL;
1236 struct hist_var_data *var_data;
1237
1238 list_for_each_entry(var_data, &tr->hist_vars, list) {
1239 if (var_data->hist_data == hist_data)
1240 continue;
1241 found = find_var_ref(var_data->hist_data, hist_data, var_idx);
1242 if (found)
1243 break;
1244 }
1245
1246 return found;
1247}
1248
1249static bool check_var_refs(struct hist_trigger_data *hist_data)
1250{
1251 struct hist_field *field;
1252 bool found = false;
1253 int i;
1254
1255 for_each_hist_field(i, hist_data) {
1256 field = hist_data->fields[i];
1257 if (field && field->flags & HIST_FIELD_FL_VAR) {
1258 if (find_any_var_ref(hist_data, field->var.idx)) {
1259 found = true;
1260 break;
1261 }
1262 }
1263 }
1264
1265 return found;
1266}
1267
1268static struct hist_var_data *find_hist_vars(struct hist_trigger_data *hist_data)
1269{
1270 struct trace_array *tr = hist_data->event_file->tr;
1271 struct hist_var_data *var_data, *found = NULL;
1272
1273 list_for_each_entry(var_data, &tr->hist_vars, list) {
1274 if (var_data->hist_data == hist_data) {
1275 found = var_data;
1276 break;
1277 }
1278 }
1279
1280 return found;
1281}
1282
1283static bool field_has_hist_vars(struct hist_field *hist_field,
1284 unsigned int level)
1285{
1286 int i;
1287
1288 if (level > 3)
1289 return false;
1290
1291 if (!hist_field)
1292 return false;
1293
1294 if (hist_field->flags & HIST_FIELD_FL_VAR ||
1295 hist_field->flags & HIST_FIELD_FL_VAR_REF)
1296 return true;
1297
1298 for (i = 0; i < HIST_FIELD_OPERANDS_MAX; i++) {
1299 struct hist_field *operand;
1300
1301 operand = hist_field->operands[i];
1302 if (field_has_hist_vars(operand, level + 1))
1303 return true;
1304 }
1305
1306 return false;
1307}
1308
1309static bool has_hist_vars(struct hist_trigger_data *hist_data)
1310{
1311 struct hist_field *hist_field;
1312 int i;
1313
1314 for_each_hist_field(i, hist_data) {
1315 hist_field = hist_data->fields[i];
1316 if (field_has_hist_vars(hist_field, 0))
1317 return true;
1318 }
1319
1320 return false;
1321}
1322
1323static int save_hist_vars(struct hist_trigger_data *hist_data)
1324{
1325 struct trace_array *tr = hist_data->event_file->tr;
1326 struct hist_var_data *var_data;
1327
1328 var_data = find_hist_vars(hist_data);
1329 if (var_data)
1330 return 0;
1331
1332 if (trace_array_get(tr) < 0)
1333 return -ENODEV;
1334
1335 var_data = kzalloc(sizeof(*var_data), GFP_KERNEL);
1336 if (!var_data) {
1337 trace_array_put(tr);
1338 return -ENOMEM;
1339 }
1340
1341 var_data->hist_data = hist_data;
1342 list_add(&var_data->list, &tr->hist_vars);
1343
1344 return 0;
1345}
1346
1347static void remove_hist_vars(struct hist_trigger_data *hist_data)
1348{
1349 struct trace_array *tr = hist_data->event_file->tr;
1350 struct hist_var_data *var_data;
1351
1352 var_data = find_hist_vars(hist_data);
1353 if (!var_data)
1354 return;
1355
1356 if (WARN_ON(check_var_refs(hist_data)))
1357 return;
1358
1359 list_del(&var_data->list);
1360
1361 kfree(var_data);
1362
1363 trace_array_put(tr);
1364}
1365
Tom Zanussi30350d62018-01-15 20:51:49 -06001366static struct hist_field *find_var_field(struct hist_trigger_data *hist_data,
1367 const char *var_name)
1368{
1369 struct hist_field *hist_field, *found = NULL;
1370 int i;
1371
1372 for_each_hist_field(i, hist_data) {
1373 hist_field = hist_data->fields[i];
1374 if (hist_field && hist_field->flags & HIST_FIELD_FL_VAR &&
1375 strcmp(hist_field->var.name, var_name) == 0) {
1376 found = hist_field;
1377 break;
1378 }
1379 }
1380
1381 return found;
1382}
1383
1384static struct hist_field *find_var(struct hist_trigger_data *hist_data,
1385 struct trace_event_file *file,
1386 const char *var_name)
1387{
1388 struct hist_trigger_data *test_data;
1389 struct event_trigger_data *test;
1390 struct hist_field *hist_field;
1391
1392 hist_field = find_var_field(hist_data, var_name);
1393 if (hist_field)
1394 return hist_field;
1395
1396 list_for_each_entry_rcu(test, &file->triggers, list) {
1397 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
1398 test_data = test->private_data;
1399 hist_field = find_var_field(test_data, var_name);
1400 if (hist_field)
1401 return hist_field;
1402 }
1403 }
1404
1405 return NULL;
1406}
1407
Tom Zanussi067fe032018-01-15 20:51:56 -06001408static struct trace_event_file *find_var_file(struct trace_array *tr,
1409 char *system,
1410 char *event_name,
1411 char *var_name)
1412{
1413 struct hist_trigger_data *var_hist_data;
1414 struct hist_var_data *var_data;
1415 struct trace_event_file *file, *found = NULL;
1416
1417 if (system)
1418 return find_event_file(tr, system, event_name);
1419
1420 list_for_each_entry(var_data, &tr->hist_vars, list) {
1421 var_hist_data = var_data->hist_data;
1422 file = var_hist_data->event_file;
1423 if (file == found)
1424 continue;
1425
1426 if (find_var_field(var_hist_data, var_name)) {
1427 if (found)
1428 return NULL;
1429
1430 found = file;
1431 }
1432 }
1433
1434 return found;
1435}
1436
1437static struct hist_field *find_file_var(struct trace_event_file *file,
1438 const char *var_name)
1439{
1440 struct hist_trigger_data *test_data;
1441 struct event_trigger_data *test;
1442 struct hist_field *hist_field;
1443
1444 list_for_each_entry_rcu(test, &file->triggers, list) {
1445 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
1446 test_data = test->private_data;
1447 hist_field = find_var_field(test_data, var_name);
1448 if (hist_field)
1449 return hist_field;
1450 }
1451 }
1452
1453 return NULL;
1454}
1455
Tom Zanussic282a382018-01-15 20:52:00 -06001456static struct hist_field *
1457find_match_var(struct hist_trigger_data *hist_data, char *var_name)
1458{
1459 struct trace_array *tr = hist_data->event_file->tr;
1460 struct hist_field *hist_field, *found = NULL;
1461 struct trace_event_file *file;
1462 unsigned int i;
1463
1464 for (i = 0; i < hist_data->n_actions; i++) {
1465 struct action_data *data = hist_data->actions[i];
1466
1467 if (data->fn == action_trace) {
1468 char *system = data->onmatch.match_event_system;
1469 char *event_name = data->onmatch.match_event;
1470
1471 file = find_var_file(tr, system, event_name, var_name);
1472 if (!file)
1473 continue;
1474 hist_field = find_file_var(file, var_name);
1475 if (hist_field) {
1476 if (found) {
1477 return ERR_PTR(-EINVAL);
1478 }
1479
1480 found = hist_field;
1481 }
1482 }
1483 }
1484 return found;
1485}
1486
Tom Zanussi067fe032018-01-15 20:51:56 -06001487static struct hist_field *find_event_var(struct hist_trigger_data *hist_data,
1488 char *system,
1489 char *event_name,
1490 char *var_name)
1491{
1492 struct trace_array *tr = hist_data->event_file->tr;
1493 struct hist_field *hist_field = NULL;
1494 struct trace_event_file *file;
1495
Tom Zanussic282a382018-01-15 20:52:00 -06001496 if (!system || !event_name) {
1497 hist_field = find_match_var(hist_data, var_name);
1498 if (IS_ERR(hist_field))
1499 return NULL;
1500 if (hist_field)
1501 return hist_field;
1502 }
1503
Tom Zanussi067fe032018-01-15 20:51:56 -06001504 file = find_var_file(tr, system, event_name, var_name);
1505 if (!file)
1506 return NULL;
1507
1508 hist_field = find_file_var(file, var_name);
1509
1510 return hist_field;
1511}
1512
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001513struct hist_elt_data {
1514 char *comm;
Tom Zanussi067fe032018-01-15 20:51:56 -06001515 u64 *var_ref_vals;
Tom Zanussi02205a62018-01-15 20:51:59 -06001516 char *field_var_str[SYNTH_FIELDS_MAX];
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001517};
1518
Tom Zanussi067fe032018-01-15 20:51:56 -06001519static u64 hist_field_var_ref(struct hist_field *hist_field,
1520 struct tracing_map_elt *elt,
1521 struct ring_buffer_event *rbe,
1522 void *event)
1523{
1524 struct hist_elt_data *elt_data;
1525 u64 var_val = 0;
1526
1527 elt_data = elt->private_data;
1528 var_val = elt_data->var_ref_vals[hist_field->var_ref_idx];
1529
1530 return var_val;
1531}
1532
1533static bool resolve_var_refs(struct hist_trigger_data *hist_data, void *key,
1534 u64 *var_ref_vals, bool self)
1535{
1536 struct hist_trigger_data *var_data;
1537 struct tracing_map_elt *var_elt;
1538 struct hist_field *hist_field;
1539 unsigned int i, var_idx;
1540 bool resolved = true;
1541 u64 var_val = 0;
1542
1543 for (i = 0; i < hist_data->n_var_refs; i++) {
1544 hist_field = hist_data->var_refs[i];
1545 var_idx = hist_field->var.idx;
1546 var_data = hist_field->var.hist_data;
1547
1548 if (var_data == NULL) {
1549 resolved = false;
1550 break;
1551 }
1552
1553 if ((self && var_data != hist_data) ||
1554 (!self && var_data == hist_data))
1555 continue;
1556
1557 var_elt = tracing_map_lookup(var_data->map, key);
1558 if (!var_elt) {
1559 resolved = false;
1560 break;
1561 }
1562
1563 if (!tracing_map_var_set(var_elt, var_idx)) {
1564 resolved = false;
1565 break;
1566 }
1567
1568 if (self || !hist_field->read_once)
1569 var_val = tracing_map_read_var(var_elt, var_idx);
1570 else
1571 var_val = tracing_map_read_var_once(var_elt, var_idx);
1572
1573 var_ref_vals[i] = var_val;
1574 }
1575
1576 return resolved;
1577}
1578
Tom Zanussi85013252017-09-22 14:58:22 -05001579static const char *hist_field_name(struct hist_field *field,
1580 unsigned int level)
1581{
1582 const char *field_name = "";
1583
1584 if (level > 1)
1585 return field_name;
1586
1587 if (field->field)
1588 field_name = field->field->name;
Tom Zanussi5819ead2017-09-22 14:58:23 -05001589 else if (field->flags & HIST_FIELD_FL_LOG2)
1590 field_name = hist_field_name(field->operands[0], ++level);
Tom Zanussiad42feb2018-01-15 20:51:45 -06001591 else if (field->flags & HIST_FIELD_FL_TIMESTAMP)
1592 field_name = "common_timestamp";
Tom Zanussi067fe032018-01-15 20:51:56 -06001593 else if (field->flags & HIST_FIELD_FL_EXPR ||
1594 field->flags & HIST_FIELD_FL_VAR_REF) {
1595 if (field->system) {
1596 static char full_name[MAX_FILTER_STR_VAL];
1597
1598 strcat(full_name, field->system);
1599 strcat(full_name, ".");
1600 strcat(full_name, field->event_name);
1601 strcat(full_name, ".");
1602 strcat(full_name, field->name);
1603 field_name = full_name;
1604 } else
1605 field_name = field->name;
1606 }
Tom Zanussi85013252017-09-22 14:58:22 -05001607
1608 if (field_name == NULL)
1609 field_name = "";
1610
1611 return field_name;
1612}
1613
Tom Zanussi7ef224d2016-03-03 12:54:42 -06001614static hist_field_fn_t select_value_fn(int field_size, int field_is_signed)
1615{
1616 hist_field_fn_t fn = NULL;
1617
1618 switch (field_size) {
1619 case 8:
1620 if (field_is_signed)
1621 fn = hist_field_s64;
1622 else
1623 fn = hist_field_u64;
1624 break;
1625 case 4:
1626 if (field_is_signed)
1627 fn = hist_field_s32;
1628 else
1629 fn = hist_field_u32;
1630 break;
1631 case 2:
1632 if (field_is_signed)
1633 fn = hist_field_s16;
1634 else
1635 fn = hist_field_u16;
1636 break;
1637 case 1:
1638 if (field_is_signed)
1639 fn = hist_field_s8;
1640 else
1641 fn = hist_field_u8;
1642 break;
1643 }
1644
1645 return fn;
1646}
1647
1648static int parse_map_size(char *str)
1649{
1650 unsigned long size, map_bits;
1651 int ret;
1652
1653 strsep(&str, "=");
1654 if (!str) {
1655 ret = -EINVAL;
1656 goto out;
1657 }
1658
1659 ret = kstrtoul(str, 0, &size);
1660 if (ret)
1661 goto out;
1662
1663 map_bits = ilog2(roundup_pow_of_two(size));
1664 if (map_bits < TRACING_MAP_BITS_MIN ||
1665 map_bits > TRACING_MAP_BITS_MAX)
1666 ret = -EINVAL;
1667 else
1668 ret = map_bits;
1669 out:
1670 return ret;
1671}
1672
1673static void destroy_hist_trigger_attrs(struct hist_trigger_attrs *attrs)
1674{
Tom Zanussi30350d62018-01-15 20:51:49 -06001675 unsigned int i;
1676
Tom Zanussi7ef224d2016-03-03 12:54:42 -06001677 if (!attrs)
1678 return;
1679
Tom Zanussi30350d62018-01-15 20:51:49 -06001680 for (i = 0; i < attrs->n_assignments; i++)
1681 kfree(attrs->assignment_str[i]);
1682
Tom Zanussi0212e2a2018-01-15 20:51:57 -06001683 for (i = 0; i < attrs->n_actions; i++)
1684 kfree(attrs->action_str[i]);
1685
Tom Zanussi5463bfd2016-03-03 12:54:59 -06001686 kfree(attrs->name);
Tom Zanussie62347d2016-03-03 12:54:45 -06001687 kfree(attrs->sort_key_str);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06001688 kfree(attrs->keys_str);
Tom Zanussif2606832016-03-03 12:54:43 -06001689 kfree(attrs->vals_str);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06001690 kfree(attrs);
1691}
1692
Tom Zanussi0212e2a2018-01-15 20:51:57 -06001693static int parse_action(char *str, struct hist_trigger_attrs *attrs)
1694{
Tom Zanussic282a382018-01-15 20:52:00 -06001695 int ret = -EINVAL;
Tom Zanussi0212e2a2018-01-15 20:51:57 -06001696
1697 if (attrs->n_actions >= HIST_ACTIONS_MAX)
1698 return ret;
1699
Tom Zanussic282a382018-01-15 20:52:00 -06001700 if ((strncmp(str, "onmatch(", strlen("onmatch(")) == 0)) {
1701 attrs->action_str[attrs->n_actions] = kstrdup(str, GFP_KERNEL);
1702 if (!attrs->action_str[attrs->n_actions]) {
1703 ret = -ENOMEM;
1704 return ret;
1705 }
1706 attrs->n_actions++;
1707 ret = 0;
1708 }
1709
Tom Zanussi0212e2a2018-01-15 20:51:57 -06001710 return ret;
1711}
1712
Tom Zanussi9b1ae032018-01-15 20:51:44 -06001713static int parse_assignment(char *str, struct hist_trigger_attrs *attrs)
1714{
1715 int ret = 0;
1716
1717 if ((strncmp(str, "key=", strlen("key=")) == 0) ||
1718 (strncmp(str, "keys=", strlen("keys=")) == 0)) {
1719 attrs->keys_str = kstrdup(str, GFP_KERNEL);
1720 if (!attrs->keys_str) {
1721 ret = -ENOMEM;
1722 goto out;
1723 }
1724 } else if ((strncmp(str, "val=", strlen("val=")) == 0) ||
1725 (strncmp(str, "vals=", strlen("vals=")) == 0) ||
1726 (strncmp(str, "values=", strlen("values=")) == 0)) {
1727 attrs->vals_str = kstrdup(str, GFP_KERNEL);
1728 if (!attrs->vals_str) {
1729 ret = -ENOMEM;
1730 goto out;
1731 }
1732 } else if (strncmp(str, "sort=", strlen("sort=")) == 0) {
1733 attrs->sort_key_str = kstrdup(str, GFP_KERNEL);
1734 if (!attrs->sort_key_str) {
1735 ret = -ENOMEM;
1736 goto out;
1737 }
1738 } else if (strncmp(str, "name=", strlen("name=")) == 0) {
1739 attrs->name = kstrdup(str, GFP_KERNEL);
1740 if (!attrs->name) {
1741 ret = -ENOMEM;
1742 goto out;
1743 }
1744 } else if (strncmp(str, "size=", strlen("size=")) == 0) {
1745 int map_bits = parse_map_size(str);
1746
1747 if (map_bits < 0) {
1748 ret = map_bits;
1749 goto out;
1750 }
1751 attrs->map_bits = map_bits;
Tom Zanussi30350d62018-01-15 20:51:49 -06001752 } else {
1753 char *assignment;
1754
1755 if (attrs->n_assignments == TRACING_MAP_VARS_MAX) {
1756 ret = -EINVAL;
1757 goto out;
1758 }
1759
1760 assignment = kstrdup(str, GFP_KERNEL);
1761 if (!assignment) {
1762 ret = -ENOMEM;
1763 goto out;
1764 }
1765
1766 attrs->assignment_str[attrs->n_assignments++] = assignment;
1767 }
Tom Zanussi9b1ae032018-01-15 20:51:44 -06001768 out:
1769 return ret;
1770}
1771
Tom Zanussi7ef224d2016-03-03 12:54:42 -06001772static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str)
1773{
1774 struct hist_trigger_attrs *attrs;
1775 int ret = 0;
1776
1777 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1778 if (!attrs)
1779 return ERR_PTR(-ENOMEM);
1780
1781 while (trigger_str) {
1782 char *str = strsep(&trigger_str, ":");
1783
Tom Zanussi9b1ae032018-01-15 20:51:44 -06001784 if (strchr(str, '=')) {
1785 ret = parse_assignment(str, attrs);
1786 if (ret)
1787 goto free;
1788 } else if (strcmp(str, "pause") == 0)
Tom Zanussi83e99912016-03-03 12:54:46 -06001789 attrs->pause = true;
1790 else if ((strcmp(str, "cont") == 0) ||
1791 (strcmp(str, "continue") == 0))
1792 attrs->cont = true;
Tom Zanussie86ae9b2016-03-03 12:54:47 -06001793 else if (strcmp(str, "clear") == 0)
1794 attrs->clear = true;
Tom Zanussi9b1ae032018-01-15 20:51:44 -06001795 else {
Tom Zanussi0212e2a2018-01-15 20:51:57 -06001796 ret = parse_action(str, attrs);
1797 if (ret)
1798 goto free;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06001799 }
1800 }
1801
1802 if (!attrs->keys_str) {
1803 ret = -EINVAL;
1804 goto free;
1805 }
1806
1807 return attrs;
1808 free:
1809 destroy_hist_trigger_attrs(attrs);
1810
1811 return ERR_PTR(ret);
1812}
1813
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001814static inline void save_comm(char *comm, struct task_struct *task)
1815{
1816 if (!task->pid) {
1817 strcpy(comm, "<idle>");
1818 return;
1819 }
1820
1821 if (WARN_ON_ONCE(task->pid < 0)) {
1822 strcpy(comm, "<XXX>");
1823 return;
1824 }
1825
1826 memcpy(comm, task->comm, TASK_COMM_LEN);
1827}
1828
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001829static void hist_elt_data_free(struct hist_elt_data *elt_data)
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001830{
Tom Zanussi02205a62018-01-15 20:51:59 -06001831 unsigned int i;
1832
1833 for (i = 0; i < SYNTH_FIELDS_MAX; i++)
1834 kfree(elt_data->field_var_str[i]);
1835
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001836 kfree(elt_data->comm);
1837 kfree(elt_data);
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001838}
1839
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001840static void hist_trigger_elt_data_free(struct tracing_map_elt *elt)
1841{
1842 struct hist_elt_data *elt_data = elt->private_data;
1843
1844 hist_elt_data_free(elt_data);
1845}
1846
1847static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt)
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001848{
1849 struct hist_trigger_data *hist_data = elt->map->private_data;
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001850 unsigned int size = TASK_COMM_LEN;
1851 struct hist_elt_data *elt_data;
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001852 struct hist_field *key_field;
Tom Zanussi02205a62018-01-15 20:51:59 -06001853 unsigned int i, n_str;
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001854
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001855 elt_data = kzalloc(sizeof(*elt_data), GFP_KERNEL);
1856 if (!elt_data)
1857 return -ENOMEM;
1858
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001859 for_each_hist_key_field(i, hist_data) {
1860 key_field = hist_data->fields[i];
1861
1862 if (key_field->flags & HIST_FIELD_FL_EXECNAME) {
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001863 elt_data->comm = kzalloc(size, GFP_KERNEL);
1864 if (!elt_data->comm) {
1865 kfree(elt_data);
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001866 return -ENOMEM;
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001867 }
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001868 break;
1869 }
1870 }
1871
Tom Zanussi02205a62018-01-15 20:51:59 -06001872 n_str = hist_data->n_field_var_str;
1873
1874 size = STR_VAR_LEN_MAX;
1875
1876 for (i = 0; i < n_str; i++) {
1877 elt_data->field_var_str[i] = kzalloc(size, GFP_KERNEL);
1878 if (!elt_data->field_var_str[i]) {
1879 hist_elt_data_free(elt_data);
1880 return -ENOMEM;
1881 }
1882 }
1883
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001884 elt->private_data = elt_data;
1885
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001886 return 0;
1887}
1888
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001889static void hist_trigger_elt_data_init(struct tracing_map_elt *elt)
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001890{
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001891 struct hist_elt_data *elt_data = elt->private_data;
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001892
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001893 if (elt_data->comm)
1894 save_comm(elt_data->comm, current);
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001895}
1896
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06001897static const struct tracing_map_ops hist_trigger_elt_data_ops = {
1898 .elt_alloc = hist_trigger_elt_data_alloc,
1899 .elt_free = hist_trigger_elt_data_free,
1900 .elt_init = hist_trigger_elt_data_init,
Tom Zanussi6b4827a2016-03-03 12:54:50 -06001901};
1902
Tom Zanussi2ece94f2018-01-15 20:51:51 -06001903static const char *get_hist_field_flags(struct hist_field *hist_field)
1904{
1905 const char *flags_str = NULL;
1906
1907 if (hist_field->flags & HIST_FIELD_FL_HEX)
1908 flags_str = "hex";
1909 else if (hist_field->flags & HIST_FIELD_FL_SYM)
1910 flags_str = "sym";
1911 else if (hist_field->flags & HIST_FIELD_FL_SYM_OFFSET)
1912 flags_str = "sym-offset";
1913 else if (hist_field->flags & HIST_FIELD_FL_EXECNAME)
1914 flags_str = "execname";
1915 else if (hist_field->flags & HIST_FIELD_FL_SYSCALL)
1916 flags_str = "syscall";
1917 else if (hist_field->flags & HIST_FIELD_FL_LOG2)
1918 flags_str = "log2";
1919 else if (hist_field->flags & HIST_FIELD_FL_TIMESTAMP_USECS)
1920 flags_str = "usecs";
1921
1922 return flags_str;
1923}
1924
Tom Zanussi100719d2018-01-15 20:51:52 -06001925static void expr_field_str(struct hist_field *field, char *expr)
1926{
Tom Zanussi067fe032018-01-15 20:51:56 -06001927 if (field->flags & HIST_FIELD_FL_VAR_REF)
1928 strcat(expr, "$");
1929
Tom Zanussi100719d2018-01-15 20:51:52 -06001930 strcat(expr, hist_field_name(field, 0));
1931
1932 if (field->flags) {
1933 const char *flags_str = get_hist_field_flags(field);
1934
1935 if (flags_str) {
1936 strcat(expr, ".");
1937 strcat(expr, flags_str);
1938 }
1939 }
1940}
1941
1942static char *expr_str(struct hist_field *field, unsigned int level)
1943{
1944 char *expr;
1945
1946 if (level > 1)
1947 return NULL;
1948
1949 expr = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
1950 if (!expr)
1951 return NULL;
1952
1953 if (!field->operands[0]) {
1954 expr_field_str(field, expr);
1955 return expr;
1956 }
1957
1958 if (field->operator == FIELD_OP_UNARY_MINUS) {
1959 char *subexpr;
1960
1961 strcat(expr, "-(");
1962 subexpr = expr_str(field->operands[0], ++level);
1963 if (!subexpr) {
1964 kfree(expr);
1965 return NULL;
1966 }
1967 strcat(expr, subexpr);
1968 strcat(expr, ")");
1969
1970 kfree(subexpr);
1971
1972 return expr;
1973 }
1974
1975 expr_field_str(field->operands[0], expr);
1976
1977 switch (field->operator) {
1978 case FIELD_OP_MINUS:
1979 strcat(expr, "-");
1980 break;
1981 case FIELD_OP_PLUS:
1982 strcat(expr, "+");
1983 break;
1984 default:
1985 kfree(expr);
1986 return NULL;
1987 }
1988
1989 expr_field_str(field->operands[1], expr);
1990
1991 return expr;
1992}
1993
1994static int contains_operator(char *str)
1995{
1996 enum field_op_id field_op = FIELD_OP_NONE;
1997 char *op;
1998
1999 op = strpbrk(str, "+-");
2000 if (!op)
2001 return FIELD_OP_NONE;
2002
2003 switch (*op) {
2004 case '-':
2005 if (*str == '-')
2006 field_op = FIELD_OP_UNARY_MINUS;
2007 else
2008 field_op = FIELD_OP_MINUS;
2009 break;
2010 case '+':
2011 field_op = FIELD_OP_PLUS;
2012 break;
2013 default:
2014 break;
2015 }
2016
2017 return field_op;
2018}
2019
Tom Zanussi5819ead2017-09-22 14:58:23 -05002020static void destroy_hist_field(struct hist_field *hist_field,
2021 unsigned int level)
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002022{
Tom Zanussi5819ead2017-09-22 14:58:23 -05002023 unsigned int i;
2024
Tom Zanussi100719d2018-01-15 20:51:52 -06002025 if (level > 3)
Tom Zanussi5819ead2017-09-22 14:58:23 -05002026 return;
2027
2028 if (!hist_field)
2029 return;
2030
2031 for (i = 0; i < HIST_FIELD_OPERANDS_MAX; i++)
2032 destroy_hist_field(hist_field->operands[i], level + 1);
2033
Tom Zanussi30350d62018-01-15 20:51:49 -06002034 kfree(hist_field->var.name);
Tom Zanussi100719d2018-01-15 20:51:52 -06002035 kfree(hist_field->name);
Tom Zanussi19a9fac2018-01-15 20:51:55 -06002036 kfree(hist_field->type);
Tom Zanussi30350d62018-01-15 20:51:49 -06002037
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002038 kfree(hist_field);
2039}
2040
Tom Zanussib559d003a2018-01-15 20:51:47 -06002041static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data,
2042 struct ftrace_event_field *field,
Tom Zanussi30350d62018-01-15 20:51:49 -06002043 unsigned long flags,
2044 char *var_name)
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002045{
2046 struct hist_field *hist_field;
2047
2048 if (field && is_function_field(field))
2049 return NULL;
2050
2051 hist_field = kzalloc(sizeof(struct hist_field), GFP_KERNEL);
2052 if (!hist_field)
2053 return NULL;
2054
Tom Zanussib559d003a2018-01-15 20:51:47 -06002055 hist_field->hist_data = hist_data;
2056
Tom Zanussi100719d2018-01-15 20:51:52 -06002057 if (flags & HIST_FIELD_FL_EXPR)
2058 goto out; /* caller will populate */
2059
Tom Zanussi067fe032018-01-15 20:51:56 -06002060 if (flags & HIST_FIELD_FL_VAR_REF) {
2061 hist_field->fn = hist_field_var_ref;
2062 goto out;
2063 }
2064
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002065 if (flags & HIST_FIELD_FL_HITCOUNT) {
2066 hist_field->fn = hist_field_counter;
Tom Zanussi19a9fac2018-01-15 20:51:55 -06002067 hist_field->size = sizeof(u64);
2068 hist_field->type = kstrdup("u64", GFP_KERNEL);
2069 if (!hist_field->type)
2070 goto free;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002071 goto out;
2072 }
2073
Tom Zanussi69a02002016-03-03 12:54:52 -06002074 if (flags & HIST_FIELD_FL_STACKTRACE) {
2075 hist_field->fn = hist_field_none;
2076 goto out;
2077 }
2078
Namhyung Kim4b94f5b2016-03-03 12:55:02 -06002079 if (flags & HIST_FIELD_FL_LOG2) {
Tom Zanussi5819ead2017-09-22 14:58:23 -05002080 unsigned long fl = flags & ~HIST_FIELD_FL_LOG2;
Namhyung Kim4b94f5b2016-03-03 12:55:02 -06002081 hist_field->fn = hist_field_log2;
Tom Zanussi30350d62018-01-15 20:51:49 -06002082 hist_field->operands[0] = create_hist_field(hist_data, field, fl, NULL);
Tom Zanussi5819ead2017-09-22 14:58:23 -05002083 hist_field->size = hist_field->operands[0]->size;
Tom Zanussi19a9fac2018-01-15 20:51:55 -06002084 hist_field->type = kstrdup(hist_field->operands[0]->type, GFP_KERNEL);
2085 if (!hist_field->type)
2086 goto free;
Namhyung Kim4b94f5b2016-03-03 12:55:02 -06002087 goto out;
2088 }
2089
Tom Zanussiad42feb2018-01-15 20:51:45 -06002090 if (flags & HIST_FIELD_FL_TIMESTAMP) {
2091 hist_field->fn = hist_field_timestamp;
2092 hist_field->size = sizeof(u64);
Tom Zanussi19a9fac2018-01-15 20:51:55 -06002093 hist_field->type = kstrdup("u64", GFP_KERNEL);
2094 if (!hist_field->type)
2095 goto free;
Tom Zanussiad42feb2018-01-15 20:51:45 -06002096 goto out;
2097 }
2098
Tom Zanussi432480c2016-04-25 14:01:27 -05002099 if (WARN_ON_ONCE(!field))
2100 goto out;
2101
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002102 if (is_string_field(field)) {
2103 flags |= HIST_FIELD_FL_STRING;
Namhyung Kim79e577c2016-03-03 12:54:53 -06002104
Tom Zanussi19a9fac2018-01-15 20:51:55 -06002105 hist_field->size = MAX_FILTER_STR_VAL;
2106 hist_field->type = kstrdup(field->type, GFP_KERNEL);
2107 if (!hist_field->type)
2108 goto free;
2109
Namhyung Kim79e577c2016-03-03 12:54:53 -06002110 if (field->filter_type == FILTER_STATIC_STRING)
2111 hist_field->fn = hist_field_string;
2112 else if (field->filter_type == FILTER_DYN_STRING)
2113 hist_field->fn = hist_field_dynstring;
2114 else
2115 hist_field->fn = hist_field_pstring;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002116 } else {
Tom Zanussi19a9fac2018-01-15 20:51:55 -06002117 hist_field->size = field->size;
2118 hist_field->is_signed = field->is_signed;
2119 hist_field->type = kstrdup(field->type, GFP_KERNEL);
2120 if (!hist_field->type)
2121 goto free;
2122
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002123 hist_field->fn = select_value_fn(field->size,
2124 field->is_signed);
2125 if (!hist_field->fn) {
Tom Zanussi5819ead2017-09-22 14:58:23 -05002126 destroy_hist_field(hist_field, 0);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002127 return NULL;
2128 }
2129 }
2130 out:
2131 hist_field->field = field;
2132 hist_field->flags = flags;
2133
Tom Zanussi30350d62018-01-15 20:51:49 -06002134 if (var_name) {
2135 hist_field->var.name = kstrdup(var_name, GFP_KERNEL);
2136 if (!hist_field->var.name)
2137 goto free;
2138 }
2139
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002140 return hist_field;
Tom Zanussi30350d62018-01-15 20:51:49 -06002141 free:
2142 destroy_hist_field(hist_field, 0);
2143 return NULL;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002144}
2145
2146static void destroy_hist_fields(struct hist_trigger_data *hist_data)
2147{
2148 unsigned int i;
2149
Tom Zanussi30350d62018-01-15 20:51:49 -06002150 for (i = 0; i < HIST_FIELDS_MAX; i++) {
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002151 if (hist_data->fields[i]) {
Tom Zanussi5819ead2017-09-22 14:58:23 -05002152 destroy_hist_field(hist_data->fields[i], 0);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06002153 hist_data->fields[i] = NULL;
2154 }
2155 }
2156}
2157
Tom Zanussi067fe032018-01-15 20:51:56 -06002158static int init_var_ref(struct hist_field *ref_field,
2159 struct hist_field *var_field,
2160 char *system, char *event_name)
2161{
2162 int err = 0;
2163
2164 ref_field->var.idx = var_field->var.idx;
2165 ref_field->var.hist_data = var_field->hist_data;
2166 ref_field->size = var_field->size;
2167 ref_field->is_signed = var_field->is_signed;
2168 ref_field->flags |= var_field->flags &
2169 (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
2170
2171 if (system) {
2172 ref_field->system = kstrdup(system, GFP_KERNEL);
2173 if (!ref_field->system)
2174 return -ENOMEM;
2175 }
2176
2177 if (event_name) {
2178 ref_field->event_name = kstrdup(event_name, GFP_KERNEL);
2179 if (!ref_field->event_name) {
2180 err = -ENOMEM;
2181 goto free;
2182 }
2183 }
2184
2185 ref_field->name = kstrdup(var_field->var.name, GFP_KERNEL);
2186 if (!ref_field->name) {
2187 err = -ENOMEM;
2188 goto free;
2189 }
2190
2191 ref_field->type = kstrdup(var_field->type, GFP_KERNEL);
2192 if (!ref_field->type) {
2193 err = -ENOMEM;
2194 goto free;
2195 }
2196 out:
2197 return err;
2198 free:
2199 kfree(ref_field->system);
2200 kfree(ref_field->event_name);
2201 kfree(ref_field->name);
2202
2203 goto out;
2204}
2205
2206static struct hist_field *create_var_ref(struct hist_field *var_field,
2207 char *system, char *event_name)
2208{
2209 unsigned long flags = HIST_FIELD_FL_VAR_REF;
2210 struct hist_field *ref_field;
2211
2212 ref_field = create_hist_field(var_field->hist_data, NULL, flags, NULL);
2213 if (ref_field) {
2214 if (init_var_ref(ref_field, var_field, system, event_name)) {
2215 destroy_hist_field(ref_field, 0);
2216 return NULL;
2217 }
2218 }
2219
2220 return ref_field;
2221}
2222
2223static bool is_var_ref(char *var_name)
2224{
2225 if (!var_name || strlen(var_name) < 2 || var_name[0] != '$')
2226 return false;
2227
2228 return true;
2229}
2230
2231static char *field_name_from_var(struct hist_trigger_data *hist_data,
2232 char *var_name)
2233{
2234 char *name, *field;
2235 unsigned int i;
2236
2237 for (i = 0; i < hist_data->attrs->var_defs.n_vars; i++) {
2238 name = hist_data->attrs->var_defs.name[i];
2239
2240 if (strcmp(var_name, name) == 0) {
2241 field = hist_data->attrs->var_defs.expr[i];
2242 if (contains_operator(field) || is_var_ref(field))
2243 continue;
2244 return field;
2245 }
2246 }
2247
2248 return NULL;
2249}
2250
2251static char *local_field_var_ref(struct hist_trigger_data *hist_data,
2252 char *system, char *event_name,
2253 char *var_name)
2254{
2255 struct trace_event_call *call;
2256
2257 if (system && event_name) {
2258 call = hist_data->event_file->event_call;
2259
2260 if (strcmp(system, call->class->system) != 0)
2261 return NULL;
2262
2263 if (strcmp(event_name, trace_event_name(call)) != 0)
2264 return NULL;
2265 }
2266
2267 if (!!system != !!event_name)
2268 return NULL;
2269
2270 if (!is_var_ref(var_name))
2271 return NULL;
2272
2273 var_name++;
2274
2275 return field_name_from_var(hist_data, var_name);
2276}
2277
2278static struct hist_field *parse_var_ref(struct hist_trigger_data *hist_data,
2279 char *system, char *event_name,
2280 char *var_name)
2281{
2282 struct hist_field *var_field = NULL, *ref_field = NULL;
2283
2284 if (!is_var_ref(var_name))
2285 return NULL;
2286
2287 var_name++;
2288
2289 var_field = find_event_var(hist_data, system, event_name, var_name);
2290 if (var_field)
2291 ref_field = create_var_ref(var_field, system, event_name);
2292
2293 return ref_field;
2294}
2295
Tom Zanussi100719d2018-01-15 20:51:52 -06002296static struct ftrace_event_field *
2297parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file,
2298 char *field_str, unsigned long *flags)
2299{
2300 struct ftrace_event_field *field = NULL;
2301 char *field_name, *modifier, *str;
2302
2303 modifier = str = kstrdup(field_str, GFP_KERNEL);
2304 if (!modifier)
2305 return ERR_PTR(-ENOMEM);
2306
2307 field_name = strsep(&modifier, ".");
2308 if (modifier) {
2309 if (strcmp(modifier, "hex") == 0)
2310 *flags |= HIST_FIELD_FL_HEX;
2311 else if (strcmp(modifier, "sym") == 0)
2312 *flags |= HIST_FIELD_FL_SYM;
2313 else if (strcmp(modifier, "sym-offset") == 0)
2314 *flags |= HIST_FIELD_FL_SYM_OFFSET;
2315 else if ((strcmp(modifier, "execname") == 0) &&
2316 (strcmp(field_name, "common_pid") == 0))
2317 *flags |= HIST_FIELD_FL_EXECNAME;
2318 else if (strcmp(modifier, "syscall") == 0)
2319 *flags |= HIST_FIELD_FL_SYSCALL;
2320 else if (strcmp(modifier, "log2") == 0)
2321 *flags |= HIST_FIELD_FL_LOG2;
2322 else if (strcmp(modifier, "usecs") == 0)
2323 *flags |= HIST_FIELD_FL_TIMESTAMP_USECS;
2324 else {
2325 field = ERR_PTR(-EINVAL);
2326 goto out;
2327 }
2328 }
2329
2330 if (strcmp(field_name, "common_timestamp") == 0) {
2331 *flags |= HIST_FIELD_FL_TIMESTAMP;
2332 hist_data->enable_timestamps = true;
2333 if (*flags & HIST_FIELD_FL_TIMESTAMP_USECS)
2334 hist_data->attrs->ts_in_usecs = true;
2335 } else {
2336 field = trace_find_event_field(file->event_call, field_name);
2337 if (!field || !field->size) {
2338 field = ERR_PTR(-EINVAL);
2339 goto out;
2340 }
2341 }
2342 out:
2343 kfree(str);
2344
2345 return field;
2346}
2347
2348static struct hist_field *parse_atom(struct hist_trigger_data *hist_data,
2349 struct trace_event_file *file, char *str,
2350 unsigned long *flags, char *var_name)
2351{
Tom Zanussi067fe032018-01-15 20:51:56 -06002352 char *s, *ref_system = NULL, *ref_event = NULL, *ref_var = str;
Tom Zanussi100719d2018-01-15 20:51:52 -06002353 struct ftrace_event_field *field = NULL;
2354 struct hist_field *hist_field = NULL;
2355 int ret = 0;
2356
Tom Zanussi067fe032018-01-15 20:51:56 -06002357 s = strchr(str, '.');
2358 if (s) {
2359 s = strchr(++s, '.');
2360 if (s) {
2361 ref_system = strsep(&str, ".");
2362 if (!str) {
2363 ret = -EINVAL;
2364 goto out;
2365 }
2366 ref_event = strsep(&str, ".");
2367 if (!str) {
2368 ret = -EINVAL;
2369 goto out;
2370 }
2371 ref_var = str;
2372 }
2373 }
2374
2375 s = local_field_var_ref(hist_data, ref_system, ref_event, ref_var);
2376 if (!s) {
2377 hist_field = parse_var_ref(hist_data, ref_system, ref_event, ref_var);
2378 if (hist_field) {
2379 hist_data->var_refs[hist_data->n_var_refs] = hist_field;
2380 hist_field->var_ref_idx = hist_data->n_var_refs++;
2381 return hist_field;
2382 }
2383 } else
2384 str = s;
2385
Tom Zanussi100719d2018-01-15 20:51:52 -06002386 field = parse_field(hist_data, file, str, flags);
2387 if (IS_ERR(field)) {
2388 ret = PTR_ERR(field);
2389 goto out;
2390 }
2391
2392 hist_field = create_hist_field(hist_data, field, *flags, var_name);
2393 if (!hist_field) {
2394 ret = -ENOMEM;
2395 goto out;
2396 }
2397
2398 return hist_field;
2399 out:
2400 return ERR_PTR(ret);
2401}
2402
2403static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
2404 struct trace_event_file *file,
2405 char *str, unsigned long flags,
2406 char *var_name, unsigned int level);
2407
2408static struct hist_field *parse_unary(struct hist_trigger_data *hist_data,
2409 struct trace_event_file *file,
2410 char *str, unsigned long flags,
2411 char *var_name, unsigned int level)
2412{
2413 struct hist_field *operand1, *expr = NULL;
2414 unsigned long operand_flags;
2415 int ret = 0;
2416 char *s;
2417
2418 /* we support only -(xxx) i.e. explicit parens required */
2419
2420 if (level > 3) {
2421 ret = -EINVAL;
2422 goto free;
2423 }
2424
2425 str++; /* skip leading '-' */
2426
2427 s = strchr(str, '(');
2428 if (s)
2429 str++;
2430 else {
2431 ret = -EINVAL;
2432 goto free;
2433 }
2434
2435 s = strrchr(str, ')');
2436 if (s)
2437 *s = '\0';
2438 else {
2439 ret = -EINVAL; /* no closing ')' */
2440 goto free;
2441 }
2442
2443 flags |= HIST_FIELD_FL_EXPR;
2444 expr = create_hist_field(hist_data, NULL, flags, var_name);
2445 if (!expr) {
2446 ret = -ENOMEM;
2447 goto free;
2448 }
2449
2450 operand_flags = 0;
2451 operand1 = parse_expr(hist_data, file, str, operand_flags, NULL, ++level);
2452 if (IS_ERR(operand1)) {
2453 ret = PTR_ERR(operand1);
2454 goto free;
2455 }
2456
2457 expr->flags |= operand1->flags &
2458 (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
2459 expr->fn = hist_field_unary_minus;
2460 expr->operands[0] = operand1;
2461 expr->operator = FIELD_OP_UNARY_MINUS;
2462 expr->name = expr_str(expr, 0);
Tom Zanussi19a9fac2018-01-15 20:51:55 -06002463 expr->type = kstrdup(operand1->type, GFP_KERNEL);
2464 if (!expr->type) {
2465 ret = -ENOMEM;
2466 goto free;
2467 }
Tom Zanussi100719d2018-01-15 20:51:52 -06002468
2469 return expr;
2470 free:
2471 destroy_hist_field(expr, 0);
2472 return ERR_PTR(ret);
2473}
2474
2475static int check_expr_operands(struct hist_field *operand1,
2476 struct hist_field *operand2)
2477{
2478 unsigned long operand1_flags = operand1->flags;
2479 unsigned long operand2_flags = operand2->flags;
2480
2481 if ((operand1_flags & HIST_FIELD_FL_TIMESTAMP_USECS) !=
2482 (operand2_flags & HIST_FIELD_FL_TIMESTAMP_USECS))
2483 return -EINVAL;
2484
2485 return 0;
2486}
2487
2488static struct hist_field *parse_expr(struct hist_trigger_data *hist_data,
2489 struct trace_event_file *file,
2490 char *str, unsigned long flags,
2491 char *var_name, unsigned int level)
2492{
2493 struct hist_field *operand1 = NULL, *operand2 = NULL, *expr = NULL;
2494 unsigned long operand_flags;
2495 int field_op, ret = -EINVAL;
2496 char *sep, *operand1_str;
2497
2498 if (level > 3)
2499 return ERR_PTR(-EINVAL);
2500
2501 field_op = contains_operator(str);
2502
2503 if (field_op == FIELD_OP_NONE)
2504 return parse_atom(hist_data, file, str, &flags, var_name);
2505
2506 if (field_op == FIELD_OP_UNARY_MINUS)
2507 return parse_unary(hist_data, file, str, flags, var_name, ++level);
2508
2509 switch (field_op) {
2510 case FIELD_OP_MINUS:
2511 sep = "-";
2512 break;
2513 case FIELD_OP_PLUS:
2514 sep = "+";
2515 break;
2516 default:
2517 goto free;
2518 }
2519
2520 operand1_str = strsep(&str, sep);
2521 if (!operand1_str || !str)
2522 goto free;
2523
2524 operand_flags = 0;
2525 operand1 = parse_atom(hist_data, file, operand1_str,
2526 &operand_flags, NULL);
2527 if (IS_ERR(operand1)) {
2528 ret = PTR_ERR(operand1);
2529 operand1 = NULL;
2530 goto free;
2531 }
2532
2533 /* rest of string could be another expression e.g. b+c in a+b+c */
2534 operand_flags = 0;
2535 operand2 = parse_expr(hist_data, file, str, operand_flags, NULL, ++level);
2536 if (IS_ERR(operand2)) {
2537 ret = PTR_ERR(operand2);
2538 operand2 = NULL;
2539 goto free;
2540 }
2541
2542 ret = check_expr_operands(operand1, operand2);
2543 if (ret)
2544 goto free;
2545
2546 flags |= HIST_FIELD_FL_EXPR;
2547
2548 flags |= operand1->flags &
2549 (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS);
2550
2551 expr = create_hist_field(hist_data, NULL, flags, var_name);
2552 if (!expr) {
2553 ret = -ENOMEM;
2554 goto free;
2555 }
2556
Tom Zanussi067fe032018-01-15 20:51:56 -06002557 operand1->read_once = true;
2558 operand2->read_once = true;
2559
Tom Zanussi100719d2018-01-15 20:51:52 -06002560 expr->operands[0] = operand1;
2561 expr->operands[1] = operand2;
2562 expr->operator = field_op;
2563 expr->name = expr_str(expr, 0);
Tom Zanussi19a9fac2018-01-15 20:51:55 -06002564 expr->type = kstrdup(operand1->type, GFP_KERNEL);
2565 if (!expr->type) {
2566 ret = -ENOMEM;
2567 goto free;
2568 }
Tom Zanussi100719d2018-01-15 20:51:52 -06002569
2570 switch (field_op) {
2571 case FIELD_OP_MINUS:
2572 expr->fn = hist_field_minus;
2573 break;
2574 case FIELD_OP_PLUS:
2575 expr->fn = hist_field_plus;
2576 break;
2577 default:
2578 goto free;
2579 }
2580
2581 return expr;
2582 free:
2583 destroy_hist_field(operand1, 0);
2584 destroy_hist_field(operand2, 0);
2585 destroy_hist_field(expr, 0);
2586
2587 return ERR_PTR(ret);
2588}
2589
Tom Zanussi02205a62018-01-15 20:51:59 -06002590static char *find_trigger_filter(struct hist_trigger_data *hist_data,
2591 struct trace_event_file *file)
2592{
2593 struct event_trigger_data *test;
2594
2595 list_for_each_entry_rcu(test, &file->triggers, list) {
2596 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
2597 if (test->private_data == hist_data)
2598 return test->filter_str;
2599 }
2600 }
2601
2602 return NULL;
2603}
2604
2605static struct event_command trigger_hist_cmd;
2606static int event_hist_trigger_func(struct event_command *cmd_ops,
2607 struct trace_event_file *file,
2608 char *glob, char *cmd, char *param);
2609
2610static bool compatible_keys(struct hist_trigger_data *target_hist_data,
2611 struct hist_trigger_data *hist_data,
2612 unsigned int n_keys)
2613{
2614 struct hist_field *target_hist_field, *hist_field;
2615 unsigned int n, i, j;
2616
2617 if (hist_data->n_fields - hist_data->n_vals != n_keys)
2618 return false;
2619
2620 i = hist_data->n_vals;
2621 j = target_hist_data->n_vals;
2622
2623 for (n = 0; n < n_keys; n++) {
2624 hist_field = hist_data->fields[i + n];
2625 target_hist_field = target_hist_data->fields[j + n];
2626
2627 if (strcmp(hist_field->type, target_hist_field->type) != 0)
2628 return false;
2629 if (hist_field->size != target_hist_field->size)
2630 return false;
2631 if (hist_field->is_signed != target_hist_field->is_signed)
2632 return false;
2633 }
2634
2635 return true;
2636}
2637
2638static struct hist_trigger_data *
2639find_compatible_hist(struct hist_trigger_data *target_hist_data,
2640 struct trace_event_file *file)
2641{
2642 struct hist_trigger_data *hist_data;
2643 struct event_trigger_data *test;
2644 unsigned int n_keys;
2645
2646 n_keys = target_hist_data->n_fields - target_hist_data->n_vals;
2647
2648 list_for_each_entry_rcu(test, &file->triggers, list) {
2649 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
2650 hist_data = test->private_data;
2651
2652 if (compatible_keys(target_hist_data, hist_data, n_keys))
2653 return hist_data;
2654 }
2655 }
2656
2657 return NULL;
2658}
2659
2660static struct trace_event_file *event_file(struct trace_array *tr,
2661 char *system, char *event_name)
2662{
2663 struct trace_event_file *file;
2664
2665 file = find_event_file(tr, system, event_name);
2666 if (!file)
2667 return ERR_PTR(-EINVAL);
2668
2669 return file;
2670}
2671
2672static struct hist_field *
2673find_synthetic_field_var(struct hist_trigger_data *target_hist_data,
2674 char *system, char *event_name, char *field_name)
2675{
2676 struct hist_field *event_var;
2677 char *synthetic_name;
2678
2679 synthetic_name = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
2680 if (!synthetic_name)
2681 return ERR_PTR(-ENOMEM);
2682
2683 strcpy(synthetic_name, "synthetic_");
2684 strcat(synthetic_name, field_name);
2685
2686 event_var = find_event_var(target_hist_data, system, event_name, synthetic_name);
2687
2688 kfree(synthetic_name);
2689
2690 return event_var;
2691}
2692
2693/**
2694 * create_field_var_hist - Automatically create a histogram and var for a field
2695 * @target_hist_data: The target hist trigger
2696 * @subsys_name: Optional subsystem name
2697 * @event_name: Optional event name
2698 * @field_name: The name of the field (and the resulting variable)
2699 *
2700 * Hist trigger actions fetch data from variables, not directly from
2701 * events. However, for convenience, users are allowed to directly
2702 * specify an event field in an action, which will be automatically
2703 * converted into a variable on their behalf.
2704
2705 * If a user specifies a field on an event that isn't the event the
2706 * histogram currently being defined (the target event histogram), the
2707 * only way that can be accomplished is if a new hist trigger is
2708 * created and the field variable defined on that.
2709 *
2710 * This function creates a new histogram compatible with the target
2711 * event (meaning a histogram with the same key as the target
2712 * histogram), and creates a variable for the specified field, but
2713 * with 'synthetic_' prepended to the variable name in order to avoid
2714 * collision with normal field variables.
2715 *
2716 * Return: The variable created for the field.
2717 */
Tom Zanussic282a382018-01-15 20:52:00 -06002718static struct hist_field *
Tom Zanussi02205a62018-01-15 20:51:59 -06002719create_field_var_hist(struct hist_trigger_data *target_hist_data,
2720 char *subsys_name, char *event_name, char *field_name)
2721{
2722 struct trace_array *tr = target_hist_data->event_file->tr;
2723 struct hist_field *event_var = ERR_PTR(-EINVAL);
2724 struct hist_trigger_data *hist_data;
2725 unsigned int i, n, first = true;
2726 struct field_var_hist *var_hist;
2727 struct trace_event_file *file;
2728 struct hist_field *key_field;
2729 char *saved_filter;
2730 char *cmd;
2731 int ret;
2732
2733 if (target_hist_data->n_field_var_hists >= SYNTH_FIELDS_MAX)
2734 return ERR_PTR(-EINVAL);
2735
2736 file = event_file(tr, subsys_name, event_name);
2737
2738 if (IS_ERR(file)) {
2739 ret = PTR_ERR(file);
2740 return ERR_PTR(ret);
2741 }
2742
2743 /*
2744 * Look for a histogram compatible with target. We'll use the
2745 * found histogram specification to create a new matching
2746 * histogram with our variable on it. target_hist_data is not
2747 * yet a registered histogram so we can't use that.
2748 */
2749 hist_data = find_compatible_hist(target_hist_data, file);
2750 if (!hist_data)
2751 return ERR_PTR(-EINVAL);
2752
2753 /* See if a synthetic field variable has already been created */
2754 event_var = find_synthetic_field_var(target_hist_data, subsys_name,
2755 event_name, field_name);
2756 if (!IS_ERR_OR_NULL(event_var))
2757 return event_var;
2758
2759 var_hist = kzalloc(sizeof(*var_hist), GFP_KERNEL);
2760 if (!var_hist)
2761 return ERR_PTR(-ENOMEM);
2762
2763 cmd = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
2764 if (!cmd) {
2765 kfree(var_hist);
2766 return ERR_PTR(-ENOMEM);
2767 }
2768
2769 /* Use the same keys as the compatible histogram */
2770 strcat(cmd, "keys=");
2771
2772 for_each_hist_key_field(i, hist_data) {
2773 key_field = hist_data->fields[i];
2774 if (!first)
2775 strcat(cmd, ",");
2776 strcat(cmd, key_field->field->name);
2777 first = false;
2778 }
2779
2780 /* Create the synthetic field variable specification */
2781 strcat(cmd, ":synthetic_");
2782 strcat(cmd, field_name);
2783 strcat(cmd, "=");
2784 strcat(cmd, field_name);
2785
2786 /* Use the same filter as the compatible histogram */
2787 saved_filter = find_trigger_filter(hist_data, file);
2788 if (saved_filter) {
2789 strcat(cmd, " if ");
2790 strcat(cmd, saved_filter);
2791 }
2792
2793 var_hist->cmd = kstrdup(cmd, GFP_KERNEL);
2794 if (!var_hist->cmd) {
2795 kfree(cmd);
2796 kfree(var_hist);
2797 return ERR_PTR(-ENOMEM);
2798 }
2799
2800 /* Save the compatible histogram information */
2801 var_hist->hist_data = hist_data;
2802
2803 /* Create the new histogram with our variable */
2804 ret = event_hist_trigger_func(&trigger_hist_cmd, file,
2805 "", "hist", cmd);
2806 if (ret) {
2807 kfree(cmd);
2808 kfree(var_hist->cmd);
2809 kfree(var_hist);
2810 return ERR_PTR(ret);
2811 }
2812
2813 kfree(cmd);
2814
2815 /* If we can't find the variable, something went wrong */
2816 event_var = find_synthetic_field_var(target_hist_data, subsys_name,
2817 event_name, field_name);
2818 if (IS_ERR_OR_NULL(event_var)) {
2819 kfree(var_hist->cmd);
2820 kfree(var_hist);
2821 return ERR_PTR(-EINVAL);
2822 }
2823
2824 n = target_hist_data->n_field_var_hists;
2825 target_hist_data->field_var_hists[n] = var_hist;
2826 target_hist_data->n_field_var_hists++;
2827
2828 return event_var;
2829}
2830
Tom Zanussic282a382018-01-15 20:52:00 -06002831static struct hist_field *
Tom Zanussi02205a62018-01-15 20:51:59 -06002832find_target_event_var(struct hist_trigger_data *hist_data,
2833 char *subsys_name, char *event_name, char *var_name)
2834{
2835 struct trace_event_file *file = hist_data->event_file;
2836 struct hist_field *hist_field = NULL;
2837
2838 if (subsys_name) {
2839 struct trace_event_call *call;
2840
2841 if (!event_name)
2842 return NULL;
2843
2844 call = file->event_call;
2845
2846 if (strcmp(subsys_name, call->class->system) != 0)
2847 return NULL;
2848
2849 if (strcmp(event_name, trace_event_name(call)) != 0)
2850 return NULL;
2851 }
2852
2853 hist_field = find_var_field(hist_data, var_name);
2854
2855 return hist_field;
2856}
2857
2858static inline void __update_field_vars(struct tracing_map_elt *elt,
2859 struct ring_buffer_event *rbe,
2860 void *rec,
2861 struct field_var **field_vars,
2862 unsigned int n_field_vars,
2863 unsigned int field_var_str_start)
2864{
2865 struct hist_elt_data *elt_data = elt->private_data;
2866 unsigned int i, j, var_idx;
2867 u64 var_val;
2868
2869 for (i = 0, j = field_var_str_start; i < n_field_vars; i++) {
2870 struct field_var *field_var = field_vars[i];
2871 struct hist_field *var = field_var->var;
2872 struct hist_field *val = field_var->val;
2873
2874 var_val = val->fn(val, elt, rbe, rec);
2875 var_idx = var->var.idx;
2876
2877 if (val->flags & HIST_FIELD_FL_STRING) {
2878 char *str = elt_data->field_var_str[j++];
2879 char *val_str = (char *)(uintptr_t)var_val;
2880
2881 strncpy(str, val_str, STR_VAR_LEN_MAX);
2882 var_val = (u64)(uintptr_t)str;
2883 }
2884 tracing_map_set_var(elt, var_idx, var_val);
2885 }
2886}
2887
2888static void update_field_vars(struct hist_trigger_data *hist_data,
2889 struct tracing_map_elt *elt,
2890 struct ring_buffer_event *rbe,
2891 void *rec)
2892{
2893 __update_field_vars(elt, rbe, rec, hist_data->field_vars,
2894 hist_data->n_field_vars, 0);
2895}
2896
2897static struct hist_field *create_var(struct hist_trigger_data *hist_data,
2898 struct trace_event_file *file,
2899 char *name, int size, const char *type)
2900{
2901 struct hist_field *var;
2902 int idx;
2903
2904 if (find_var(hist_data, file, name) && !hist_data->remove) {
2905 var = ERR_PTR(-EINVAL);
2906 goto out;
2907 }
2908
2909 var = kzalloc(sizeof(struct hist_field), GFP_KERNEL);
2910 if (!var) {
2911 var = ERR_PTR(-ENOMEM);
2912 goto out;
2913 }
2914
2915 idx = tracing_map_add_var(hist_data->map);
2916 if (idx < 0) {
2917 kfree(var);
2918 var = ERR_PTR(-EINVAL);
2919 goto out;
2920 }
2921
2922 var->flags = HIST_FIELD_FL_VAR;
2923 var->var.idx = idx;
2924 var->var.hist_data = var->hist_data = hist_data;
2925 var->size = size;
2926 var->var.name = kstrdup(name, GFP_KERNEL);
2927 var->type = kstrdup(type, GFP_KERNEL);
2928 if (!var->var.name || !var->type) {
2929 kfree(var->var.name);
2930 kfree(var->type);
2931 kfree(var);
2932 var = ERR_PTR(-ENOMEM);
2933 }
2934 out:
2935 return var;
2936}
2937
2938static struct field_var *create_field_var(struct hist_trigger_data *hist_data,
2939 struct trace_event_file *file,
2940 char *field_name)
2941{
2942 struct hist_field *val = NULL, *var = NULL;
2943 unsigned long flags = HIST_FIELD_FL_VAR;
2944 struct field_var *field_var;
2945 int ret = 0;
2946
2947 if (hist_data->n_field_vars >= SYNTH_FIELDS_MAX) {
2948 ret = -EINVAL;
2949 goto err;
2950 }
2951
2952 val = parse_atom(hist_data, file, field_name, &flags, NULL);
2953 if (IS_ERR(val)) {
2954 ret = PTR_ERR(val);
2955 goto err;
2956 }
2957
2958 var = create_var(hist_data, file, field_name, val->size, val->type);
2959 if (IS_ERR(var)) {
2960 kfree(val);
2961 ret = PTR_ERR(var);
2962 goto err;
2963 }
2964
2965 field_var = kzalloc(sizeof(struct field_var), GFP_KERNEL);
2966 if (!field_var) {
2967 kfree(val);
2968 kfree(var);
2969 ret = -ENOMEM;
2970 goto err;
2971 }
2972
2973 field_var->var = var;
2974 field_var->val = val;
2975 out:
2976 return field_var;
2977 err:
2978 field_var = ERR_PTR(ret);
2979 goto out;
2980}
2981
2982/**
2983 * create_target_field_var - Automatically create a variable for a field
2984 * @target_hist_data: The target hist trigger
2985 * @subsys_name: Optional subsystem name
2986 * @event_name: Optional event name
2987 * @var_name: The name of the field (and the resulting variable)
2988 *
2989 * Hist trigger actions fetch data from variables, not directly from
2990 * events. However, for convenience, users are allowed to directly
2991 * specify an event field in an action, which will be automatically
2992 * converted into a variable on their behalf.
2993
2994 * This function creates a field variable with the name var_name on
2995 * the hist trigger currently being defined on the target event. If
2996 * subsys_name and event_name are specified, this function simply
2997 * verifies that they do in fact match the target event subsystem and
2998 * event name.
2999 *
3000 * Return: The variable created for the field.
3001 */
Tom Zanussic282a382018-01-15 20:52:00 -06003002static struct field_var *
Tom Zanussi02205a62018-01-15 20:51:59 -06003003create_target_field_var(struct hist_trigger_data *target_hist_data,
3004 char *subsys_name, char *event_name, char *var_name)
3005{
3006 struct trace_event_file *file = target_hist_data->event_file;
3007
3008 if (subsys_name) {
3009 struct trace_event_call *call;
3010
3011 if (!event_name)
3012 return NULL;
3013
3014 call = file->event_call;
3015
3016 if (strcmp(subsys_name, call->class->system) != 0)
3017 return NULL;
3018
3019 if (strcmp(event_name, trace_event_name(call)) != 0)
3020 return NULL;
3021 }
3022
3023 return create_field_var(target_hist_data, file, var_name);
3024}
3025
Tom Zanussic282a382018-01-15 20:52:00 -06003026static void onmatch_destroy(struct action_data *data)
3027{
3028 unsigned int i;
3029
3030 mutex_lock(&synth_event_mutex);
3031
3032 kfree(data->onmatch.match_event);
3033 kfree(data->onmatch.match_event_system);
3034 kfree(data->onmatch.synth_event_name);
3035
3036 for (i = 0; i < data->n_params; i++)
3037 kfree(data->params[i]);
3038
3039 if (data->onmatch.synth_event)
3040 data->onmatch.synth_event->ref--;
3041
3042 kfree(data);
3043
3044 mutex_unlock(&synth_event_mutex);
3045}
3046
Tom Zanussi02205a62018-01-15 20:51:59 -06003047static void destroy_field_var(struct field_var *field_var)
3048{
3049 if (!field_var)
3050 return;
3051
3052 destroy_hist_field(field_var->var, 0);
3053 destroy_hist_field(field_var->val, 0);
3054
3055 kfree(field_var);
3056}
3057
3058static void destroy_field_vars(struct hist_trigger_data *hist_data)
3059{
3060 unsigned int i;
3061
3062 for (i = 0; i < hist_data->n_field_vars; i++)
3063 destroy_field_var(hist_data->field_vars[i]);
3064}
3065
Tom Zanussic282a382018-01-15 20:52:00 -06003066static void save_field_var(struct hist_trigger_data *hist_data,
3067 struct field_var *field_var)
Tom Zanussi02205a62018-01-15 20:51:59 -06003068{
3069 hist_data->field_vars[hist_data->n_field_vars++] = field_var;
3070
3071 if (field_var->val->flags & HIST_FIELD_FL_STRING)
3072 hist_data->n_field_var_str++;
3073}
3074
Tom Zanussic282a382018-01-15 20:52:00 -06003075
3076static void destroy_synth_var_refs(struct hist_trigger_data *hist_data)
3077{
3078 unsigned int i;
3079
3080 for (i = 0; i < hist_data->n_synth_var_refs; i++)
3081 destroy_hist_field(hist_data->synth_var_refs[i], 0);
3082}
3083
3084static void save_synth_var_ref(struct hist_trigger_data *hist_data,
3085 struct hist_field *var_ref)
3086{
3087 hist_data->synth_var_refs[hist_data->n_synth_var_refs++] = var_ref;
3088
3089 hist_data->var_refs[hist_data->n_var_refs] = var_ref;
3090 var_ref->var_ref_idx = hist_data->n_var_refs++;
3091}
3092
3093static int check_synth_field(struct synth_event *event,
3094 struct hist_field *hist_field,
3095 unsigned int field_pos)
3096{
3097 struct synth_field *field;
3098
3099 if (field_pos >= event->n_fields)
3100 return -EINVAL;
3101
3102 field = event->fields[field_pos];
3103
3104 if (strcmp(field->type, hist_field->type) != 0)
3105 return -EINVAL;
3106
3107 return 0;
3108}
3109
3110static int parse_action_params(char *params, struct action_data *data)
3111{
3112 char *param, *saved_param;
3113 int ret = 0;
3114
3115 while (params) {
3116 if (data->n_params >= SYNTH_FIELDS_MAX)
3117 goto out;
3118
3119 param = strsep(&params, ",");
3120 if (!param) {
3121 ret = -EINVAL;
3122 goto out;
3123 }
3124
3125 param = strstrip(param);
3126 if (strlen(param) < 2) {
3127 ret = -EINVAL;
3128 goto out;
3129 }
3130
3131 saved_param = kstrdup(param, GFP_KERNEL);
3132 if (!saved_param) {
3133 ret = -ENOMEM;
3134 goto out;
3135 }
3136
3137 data->params[data->n_params++] = saved_param;
3138 }
3139 out:
3140 return ret;
3141}
3142
3143static struct hist_field *
3144onmatch_find_var(struct hist_trigger_data *hist_data, struct action_data *data,
3145 char *system, char *event, char *var)
3146{
3147 struct hist_field *hist_field;
3148
3149 var++; /* skip '$' */
3150
3151 hist_field = find_target_event_var(hist_data, system, event, var);
3152 if (!hist_field) {
3153 if (!system) {
3154 system = data->onmatch.match_event_system;
3155 event = data->onmatch.match_event;
3156 }
3157
3158 hist_field = find_event_var(hist_data, system, event, var);
3159 }
3160
3161 return hist_field;
3162}
3163
3164static struct hist_field *
3165onmatch_create_field_var(struct hist_trigger_data *hist_data,
3166 struct action_data *data, char *system,
3167 char *event, char *var)
3168{
3169 struct hist_field *hist_field = NULL;
3170 struct field_var *field_var;
3171
3172 /*
3173 * First try to create a field var on the target event (the
3174 * currently being defined). This will create a variable for
3175 * unqualified fields on the target event, or if qualified,
3176 * target fields that have qualified names matching the target.
3177 */
3178 field_var = create_target_field_var(hist_data, system, event, var);
3179
3180 if (field_var && !IS_ERR(field_var)) {
3181 save_field_var(hist_data, field_var);
3182 hist_field = field_var->var;
3183 } else {
3184 field_var = NULL;
3185 /*
3186 * If no explicit system.event is specfied, default to
3187 * looking for fields on the onmatch(system.event.xxx)
3188 * event.
3189 */
3190 if (!system) {
3191 system = data->onmatch.match_event_system;
3192 event = data->onmatch.match_event;
3193 }
3194
3195 /*
3196 * At this point, we're looking at a field on another
3197 * event. Because we can't modify a hist trigger on
3198 * another event to add a variable for a field, we need
3199 * to create a new trigger on that event and create the
3200 * variable at the same time.
3201 */
3202 hist_field = create_field_var_hist(hist_data, system, event, var);
3203 if (IS_ERR(hist_field))
3204 goto free;
3205 }
3206 out:
3207 return hist_field;
3208 free:
3209 destroy_field_var(field_var);
3210 hist_field = NULL;
3211 goto out;
3212}
3213
3214static int onmatch_create(struct hist_trigger_data *hist_data,
3215 struct trace_event_file *file,
3216 struct action_data *data)
3217{
3218 char *event_name, *param, *system = NULL;
3219 struct hist_field *hist_field, *var_ref;
3220 unsigned int i, var_ref_idx;
3221 unsigned int field_pos = 0;
3222 struct synth_event *event;
3223 int ret = 0;
3224
3225 mutex_lock(&synth_event_mutex);
3226 event = find_synth_event(data->onmatch.synth_event_name);
3227 if (!event) {
3228 mutex_unlock(&synth_event_mutex);
3229 return -EINVAL;
3230 }
3231 event->ref++;
3232 mutex_unlock(&synth_event_mutex);
3233
3234 var_ref_idx = hist_data->n_var_refs;
3235
3236 for (i = 0; i < data->n_params; i++) {
3237 char *p;
3238
3239 p = param = kstrdup(data->params[i], GFP_KERNEL);
3240 if (!param) {
3241 ret = -ENOMEM;
3242 goto err;
3243 }
3244
3245 system = strsep(&param, ".");
3246 if (!param) {
3247 param = (char *)system;
3248 system = event_name = NULL;
3249 } else {
3250 event_name = strsep(&param, ".");
3251 if (!param) {
3252 kfree(p);
3253 ret = -EINVAL;
3254 goto err;
3255 }
3256 }
3257
3258 if (param[0] == '$')
3259 hist_field = onmatch_find_var(hist_data, data, system,
3260 event_name, param);
3261 else
3262 hist_field = onmatch_create_field_var(hist_data, data,
3263 system,
3264 event_name,
3265 param);
3266
3267 if (!hist_field) {
3268 kfree(p);
3269 ret = -EINVAL;
3270 goto err;
3271 }
3272
3273 if (check_synth_field(event, hist_field, field_pos) == 0) {
3274 var_ref = create_var_ref(hist_field, system, event_name);
3275 if (!var_ref) {
3276 kfree(p);
3277 ret = -ENOMEM;
3278 goto err;
3279 }
3280
3281 save_synth_var_ref(hist_data, var_ref);
3282 field_pos++;
3283 kfree(p);
3284 continue;
3285 }
3286
3287 kfree(p);
3288 ret = -EINVAL;
3289 goto err;
3290 }
3291
3292 if (field_pos != event->n_fields) {
3293 ret = -EINVAL;
3294 goto err;
3295 }
3296
3297 data->fn = action_trace;
3298 data->onmatch.synth_event = event;
3299 data->onmatch.var_ref_idx = var_ref_idx;
3300 out:
3301 return ret;
3302 err:
3303 mutex_lock(&synth_event_mutex);
3304 event->ref--;
3305 mutex_unlock(&synth_event_mutex);
3306
3307 goto out;
3308}
3309
3310static struct action_data *onmatch_parse(struct trace_array *tr, char *str)
3311{
3312 char *match_event, *match_event_system;
3313 char *synth_event_name, *params;
3314 struct action_data *data;
3315 int ret = -EINVAL;
3316
3317 data = kzalloc(sizeof(*data), GFP_KERNEL);
3318 if (!data)
3319 return ERR_PTR(-ENOMEM);
3320
3321 match_event = strsep(&str, ")");
3322 if (!match_event || !str)
3323 goto free;
3324
3325 match_event_system = strsep(&match_event, ".");
3326 if (!match_event)
3327 goto free;
3328
3329 if (IS_ERR(event_file(tr, match_event_system, match_event)))
3330 goto free;
3331
3332 data->onmatch.match_event = kstrdup(match_event, GFP_KERNEL);
3333 if (!data->onmatch.match_event) {
3334 ret = -ENOMEM;
3335 goto free;
3336 }
3337
3338 data->onmatch.match_event_system = kstrdup(match_event_system, GFP_KERNEL);
3339 if (!data->onmatch.match_event_system) {
3340 ret = -ENOMEM;
3341 goto free;
3342 }
3343
3344 strsep(&str, ".");
3345 if (!str)
3346 goto free;
3347
3348 synth_event_name = strsep(&str, "(");
3349 if (!synth_event_name || !str)
3350 goto free;
3351
3352 data->onmatch.synth_event_name = kstrdup(synth_event_name, GFP_KERNEL);
3353 if (!data->onmatch.synth_event_name) {
3354 ret = -ENOMEM;
3355 goto free;
3356 }
3357
3358 params = strsep(&str, ")");
3359 if (!params || !str || (str && strlen(str)))
3360 goto free;
3361
3362 ret = parse_action_params(params, data);
3363 if (ret)
3364 goto free;
3365 out:
3366 return data;
3367 free:
3368 onmatch_destroy(data);
3369 data = ERR_PTR(ret);
3370 goto out;
3371}
3372
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003373static int create_hitcount_val(struct hist_trigger_data *hist_data)
3374{
3375 hist_data->fields[HITCOUNT_IDX] =
Tom Zanussi30350d62018-01-15 20:51:49 -06003376 create_hist_field(hist_data, NULL, HIST_FIELD_FL_HITCOUNT, NULL);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003377 if (!hist_data->fields[HITCOUNT_IDX])
3378 return -ENOMEM;
3379
3380 hist_data->n_vals++;
Tom Zanussi30350d62018-01-15 20:51:49 -06003381 hist_data->n_fields++;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003382
3383 if (WARN_ON(hist_data->n_vals > TRACING_MAP_VALS_MAX))
3384 return -EINVAL;
3385
3386 return 0;
3387}
3388
Tom Zanussi30350d62018-01-15 20:51:49 -06003389static int __create_val_field(struct hist_trigger_data *hist_data,
3390 unsigned int val_idx,
3391 struct trace_event_file *file,
3392 char *var_name, char *field_str,
3393 unsigned long flags)
Tom Zanussif2606832016-03-03 12:54:43 -06003394{
Tom Zanussi100719d2018-01-15 20:51:52 -06003395 struct hist_field *hist_field;
Tom Zanussif2606832016-03-03 12:54:43 -06003396 int ret = 0;
3397
Tom Zanussi100719d2018-01-15 20:51:52 -06003398 hist_field = parse_expr(hist_data, file, field_str, flags, var_name, 0);
3399 if (IS_ERR(hist_field)) {
3400 ret = PTR_ERR(hist_field);
Tom Zanussif2606832016-03-03 12:54:43 -06003401 goto out;
3402 }
3403
Tom Zanussi100719d2018-01-15 20:51:52 -06003404 hist_data->fields[val_idx] = hist_field;
3405
Tom Zanussif2606832016-03-03 12:54:43 -06003406 ++hist_data->n_vals;
Tom Zanussi30350d62018-01-15 20:51:49 -06003407 ++hist_data->n_fields;
Tom Zanussif2606832016-03-03 12:54:43 -06003408
Tom Zanussi30350d62018-01-15 20:51:49 -06003409 if (WARN_ON(hist_data->n_vals > TRACING_MAP_VALS_MAX + TRACING_MAP_VARS_MAX))
Tom Zanussif2606832016-03-03 12:54:43 -06003410 ret = -EINVAL;
3411 out:
3412 return ret;
3413}
3414
Tom Zanussi30350d62018-01-15 20:51:49 -06003415static int create_val_field(struct hist_trigger_data *hist_data,
3416 unsigned int val_idx,
3417 struct trace_event_file *file,
3418 char *field_str)
3419{
3420 if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX))
3421 return -EINVAL;
3422
3423 return __create_val_field(hist_data, val_idx, file, NULL, field_str, 0);
3424}
3425
3426static int create_var_field(struct hist_trigger_data *hist_data,
3427 unsigned int val_idx,
3428 struct trace_event_file *file,
3429 char *var_name, char *expr_str)
3430{
3431 unsigned long flags = 0;
3432
3433 if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX + TRACING_MAP_VARS_MAX))
3434 return -EINVAL;
3435 if (find_var(hist_data, file, var_name) && !hist_data->remove) {
3436 return -EINVAL;
3437 }
3438
3439 flags |= HIST_FIELD_FL_VAR;
3440 hist_data->n_vars++;
3441 if (WARN_ON(hist_data->n_vars > TRACING_MAP_VARS_MAX))
3442 return -EINVAL;
3443
3444 return __create_val_field(hist_data, val_idx, file, var_name, expr_str, flags);
3445}
3446
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003447static int create_val_fields(struct hist_trigger_data *hist_data,
3448 struct trace_event_file *file)
3449{
Tom Zanussif2606832016-03-03 12:54:43 -06003450 char *fields_str, *field_str;
Tom Zanussi30350d62018-01-15 20:51:49 -06003451 unsigned int i, j = 1;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003452 int ret;
3453
3454 ret = create_hitcount_val(hist_data);
Tom Zanussif2606832016-03-03 12:54:43 -06003455 if (ret)
3456 goto out;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003457
Tom Zanussif2606832016-03-03 12:54:43 -06003458 fields_str = hist_data->attrs->vals_str;
3459 if (!fields_str)
3460 goto out;
3461
3462 strsep(&fields_str, "=");
3463 if (!fields_str)
3464 goto out;
3465
3466 for (i = 0, j = 1; i < TRACING_MAP_VALS_MAX &&
3467 j < TRACING_MAP_VALS_MAX; i++) {
3468 field_str = strsep(&fields_str, ",");
3469 if (!field_str)
3470 break;
Tom Zanussi30350d62018-01-15 20:51:49 -06003471
Tom Zanussif2606832016-03-03 12:54:43 -06003472 if (strcmp(field_str, "hitcount") == 0)
3473 continue;
Tom Zanussi30350d62018-01-15 20:51:49 -06003474
Tom Zanussif2606832016-03-03 12:54:43 -06003475 ret = create_val_field(hist_data, j++, file, field_str);
3476 if (ret)
3477 goto out;
3478 }
Tom Zanussi30350d62018-01-15 20:51:49 -06003479
Tom Zanussif2606832016-03-03 12:54:43 -06003480 if (fields_str && (strcmp(fields_str, "hitcount") != 0))
3481 ret = -EINVAL;
3482 out:
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003483 return ret;
3484}
3485
3486static int create_key_field(struct hist_trigger_data *hist_data,
3487 unsigned int key_idx,
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06003488 unsigned int key_offset,
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003489 struct trace_event_file *file,
3490 char *field_str)
3491{
Tom Zanussi30350d62018-01-15 20:51:49 -06003492 struct hist_field *hist_field = NULL;
Tom Zanussi100719d2018-01-15 20:51:52 -06003493
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003494 unsigned long flags = 0;
3495 unsigned int key_size;
3496 int ret = 0;
3497
Tom Zanussi30350d62018-01-15 20:51:49 -06003498 if (WARN_ON(key_idx >= HIST_FIELDS_MAX))
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003499 return -EINVAL;
3500
3501 flags |= HIST_FIELD_FL_KEY;
3502
Tom Zanussi69a02002016-03-03 12:54:52 -06003503 if (strcmp(field_str, "stacktrace") == 0) {
3504 flags |= HIST_FIELD_FL_STACKTRACE;
3505 key_size = sizeof(unsigned long) * HIST_STACKTRACE_DEPTH;
Tom Zanussi30350d62018-01-15 20:51:49 -06003506 hist_field = create_hist_field(hist_data, NULL, flags, NULL);
Tom Zanussi69a02002016-03-03 12:54:52 -06003507 } else {
Tom Zanussi100719d2018-01-15 20:51:52 -06003508 hist_field = parse_expr(hist_data, file, field_str, flags,
3509 NULL, 0);
3510 if (IS_ERR(hist_field)) {
3511 ret = PTR_ERR(hist_field);
3512 goto out;
Tom Zanussi69a02002016-03-03 12:54:52 -06003513 }
3514
Tom Zanussi067fe032018-01-15 20:51:56 -06003515 if (hist_field->flags & HIST_FIELD_FL_VAR_REF) {
3516 destroy_hist_field(hist_field, 0);
3517 ret = -EINVAL;
3518 goto out;
3519 }
3520
Tom Zanussi100719d2018-01-15 20:51:52 -06003521 key_size = hist_field->size;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003522 }
3523
Tom Zanussi100719d2018-01-15 20:51:52 -06003524 hist_data->fields[key_idx] = hist_field;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003525
3526 key_size = ALIGN(key_size, sizeof(u64));
3527 hist_data->fields[key_idx]->size = key_size;
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06003528 hist_data->fields[key_idx]->offset = key_offset;
Tom Zanussi100719d2018-01-15 20:51:52 -06003529
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06003530 hist_data->key_size += key_size;
Tom Zanussi100719d2018-01-15 20:51:52 -06003531
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003532 if (hist_data->key_size > HIST_KEY_SIZE_MAX) {
3533 ret = -EINVAL;
3534 goto out;
3535 }
3536
3537 hist_data->n_keys++;
Tom Zanussi30350d62018-01-15 20:51:49 -06003538 hist_data->n_fields++;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003539
3540 if (WARN_ON(hist_data->n_keys > TRACING_MAP_KEYS_MAX))
3541 return -EINVAL;
3542
3543 ret = key_size;
3544 out:
3545 return ret;
3546}
3547
3548static int create_key_fields(struct hist_trigger_data *hist_data,
3549 struct trace_event_file *file)
3550{
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06003551 unsigned int i, key_offset = 0, n_vals = hist_data->n_vals;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003552 char *fields_str, *field_str;
3553 int ret = -EINVAL;
3554
3555 fields_str = hist_data->attrs->keys_str;
3556 if (!fields_str)
3557 goto out;
3558
3559 strsep(&fields_str, "=");
3560 if (!fields_str)
3561 goto out;
3562
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06003563 for (i = n_vals; i < n_vals + TRACING_MAP_KEYS_MAX; i++) {
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003564 field_str = strsep(&fields_str, ",");
3565 if (!field_str)
3566 break;
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06003567 ret = create_key_field(hist_data, i, key_offset,
3568 file, field_str);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003569 if (ret < 0)
3570 goto out;
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06003571 key_offset += ret;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003572 }
3573 if (fields_str) {
3574 ret = -EINVAL;
3575 goto out;
3576 }
3577 ret = 0;
3578 out:
3579 return ret;
3580}
3581
Tom Zanussi30350d62018-01-15 20:51:49 -06003582static int create_var_fields(struct hist_trigger_data *hist_data,
3583 struct trace_event_file *file)
3584{
3585 unsigned int i, j = hist_data->n_vals;
3586 int ret = 0;
3587
3588 unsigned int n_vars = hist_data->attrs->var_defs.n_vars;
3589
3590 for (i = 0; i < n_vars; i++) {
3591 char *var_name = hist_data->attrs->var_defs.name[i];
3592 char *expr = hist_data->attrs->var_defs.expr[i];
3593
3594 ret = create_var_field(hist_data, j++, file, var_name, expr);
3595 if (ret)
3596 goto out;
3597 }
3598 out:
3599 return ret;
3600}
3601
3602static void free_var_defs(struct hist_trigger_data *hist_data)
3603{
3604 unsigned int i;
3605
3606 for (i = 0; i < hist_data->attrs->var_defs.n_vars; i++) {
3607 kfree(hist_data->attrs->var_defs.name[i]);
3608 kfree(hist_data->attrs->var_defs.expr[i]);
3609 }
3610
3611 hist_data->attrs->var_defs.n_vars = 0;
3612}
3613
3614static int parse_var_defs(struct hist_trigger_data *hist_data)
3615{
3616 char *s, *str, *var_name, *field_str;
3617 unsigned int i, j, n_vars = 0;
3618 int ret = 0;
3619
3620 for (i = 0; i < hist_data->attrs->n_assignments; i++) {
3621 str = hist_data->attrs->assignment_str[i];
3622 for (j = 0; j < TRACING_MAP_VARS_MAX; j++) {
3623 field_str = strsep(&str, ",");
3624 if (!field_str)
3625 break;
3626
3627 var_name = strsep(&field_str, "=");
3628 if (!var_name || !field_str) {
3629 ret = -EINVAL;
3630 goto free;
3631 }
3632
3633 if (n_vars == TRACING_MAP_VARS_MAX) {
3634 ret = -EINVAL;
3635 goto free;
3636 }
3637
3638 s = kstrdup(var_name, GFP_KERNEL);
3639 if (!s) {
3640 ret = -ENOMEM;
3641 goto free;
3642 }
3643 hist_data->attrs->var_defs.name[n_vars] = s;
3644
3645 s = kstrdup(field_str, GFP_KERNEL);
3646 if (!s) {
3647 kfree(hist_data->attrs->var_defs.name[n_vars]);
3648 ret = -ENOMEM;
3649 goto free;
3650 }
3651 hist_data->attrs->var_defs.expr[n_vars++] = s;
3652
3653 hist_data->attrs->var_defs.n_vars = n_vars;
3654 }
3655 }
3656
3657 return ret;
3658 free:
3659 free_var_defs(hist_data);
3660
3661 return ret;
3662}
3663
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003664static int create_hist_fields(struct hist_trigger_data *hist_data,
3665 struct trace_event_file *file)
3666{
3667 int ret;
3668
Tom Zanussi30350d62018-01-15 20:51:49 -06003669 ret = parse_var_defs(hist_data);
3670 if (ret)
3671 goto out;
3672
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003673 ret = create_val_fields(hist_data, file);
3674 if (ret)
3675 goto out;
3676
Tom Zanussi30350d62018-01-15 20:51:49 -06003677 ret = create_var_fields(hist_data, file);
3678 if (ret)
3679 goto out;
3680
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003681 ret = create_key_fields(hist_data, file);
3682 if (ret)
3683 goto out;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003684 out:
Tom Zanussi30350d62018-01-15 20:51:49 -06003685 free_var_defs(hist_data);
3686
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003687 return ret;
3688}
3689
Tom Zanussie62347d2016-03-03 12:54:45 -06003690static int is_descending(const char *str)
3691{
3692 if (!str)
3693 return 0;
3694
3695 if (strcmp(str, "descending") == 0)
3696 return 1;
3697
3698 if (strcmp(str, "ascending") == 0)
3699 return 0;
3700
3701 return -EINVAL;
3702}
3703
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003704static int create_sort_keys(struct hist_trigger_data *hist_data)
3705{
Tom Zanussie62347d2016-03-03 12:54:45 -06003706 char *fields_str = hist_data->attrs->sort_key_str;
Tom Zanussie62347d2016-03-03 12:54:45 -06003707 struct tracing_map_sort_key *sort_key;
3708 int descending, ret = 0;
Tom Zanussi30350d62018-01-15 20:51:49 -06003709 unsigned int i, j, k;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003710
Tom Zanussie62347d2016-03-03 12:54:45 -06003711 hist_data->n_sort_keys = 1; /* we always have at least one, hitcount */
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003712
Tom Zanussie62347d2016-03-03 12:54:45 -06003713 if (!fields_str)
3714 goto out;
3715
3716 strsep(&fields_str, "=");
3717 if (!fields_str) {
3718 ret = -EINVAL;
3719 goto out;
3720 }
3721
3722 for (i = 0; i < TRACING_MAP_SORT_KEYS_MAX; i++) {
Tom Zanussi85013252017-09-22 14:58:22 -05003723 struct hist_field *hist_field;
Tom Zanussie62347d2016-03-03 12:54:45 -06003724 char *field_str, *field_name;
Tom Zanussi85013252017-09-22 14:58:22 -05003725 const char *test_name;
Tom Zanussie62347d2016-03-03 12:54:45 -06003726
3727 sort_key = &hist_data->sort_keys[i];
3728
3729 field_str = strsep(&fields_str, ",");
3730 if (!field_str) {
3731 if (i == 0)
3732 ret = -EINVAL;
3733 break;
3734 }
3735
3736 if ((i == TRACING_MAP_SORT_KEYS_MAX - 1) && fields_str) {
3737 ret = -EINVAL;
3738 break;
3739 }
3740
3741 field_name = strsep(&field_str, ".");
3742 if (!field_name) {
3743 ret = -EINVAL;
3744 break;
3745 }
3746
3747 if (strcmp(field_name, "hitcount") == 0) {
3748 descending = is_descending(field_str);
3749 if (descending < 0) {
3750 ret = descending;
3751 break;
3752 }
3753 sort_key->descending = descending;
3754 continue;
3755 }
3756
Tom Zanussi30350d62018-01-15 20:51:49 -06003757 for (j = 1, k = 1; j < hist_data->n_fields; j++) {
3758 unsigned int idx;
3759
Tom Zanussi85013252017-09-22 14:58:22 -05003760 hist_field = hist_data->fields[j];
Tom Zanussi30350d62018-01-15 20:51:49 -06003761 if (hist_field->flags & HIST_FIELD_FL_VAR)
3762 continue;
3763
3764 idx = k++;
3765
Tom Zanussi85013252017-09-22 14:58:22 -05003766 test_name = hist_field_name(hist_field, 0);
3767
3768 if (strcmp(field_name, test_name) == 0) {
Tom Zanussi30350d62018-01-15 20:51:49 -06003769 sort_key->field_idx = idx;
Tom Zanussie62347d2016-03-03 12:54:45 -06003770 descending = is_descending(field_str);
3771 if (descending < 0) {
3772 ret = descending;
3773 goto out;
3774 }
3775 sort_key->descending = descending;
3776 break;
3777 }
3778 }
3779 if (j == hist_data->n_fields) {
3780 ret = -EINVAL;
3781 break;
3782 }
3783 }
Tom Zanussi30350d62018-01-15 20:51:49 -06003784
Tom Zanussie62347d2016-03-03 12:54:45 -06003785 hist_data->n_sort_keys = i;
3786 out:
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003787 return ret;
3788}
3789
Tom Zanussi0212e2a2018-01-15 20:51:57 -06003790static void destroy_actions(struct hist_trigger_data *hist_data)
3791{
3792 unsigned int i;
3793
3794 for (i = 0; i < hist_data->n_actions; i++) {
3795 struct action_data *data = hist_data->actions[i];
3796
Tom Zanussic282a382018-01-15 20:52:00 -06003797 if (data->fn == action_trace)
3798 onmatch_destroy(data);
3799 else
3800 kfree(data);
Tom Zanussi0212e2a2018-01-15 20:51:57 -06003801 }
3802}
3803
3804static int parse_actions(struct hist_trigger_data *hist_data)
3805{
Tom Zanussic282a382018-01-15 20:52:00 -06003806 struct trace_array *tr = hist_data->event_file->tr;
3807 struct action_data *data;
Tom Zanussi0212e2a2018-01-15 20:51:57 -06003808 unsigned int i;
3809 int ret = 0;
3810 char *str;
3811
3812 for (i = 0; i < hist_data->attrs->n_actions; i++) {
3813 str = hist_data->attrs->action_str[i];
Tom Zanussic282a382018-01-15 20:52:00 -06003814
3815 if (strncmp(str, "onmatch(", strlen("onmatch(")) == 0) {
3816 char *action_str = str + strlen("onmatch(");
3817
3818 data = onmatch_parse(tr, action_str);
3819 if (IS_ERR(data)) {
3820 ret = PTR_ERR(data);
3821 break;
3822 }
3823 data->fn = action_trace;
3824 } else {
3825 ret = -EINVAL;
3826 break;
3827 }
3828
3829 hist_data->actions[hist_data->n_actions++] = data;
Tom Zanussi0212e2a2018-01-15 20:51:57 -06003830 }
3831
3832 return ret;
3833}
3834
3835static int create_actions(struct hist_trigger_data *hist_data,
3836 struct trace_event_file *file)
3837{
3838 struct action_data *data;
3839 unsigned int i;
3840 int ret = 0;
3841
3842 for (i = 0; i < hist_data->attrs->n_actions; i++) {
3843 data = hist_data->actions[i];
Tom Zanussic282a382018-01-15 20:52:00 -06003844
3845 if (data->fn == action_trace) {
3846 ret = onmatch_create(hist_data, file, data);
3847 if (ret)
3848 return ret;
3849 }
Tom Zanussi0212e2a2018-01-15 20:51:57 -06003850 }
3851
3852 return ret;
3853}
3854
Tom Zanussic282a382018-01-15 20:52:00 -06003855static void print_onmatch_spec(struct seq_file *m,
3856 struct hist_trigger_data *hist_data,
3857 struct action_data *data)
3858{
3859 unsigned int i;
3860
3861 seq_printf(m, ":onmatch(%s.%s).", data->onmatch.match_event_system,
3862 data->onmatch.match_event);
3863
3864 seq_printf(m, "%s(", data->onmatch.synth_event->name);
3865
3866 for (i = 0; i < data->n_params; i++) {
3867 if (i)
3868 seq_puts(m, ",");
3869 seq_printf(m, "%s", data->params[i]);
3870 }
3871
3872 seq_puts(m, ")");
3873}
3874
3875static void print_actions_spec(struct seq_file *m,
3876 struct hist_trigger_data *hist_data)
3877{
3878 unsigned int i;
3879
3880 for (i = 0; i < hist_data->n_actions; i++) {
3881 struct action_data *data = hist_data->actions[i];
3882
3883 if (data->fn == action_trace)
3884 print_onmatch_spec(m, hist_data, data);
3885 }
3886}
3887
Tom Zanussi02205a62018-01-15 20:51:59 -06003888static void destroy_field_var_hists(struct hist_trigger_data *hist_data)
3889{
3890 unsigned int i;
3891
3892 for (i = 0; i < hist_data->n_field_var_hists; i++) {
3893 kfree(hist_data->field_var_hists[i]->cmd);
3894 kfree(hist_data->field_var_hists[i]);
3895 }
3896}
3897
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003898static void destroy_hist_data(struct hist_trigger_data *hist_data)
3899{
Tom Zanussi0212e2a2018-01-15 20:51:57 -06003900 if (!hist_data)
3901 return;
3902
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003903 destroy_hist_trigger_attrs(hist_data->attrs);
3904 destroy_hist_fields(hist_data);
3905 tracing_map_destroy(hist_data->map);
Tom Zanussi0212e2a2018-01-15 20:51:57 -06003906
3907 destroy_actions(hist_data);
Tom Zanussi02205a62018-01-15 20:51:59 -06003908 destroy_field_vars(hist_data);
3909 destroy_field_var_hists(hist_data);
Tom Zanussic282a382018-01-15 20:52:00 -06003910 destroy_synth_var_refs(hist_data);
Tom Zanussi0212e2a2018-01-15 20:51:57 -06003911
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003912 kfree(hist_data);
3913}
3914
3915static int create_tracing_map_fields(struct hist_trigger_data *hist_data)
3916{
3917 struct tracing_map *map = hist_data->map;
3918 struct ftrace_event_field *field;
3919 struct hist_field *hist_field;
Steven Rostedt (Red Hat)d50c7442016-03-08 17:17:15 -05003920 int i, idx;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003921
3922 for_each_hist_field(i, hist_data) {
3923 hist_field = hist_data->fields[i];
3924 if (hist_field->flags & HIST_FIELD_FL_KEY) {
3925 tracing_map_cmp_fn_t cmp_fn;
3926
3927 field = hist_field->field;
3928
Tom Zanussi69a02002016-03-03 12:54:52 -06003929 if (hist_field->flags & HIST_FIELD_FL_STACKTRACE)
3930 cmp_fn = tracing_map_cmp_none;
Tom Zanussiad42feb2018-01-15 20:51:45 -06003931 else if (!field)
3932 cmp_fn = tracing_map_cmp_num(hist_field->size,
3933 hist_field->is_signed);
Tom Zanussi69a02002016-03-03 12:54:52 -06003934 else if (is_string_field(field))
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003935 cmp_fn = tracing_map_cmp_string;
3936 else
3937 cmp_fn = tracing_map_cmp_num(field->size,
3938 field->is_signed);
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06003939 idx = tracing_map_add_key_field(map,
3940 hist_field->offset,
3941 cmp_fn);
Tom Zanussi30350d62018-01-15 20:51:49 -06003942 } else if (!(hist_field->flags & HIST_FIELD_FL_VAR))
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003943 idx = tracing_map_add_sum_field(map);
3944
3945 if (idx < 0)
3946 return idx;
Tom Zanussi30350d62018-01-15 20:51:49 -06003947
3948 if (hist_field->flags & HIST_FIELD_FL_VAR) {
3949 idx = tracing_map_add_var(map);
3950 if (idx < 0)
3951 return idx;
3952 hist_field->var.idx = idx;
3953 hist_field->var.hist_data = hist_data;
3954 }
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003955 }
3956
3957 return 0;
3958}
3959
3960static struct hist_trigger_data *
3961create_hist_data(unsigned int map_bits,
3962 struct hist_trigger_attrs *attrs,
Tom Zanussi30350d62018-01-15 20:51:49 -06003963 struct trace_event_file *file,
3964 bool remove)
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003965{
Tom Zanussi6b4827a2016-03-03 12:54:50 -06003966 const struct tracing_map_ops *map_ops = NULL;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003967 struct hist_trigger_data *hist_data;
3968 int ret = 0;
3969
3970 hist_data = kzalloc(sizeof(*hist_data), GFP_KERNEL);
3971 if (!hist_data)
3972 return ERR_PTR(-ENOMEM);
3973
3974 hist_data->attrs = attrs;
Tom Zanussi30350d62018-01-15 20:51:49 -06003975 hist_data->remove = remove;
Tom Zanussi067fe032018-01-15 20:51:56 -06003976 hist_data->event_file = file;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003977
Tom Zanussi0212e2a2018-01-15 20:51:57 -06003978 ret = parse_actions(hist_data);
3979 if (ret)
3980 goto free;
3981
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003982 ret = create_hist_fields(hist_data, file);
3983 if (ret)
3984 goto free;
3985
3986 ret = create_sort_keys(hist_data);
3987 if (ret)
3988 goto free;
3989
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06003990 map_ops = &hist_trigger_elt_data_ops;
Tom Zanussi6b4827a2016-03-03 12:54:50 -06003991
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003992 hist_data->map = tracing_map_create(map_bits, hist_data->key_size,
Tom Zanussi6b4827a2016-03-03 12:54:50 -06003993 map_ops, hist_data);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06003994 if (IS_ERR(hist_data->map)) {
3995 ret = PTR_ERR(hist_data->map);
3996 hist_data->map = NULL;
3997 goto free;
3998 }
3999
4000 ret = create_tracing_map_fields(hist_data);
4001 if (ret)
4002 goto free;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004003 out:
4004 return hist_data;
4005 free:
4006 hist_data->attrs = NULL;
4007
4008 destroy_hist_data(hist_data);
4009
4010 hist_data = ERR_PTR(ret);
4011
4012 goto out;
4013}
4014
4015static void hist_trigger_elt_update(struct hist_trigger_data *hist_data,
Tom Zanussifbd302c2018-01-15 20:51:43 -06004016 struct tracing_map_elt *elt, void *rec,
Tom Zanussi067fe032018-01-15 20:51:56 -06004017 struct ring_buffer_event *rbe,
4018 u64 *var_ref_vals)
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004019{
Tom Zanussi067fe032018-01-15 20:51:56 -06004020 struct hist_elt_data *elt_data;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004021 struct hist_field *hist_field;
Tom Zanussi30350d62018-01-15 20:51:49 -06004022 unsigned int i, var_idx;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004023 u64 hist_val;
4024
Tom Zanussi067fe032018-01-15 20:51:56 -06004025 elt_data = elt->private_data;
4026 elt_data->var_ref_vals = var_ref_vals;
4027
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004028 for_each_hist_val_field(i, hist_data) {
4029 hist_field = hist_data->fields[i];
Tom Zanussidf35d932018-01-15 20:51:54 -06004030 hist_val = hist_field->fn(hist_field, elt, rbe, rec);
Tom Zanussi30350d62018-01-15 20:51:49 -06004031 if (hist_field->flags & HIST_FIELD_FL_VAR) {
4032 var_idx = hist_field->var.idx;
4033 tracing_map_set_var(elt, var_idx, hist_val);
4034 continue;
4035 }
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004036 tracing_map_update_sum(elt, i, hist_val);
4037 }
Tom Zanussi30350d62018-01-15 20:51:49 -06004038
4039 for_each_hist_key_field(i, hist_data) {
4040 hist_field = hist_data->fields[i];
4041 if (hist_field->flags & HIST_FIELD_FL_VAR) {
Tom Zanussidf35d932018-01-15 20:51:54 -06004042 hist_val = hist_field->fn(hist_field, elt, rbe, rec);
Tom Zanussi30350d62018-01-15 20:51:49 -06004043 var_idx = hist_field->var.idx;
4044 tracing_map_set_var(elt, var_idx, hist_val);
4045 }
4046 }
Tom Zanussi02205a62018-01-15 20:51:59 -06004047
4048 update_field_vars(hist_data, elt, rbe, rec);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004049}
4050
Tom Zanussi6a475cb2016-03-03 12:54:54 -06004051static inline void add_to_key(char *compound_key, void *key,
4052 struct hist_field *key_field, void *rec)
4053{
4054 size_t size = key_field->size;
4055
4056 if (key_field->flags & HIST_FIELD_FL_STRING) {
4057 struct ftrace_event_field *field;
4058
4059 field = key_field->field;
4060 if (field->filter_type == FILTER_DYN_STRING)
4061 size = *(u32 *)(rec + field->offset) >> 16;
4062 else if (field->filter_type == FILTER_PTR_STRING)
4063 size = strlen(key);
4064 else if (field->filter_type == FILTER_STATIC_STRING)
4065 size = field->size;
4066
4067 /* ensure NULL-termination */
4068 if (size > key_field->size - 1)
4069 size = key_field->size - 1;
4070 }
4071
4072 memcpy(compound_key + key_field->offset, key, size);
4073}
4074
Tom Zanussi0212e2a2018-01-15 20:51:57 -06004075static void
4076hist_trigger_actions(struct hist_trigger_data *hist_data,
4077 struct tracing_map_elt *elt, void *rec,
4078 struct ring_buffer_event *rbe, u64 *var_ref_vals)
4079{
4080 struct action_data *data;
4081 unsigned int i;
4082
4083 for (i = 0; i < hist_data->n_actions; i++) {
4084 data = hist_data->actions[i];
4085 data->fn(hist_data, elt, rec, rbe, data, var_ref_vals);
4086 }
4087}
4088
Tom Zanussi1ac4f512018-01-15 20:51:42 -06004089static void event_hist_trigger(struct event_trigger_data *data, void *rec,
Tom Zanussifbd302c2018-01-15 20:51:43 -06004090 struct ring_buffer_event *rbe)
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004091{
4092 struct hist_trigger_data *hist_data = data->private_data;
Tom Zanussi6a475cb2016-03-03 12:54:54 -06004093 bool use_compound_key = (hist_data->n_keys > 1);
Tom Zanussi69a02002016-03-03 12:54:52 -06004094 unsigned long entries[HIST_STACKTRACE_DEPTH];
Tom Zanussi067fe032018-01-15 20:51:56 -06004095 u64 var_ref_vals[TRACING_MAP_VARS_MAX];
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06004096 char compound_key[HIST_KEY_SIZE_MAX];
Tom Zanussidf35d932018-01-15 20:51:54 -06004097 struct tracing_map_elt *elt = NULL;
Tom Zanussi69a02002016-03-03 12:54:52 -06004098 struct stack_trace stacktrace;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004099 struct hist_field *key_field;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004100 u64 field_contents;
4101 void *key = NULL;
4102 unsigned int i;
4103
Tom Zanussi6a475cb2016-03-03 12:54:54 -06004104 memset(compound_key, 0, hist_data->key_size);
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06004105
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004106 for_each_hist_key_field(i, hist_data) {
4107 key_field = hist_data->fields[i];
4108
Tom Zanussi69a02002016-03-03 12:54:52 -06004109 if (key_field->flags & HIST_FIELD_FL_STACKTRACE) {
4110 stacktrace.max_entries = HIST_STACKTRACE_DEPTH;
4111 stacktrace.entries = entries;
4112 stacktrace.nr_entries = 0;
4113 stacktrace.skip = HIST_STACKTRACE_SKIP;
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06004114
Tom Zanussi69a02002016-03-03 12:54:52 -06004115 memset(stacktrace.entries, 0, HIST_STACKTRACE_SIZE);
4116 save_stack_trace(&stacktrace);
4117
4118 key = entries;
4119 } else {
Tom Zanussidf35d932018-01-15 20:51:54 -06004120 field_contents = key_field->fn(key_field, elt, rbe, rec);
Tom Zanussi6a475cb2016-03-03 12:54:54 -06004121 if (key_field->flags & HIST_FIELD_FL_STRING) {
Tom Zanussi69a02002016-03-03 12:54:52 -06004122 key = (void *)(unsigned long)field_contents;
Tom Zanussi6a475cb2016-03-03 12:54:54 -06004123 use_compound_key = true;
4124 } else
Tom Zanussi69a02002016-03-03 12:54:52 -06004125 key = (void *)&field_contents;
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06004126 }
Tom Zanussi6a475cb2016-03-03 12:54:54 -06004127
4128 if (use_compound_key)
4129 add_to_key(compound_key, key, key_field, rec);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004130 }
4131
Tom Zanussi6a475cb2016-03-03 12:54:54 -06004132 if (use_compound_key)
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06004133 key = compound_key;
4134
Tom Zanussi067fe032018-01-15 20:51:56 -06004135 if (hist_data->n_var_refs &&
4136 !resolve_var_refs(hist_data, key, var_ref_vals, false))
4137 return;
4138
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004139 elt = tracing_map_insert(hist_data->map, key);
Tom Zanussi067fe032018-01-15 20:51:56 -06004140 if (!elt)
4141 return;
4142
4143 hist_trigger_elt_update(hist_data, elt, rec, rbe, var_ref_vals);
Tom Zanussi0212e2a2018-01-15 20:51:57 -06004144
4145 if (resolve_var_refs(hist_data, key, var_ref_vals, true))
4146 hist_trigger_actions(hist_data, elt, rec, rbe, var_ref_vals);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004147}
4148
Tom Zanussi69a02002016-03-03 12:54:52 -06004149static void hist_trigger_stacktrace_print(struct seq_file *m,
4150 unsigned long *stacktrace_entries,
4151 unsigned int max_entries)
4152{
4153 char str[KSYM_SYMBOL_LEN];
4154 unsigned int spaces = 8;
4155 unsigned int i;
4156
4157 for (i = 0; i < max_entries; i++) {
4158 if (stacktrace_entries[i] == ULONG_MAX)
4159 return;
4160
4161 seq_printf(m, "%*c", 1 + spaces, ' ');
4162 sprint_symbol(str, stacktrace_entries[i]);
4163 seq_printf(m, "%s\n", str);
4164 }
4165}
4166
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004167static void
4168hist_trigger_entry_print(struct seq_file *m,
4169 struct hist_trigger_data *hist_data, void *key,
4170 struct tracing_map_elt *elt)
4171{
4172 struct hist_field *key_field;
Tom Zanussic6afad42016-03-03 12:54:49 -06004173 char str[KSYM_SYMBOL_LEN];
Tom Zanussi69a02002016-03-03 12:54:52 -06004174 bool multiline = false;
Tom Zanussi85013252017-09-22 14:58:22 -05004175 const char *field_name;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004176 unsigned int i;
4177 u64 uval;
4178
4179 seq_puts(m, "{ ");
4180
4181 for_each_hist_key_field(i, hist_data) {
4182 key_field = hist_data->fields[i];
4183
4184 if (i > hist_data->n_vals)
4185 seq_puts(m, ", ");
4186
Tom Zanussi85013252017-09-22 14:58:22 -05004187 field_name = hist_field_name(key_field, 0);
4188
Tom Zanussi0c4a6b42016-03-03 12:54:48 -06004189 if (key_field->flags & HIST_FIELD_FL_HEX) {
4190 uval = *(u64 *)(key + key_field->offset);
Tom Zanussi85013252017-09-22 14:58:22 -05004191 seq_printf(m, "%s: %llx", field_name, uval);
Tom Zanussic6afad42016-03-03 12:54:49 -06004192 } else if (key_field->flags & HIST_FIELD_FL_SYM) {
4193 uval = *(u64 *)(key + key_field->offset);
4194 sprint_symbol_no_offset(str, uval);
Tom Zanussi85013252017-09-22 14:58:22 -05004195 seq_printf(m, "%s: [%llx] %-45s", field_name,
4196 uval, str);
Tom Zanussic6afad42016-03-03 12:54:49 -06004197 } else if (key_field->flags & HIST_FIELD_FL_SYM_OFFSET) {
4198 uval = *(u64 *)(key + key_field->offset);
4199 sprint_symbol(str, uval);
Tom Zanussi85013252017-09-22 14:58:22 -05004200 seq_printf(m, "%s: [%llx] %-55s", field_name,
4201 uval, str);
Tom Zanussi6b4827a2016-03-03 12:54:50 -06004202 } else if (key_field->flags & HIST_FIELD_FL_EXECNAME) {
Tom Zanussiaf6a29b2018-01-15 20:51:53 -06004203 struct hist_elt_data *elt_data = elt->private_data;
4204 char *comm;
4205
4206 if (WARN_ON_ONCE(!elt_data))
4207 return;
4208
4209 comm = elt_data->comm;
Tom Zanussi6b4827a2016-03-03 12:54:50 -06004210
4211 uval = *(u64 *)(key + key_field->offset);
Tom Zanussi85013252017-09-22 14:58:22 -05004212 seq_printf(m, "%s: %-16s[%10llu]", field_name,
4213 comm, uval);
Tom Zanussi31696192016-03-03 12:54:51 -06004214 } else if (key_field->flags & HIST_FIELD_FL_SYSCALL) {
4215 const char *syscall_name;
4216
4217 uval = *(u64 *)(key + key_field->offset);
4218 syscall_name = get_syscall_name(uval);
4219 if (!syscall_name)
4220 syscall_name = "unknown_syscall";
4221
Tom Zanussi85013252017-09-22 14:58:22 -05004222 seq_printf(m, "%s: %-30s[%3llu]", field_name,
4223 syscall_name, uval);
Tom Zanussi69a02002016-03-03 12:54:52 -06004224 } else if (key_field->flags & HIST_FIELD_FL_STACKTRACE) {
4225 seq_puts(m, "stacktrace:\n");
4226 hist_trigger_stacktrace_print(m,
4227 key + key_field->offset,
4228 HIST_STACKTRACE_DEPTH);
4229 multiline = true;
Namhyung Kim4b94f5b2016-03-03 12:55:02 -06004230 } else if (key_field->flags & HIST_FIELD_FL_LOG2) {
Tom Zanussi85013252017-09-22 14:58:22 -05004231 seq_printf(m, "%s: ~ 2^%-2llu", field_name,
Namhyung Kim4b94f5b2016-03-03 12:55:02 -06004232 *(u64 *)(key + key_field->offset));
Tom Zanussi0c4a6b42016-03-03 12:54:48 -06004233 } else if (key_field->flags & HIST_FIELD_FL_STRING) {
Tom Zanussi85013252017-09-22 14:58:22 -05004234 seq_printf(m, "%s: %-50s", field_name,
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06004235 (char *)(key + key_field->offset));
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004236 } else {
Tom Zanussi76a3b0c2016-03-03 12:54:44 -06004237 uval = *(u64 *)(key + key_field->offset);
Tom Zanussi85013252017-09-22 14:58:22 -05004238 seq_printf(m, "%s: %10llu", field_name, uval);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004239 }
4240 }
4241
Tom Zanussi69a02002016-03-03 12:54:52 -06004242 if (!multiline)
4243 seq_puts(m, " ");
4244
4245 seq_puts(m, "}");
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004246
4247 seq_printf(m, " hitcount: %10llu",
4248 tracing_map_read_sum(elt, HITCOUNT_IDX));
4249
Tom Zanussif2606832016-03-03 12:54:43 -06004250 for (i = 1; i < hist_data->n_vals; i++) {
Tom Zanussi85013252017-09-22 14:58:22 -05004251 field_name = hist_field_name(hist_data->fields[i], 0);
4252
Tom Zanussi100719d2018-01-15 20:51:52 -06004253 if (hist_data->fields[i]->flags & HIST_FIELD_FL_VAR ||
4254 hist_data->fields[i]->flags & HIST_FIELD_FL_EXPR)
Tom Zanussi30350d62018-01-15 20:51:49 -06004255 continue;
4256
Tom Zanussi0c4a6b42016-03-03 12:54:48 -06004257 if (hist_data->fields[i]->flags & HIST_FIELD_FL_HEX) {
Tom Zanussi85013252017-09-22 14:58:22 -05004258 seq_printf(m, " %s: %10llx", field_name,
Tom Zanussi0c4a6b42016-03-03 12:54:48 -06004259 tracing_map_read_sum(elt, i));
4260 } else {
Tom Zanussi85013252017-09-22 14:58:22 -05004261 seq_printf(m, " %s: %10llu", field_name,
Tom Zanussi0c4a6b42016-03-03 12:54:48 -06004262 tracing_map_read_sum(elt, i));
4263 }
Tom Zanussif2606832016-03-03 12:54:43 -06004264 }
4265
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004266 seq_puts(m, "\n");
4267}
4268
4269static int print_entries(struct seq_file *m,
4270 struct hist_trigger_data *hist_data)
4271{
4272 struct tracing_map_sort_entry **sort_entries = NULL;
4273 struct tracing_map *map = hist_data->map;
Steven Rostedt (Red Hat)d50c7442016-03-08 17:17:15 -05004274 int i, n_entries;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004275
4276 n_entries = tracing_map_sort_entries(map, hist_data->sort_keys,
4277 hist_data->n_sort_keys,
4278 &sort_entries);
4279 if (n_entries < 0)
4280 return n_entries;
4281
4282 for (i = 0; i < n_entries; i++)
4283 hist_trigger_entry_print(m, hist_data,
4284 sort_entries[i]->key,
4285 sort_entries[i]->elt);
4286
4287 tracing_map_destroy_sort_entries(sort_entries, n_entries);
4288
4289 return n_entries;
4290}
4291
Tom Zanussi52a7f162016-03-03 12:54:57 -06004292static void hist_trigger_show(struct seq_file *m,
4293 struct event_trigger_data *data, int n)
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004294{
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004295 struct hist_trigger_data *hist_data;
Colin Ian King6e7a2392017-08-23 12:23:09 +01004296 int n_entries;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004297
Tom Zanussi52a7f162016-03-03 12:54:57 -06004298 if (n > 0)
4299 seq_puts(m, "\n\n");
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004300
4301 seq_puts(m, "# event histogram\n#\n# trigger info: ");
4302 data->ops->print(m, data->ops, data);
Tom Zanussi52a7f162016-03-03 12:54:57 -06004303 seq_puts(m, "#\n\n");
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004304
4305 hist_data = data->private_data;
4306 n_entries = print_entries(m, hist_data);
Colin Ian King6e7a2392017-08-23 12:23:09 +01004307 if (n_entries < 0)
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004308 n_entries = 0;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004309
4310 seq_printf(m, "\nTotals:\n Hits: %llu\n Entries: %u\n Dropped: %llu\n",
4311 (u64)atomic64_read(&hist_data->map->hits),
4312 n_entries, (u64)atomic64_read(&hist_data->map->drops));
Tom Zanussi52a7f162016-03-03 12:54:57 -06004313}
4314
4315static int hist_show(struct seq_file *m, void *v)
4316{
4317 struct event_trigger_data *data;
4318 struct trace_event_file *event_file;
4319 int n = 0, ret = 0;
4320
4321 mutex_lock(&event_mutex);
4322
4323 event_file = event_file_data(m->private);
4324 if (unlikely(!event_file)) {
4325 ret = -ENODEV;
4326 goto out_unlock;
4327 }
4328
4329 list_for_each_entry_rcu(data, &event_file->triggers, list) {
4330 if (data->cmd_ops->trigger_type == ETT_EVENT_HIST)
4331 hist_trigger_show(m, data, n++);
4332 }
4333
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004334 out_unlock:
4335 mutex_unlock(&event_mutex);
4336
4337 return ret;
4338}
4339
4340static int event_hist_open(struct inode *inode, struct file *file)
4341{
4342 return single_open(file, hist_show, file);
4343}
4344
4345const struct file_operations event_hist_fops = {
4346 .open = event_hist_open,
4347 .read = seq_read,
4348 .llseek = seq_lseek,
4349 .release = single_release,
4350};
4351
4352static void hist_field_print(struct seq_file *m, struct hist_field *hist_field)
4353{
Tom Zanussi85013252017-09-22 14:58:22 -05004354 const char *field_name = hist_field_name(hist_field, 0);
4355
Tom Zanussi30350d62018-01-15 20:51:49 -06004356 if (hist_field->var.name)
4357 seq_printf(m, "%s=", hist_field->var.name);
4358
Tom Zanussiad42feb2018-01-15 20:51:45 -06004359 if (hist_field->flags & HIST_FIELD_FL_TIMESTAMP)
4360 seq_puts(m, "common_timestamp");
Tom Zanussi067fe032018-01-15 20:51:56 -06004361 else if (field_name) {
4362 if (hist_field->flags & HIST_FIELD_FL_VAR_REF)
4363 seq_putc(m, '$');
Tom Zanussiad42feb2018-01-15 20:51:45 -06004364 seq_printf(m, "%s", field_name);
Tom Zanussi067fe032018-01-15 20:51:56 -06004365 }
Tom Zanussiad42feb2018-01-15 20:51:45 -06004366
Tom Zanussi0c4a6b42016-03-03 12:54:48 -06004367 if (hist_field->flags) {
4368 const char *flags_str = get_hist_field_flags(hist_field);
4369
4370 if (flags_str)
4371 seq_printf(m, ".%s", flags_str);
4372 }
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004373}
4374
4375static int event_hist_trigger_print(struct seq_file *m,
4376 struct event_trigger_ops *ops,
4377 struct event_trigger_data *data)
4378{
4379 struct hist_trigger_data *hist_data = data->private_data;
Tom Zanussi30350d62018-01-15 20:51:49 -06004380 struct hist_field *field;
4381 bool have_var = false;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004382 unsigned int i;
4383
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004384 seq_puts(m, "hist:");
4385
4386 if (data->name)
4387 seq_printf(m, "%s:", data->name);
4388
4389 seq_puts(m, "keys=");
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004390
4391 for_each_hist_key_field(i, hist_data) {
Tom Zanussi30350d62018-01-15 20:51:49 -06004392 field = hist_data->fields[i];
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004393
4394 if (i > hist_data->n_vals)
4395 seq_puts(m, ",");
4396
Tom Zanussi30350d62018-01-15 20:51:49 -06004397 if (field->flags & HIST_FIELD_FL_STACKTRACE)
Tom Zanussi69a02002016-03-03 12:54:52 -06004398 seq_puts(m, "stacktrace");
4399 else
Tom Zanussi30350d62018-01-15 20:51:49 -06004400 hist_field_print(m, field);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004401 }
4402
4403 seq_puts(m, ":vals=");
Tom Zanussif2606832016-03-03 12:54:43 -06004404
4405 for_each_hist_val_field(i, hist_data) {
Tom Zanussi30350d62018-01-15 20:51:49 -06004406 field = hist_data->fields[i];
4407 if (field->flags & HIST_FIELD_FL_VAR) {
4408 have_var = true;
4409 continue;
4410 }
4411
Tom Zanussif2606832016-03-03 12:54:43 -06004412 if (i == HITCOUNT_IDX)
4413 seq_puts(m, "hitcount");
4414 else {
4415 seq_puts(m, ",");
Tom Zanussi30350d62018-01-15 20:51:49 -06004416 hist_field_print(m, field);
4417 }
4418 }
4419
4420 if (have_var) {
4421 unsigned int n = 0;
4422
4423 seq_puts(m, ":");
4424
4425 for_each_hist_val_field(i, hist_data) {
4426 field = hist_data->fields[i];
4427
4428 if (field->flags & HIST_FIELD_FL_VAR) {
4429 if (n++)
4430 seq_puts(m, ",");
4431 hist_field_print(m, field);
4432 }
Tom Zanussif2606832016-03-03 12:54:43 -06004433 }
4434 }
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004435
4436 seq_puts(m, ":sort=");
Tom Zanussie62347d2016-03-03 12:54:45 -06004437
4438 for (i = 0; i < hist_data->n_sort_keys; i++) {
4439 struct tracing_map_sort_key *sort_key;
Tom Zanussi30350d62018-01-15 20:51:49 -06004440 unsigned int idx, first_key_idx;
4441
4442 /* skip VAR vals */
4443 first_key_idx = hist_data->n_vals - hist_data->n_vars;
Tom Zanussie62347d2016-03-03 12:54:45 -06004444
4445 sort_key = &hist_data->sort_keys[i];
Tom Zanussiad42feb2018-01-15 20:51:45 -06004446 idx = sort_key->field_idx;
4447
Tom Zanussi1a361df2018-01-15 20:51:50 -06004448 if (WARN_ON(idx >= HIST_FIELDS_MAX))
Tom Zanussiad42feb2018-01-15 20:51:45 -06004449 return -EINVAL;
Tom Zanussie62347d2016-03-03 12:54:45 -06004450
4451 if (i > 0)
4452 seq_puts(m, ",");
4453
Tom Zanussiad42feb2018-01-15 20:51:45 -06004454 if (idx == HITCOUNT_IDX)
Tom Zanussie62347d2016-03-03 12:54:45 -06004455 seq_puts(m, "hitcount");
Tom Zanussi30350d62018-01-15 20:51:49 -06004456 else {
4457 if (idx >= first_key_idx)
4458 idx += hist_data->n_vars;
Tom Zanussie62347d2016-03-03 12:54:45 -06004459 hist_field_print(m, hist_data->fields[idx]);
Tom Zanussi30350d62018-01-15 20:51:49 -06004460 }
Tom Zanussie62347d2016-03-03 12:54:45 -06004461
4462 if (sort_key->descending)
4463 seq_puts(m, ".descending");
4464 }
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004465 seq_printf(m, ":size=%u", (1 << hist_data->map->map_bits));
4466
Tom Zanussic282a382018-01-15 20:52:00 -06004467 print_actions_spec(m, hist_data);
4468
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004469 if (data->filter_str)
4470 seq_printf(m, " if %s", data->filter_str);
4471
Tom Zanussi83e99912016-03-03 12:54:46 -06004472 if (data->paused)
4473 seq_puts(m, " [paused]");
4474 else
4475 seq_puts(m, " [active]");
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004476
4477 seq_putc(m, '\n');
4478
4479 return 0;
4480}
4481
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004482static int event_hist_trigger_init(struct event_trigger_ops *ops,
4483 struct event_trigger_data *data)
4484{
4485 struct hist_trigger_data *hist_data = data->private_data;
4486
4487 if (!data->ref && hist_data->attrs->name)
4488 save_named_trigger(hist_data->attrs->name, data);
4489
4490 data->ref++;
4491
4492 return 0;
4493}
4494
Tom Zanussi02205a62018-01-15 20:51:59 -06004495static void unregister_field_var_hists(struct hist_trigger_data *hist_data)
4496{
4497 struct trace_event_file *file;
4498 unsigned int i;
4499 char *cmd;
4500 int ret;
4501
4502 for (i = 0; i < hist_data->n_field_var_hists; i++) {
4503 file = hist_data->field_var_hists[i]->hist_data->event_file;
4504 cmd = hist_data->field_var_hists[i]->cmd;
4505 ret = event_hist_trigger_func(&trigger_hist_cmd, file,
4506 "!hist", "hist", cmd);
4507 }
4508}
4509
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004510static void event_hist_trigger_free(struct event_trigger_ops *ops,
4511 struct event_trigger_data *data)
4512{
4513 struct hist_trigger_data *hist_data = data->private_data;
4514
4515 if (WARN_ON_ONCE(data->ref <= 0))
4516 return;
4517
4518 data->ref--;
4519 if (!data->ref) {
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004520 if (data->name)
4521 del_named_trigger(data);
Tom Zanussi067fe032018-01-15 20:51:56 -06004522
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004523 trigger_data_free(data);
Tom Zanussi067fe032018-01-15 20:51:56 -06004524
4525 remove_hist_vars(hist_data);
4526
Tom Zanussi02205a62018-01-15 20:51:59 -06004527 unregister_field_var_hists(hist_data);
4528
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004529 destroy_hist_data(hist_data);
4530 }
4531}
4532
4533static struct event_trigger_ops event_hist_trigger_ops = {
4534 .func = event_hist_trigger,
4535 .print = event_hist_trigger_print,
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004536 .init = event_hist_trigger_init,
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004537 .free = event_hist_trigger_free,
4538};
4539
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004540static int event_hist_trigger_named_init(struct event_trigger_ops *ops,
4541 struct event_trigger_data *data)
4542{
4543 data->ref++;
4544
4545 save_named_trigger(data->named_data->name, data);
4546
4547 event_hist_trigger_init(ops, data->named_data);
4548
4549 return 0;
4550}
4551
4552static void event_hist_trigger_named_free(struct event_trigger_ops *ops,
4553 struct event_trigger_data *data)
4554{
4555 if (WARN_ON_ONCE(data->ref <= 0))
4556 return;
4557
4558 event_hist_trigger_free(ops, data->named_data);
4559
4560 data->ref--;
4561 if (!data->ref) {
4562 del_named_trigger(data);
4563 trigger_data_free(data);
4564 }
4565}
4566
4567static struct event_trigger_ops event_hist_trigger_named_ops = {
4568 .func = event_hist_trigger,
4569 .print = event_hist_trigger_print,
4570 .init = event_hist_trigger_named_init,
4571 .free = event_hist_trigger_named_free,
4572};
4573
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004574static struct event_trigger_ops *event_hist_get_trigger_ops(char *cmd,
4575 char *param)
4576{
4577 return &event_hist_trigger_ops;
4578}
4579
Tom Zanussie86ae9b2016-03-03 12:54:47 -06004580static void hist_clear(struct event_trigger_data *data)
4581{
4582 struct hist_trigger_data *hist_data = data->private_data;
Tom Zanussie86ae9b2016-03-03 12:54:47 -06004583
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004584 if (data->name)
4585 pause_named_trigger(data);
Tom Zanussie86ae9b2016-03-03 12:54:47 -06004586
4587 synchronize_sched();
4588
4589 tracing_map_clear(hist_data->map);
4590
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004591 if (data->name)
4592 unpause_named_trigger(data);
4593}
4594
4595static bool compatible_field(struct ftrace_event_field *field,
4596 struct ftrace_event_field *test_field)
4597{
4598 if (field == test_field)
4599 return true;
4600 if (field == NULL || test_field == NULL)
4601 return false;
4602 if (strcmp(field->name, test_field->name) != 0)
4603 return false;
4604 if (strcmp(field->type, test_field->type) != 0)
4605 return false;
4606 if (field->size != test_field->size)
4607 return false;
4608 if (field->is_signed != test_field->is_signed)
4609 return false;
4610
4611 return true;
Tom Zanussie86ae9b2016-03-03 12:54:47 -06004612}
4613
Tom Zanussi52a7f162016-03-03 12:54:57 -06004614static bool hist_trigger_match(struct event_trigger_data *data,
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004615 struct event_trigger_data *data_test,
4616 struct event_trigger_data *named_data,
4617 bool ignore_filter)
Tom Zanussi52a7f162016-03-03 12:54:57 -06004618{
4619 struct tracing_map_sort_key *sort_key, *sort_key_test;
4620 struct hist_trigger_data *hist_data, *hist_data_test;
4621 struct hist_field *key_field, *key_field_test;
4622 unsigned int i;
4623
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004624 if (named_data && (named_data != data_test) &&
4625 (named_data != data_test->named_data))
4626 return false;
4627
4628 if (!named_data && is_named_trigger(data_test))
4629 return false;
4630
Tom Zanussi52a7f162016-03-03 12:54:57 -06004631 hist_data = data->private_data;
4632 hist_data_test = data_test->private_data;
4633
4634 if (hist_data->n_vals != hist_data_test->n_vals ||
4635 hist_data->n_fields != hist_data_test->n_fields ||
4636 hist_data->n_sort_keys != hist_data_test->n_sort_keys)
4637 return false;
4638
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004639 if (!ignore_filter) {
4640 if ((data->filter_str && !data_test->filter_str) ||
4641 (!data->filter_str && data_test->filter_str))
4642 return false;
4643 }
Tom Zanussi52a7f162016-03-03 12:54:57 -06004644
4645 for_each_hist_field(i, hist_data) {
4646 key_field = hist_data->fields[i];
4647 key_field_test = hist_data_test->fields[i];
4648
4649 if (key_field->flags != key_field_test->flags)
4650 return false;
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004651 if (!compatible_field(key_field->field, key_field_test->field))
Tom Zanussi52a7f162016-03-03 12:54:57 -06004652 return false;
4653 if (key_field->offset != key_field_test->offset)
4654 return false;
Tom Zanussiad42feb2018-01-15 20:51:45 -06004655 if (key_field->size != key_field_test->size)
4656 return false;
4657 if (key_field->is_signed != key_field_test->is_signed)
4658 return false;
Tom Zanussi1a361df2018-01-15 20:51:50 -06004659 if (!!key_field->var.name != !!key_field_test->var.name)
4660 return false;
4661 if (key_field->var.name &&
4662 strcmp(key_field->var.name, key_field_test->var.name) != 0)
4663 return false;
Tom Zanussi52a7f162016-03-03 12:54:57 -06004664 }
4665
4666 for (i = 0; i < hist_data->n_sort_keys; i++) {
4667 sort_key = &hist_data->sort_keys[i];
4668 sort_key_test = &hist_data_test->sort_keys[i];
4669
4670 if (sort_key->field_idx != sort_key_test->field_idx ||
4671 sort_key->descending != sort_key_test->descending)
4672 return false;
4673 }
4674
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004675 if (!ignore_filter && data->filter_str &&
Tom Zanussi52a7f162016-03-03 12:54:57 -06004676 (strcmp(data->filter_str, data_test->filter_str) != 0))
4677 return false;
4678
4679 return true;
4680}
4681
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004682static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
4683 struct event_trigger_data *data,
4684 struct trace_event_file *file)
4685{
Tom Zanussi83e99912016-03-03 12:54:46 -06004686 struct hist_trigger_data *hist_data = data->private_data;
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004687 struct event_trigger_data *test, *named_data = NULL;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004688 int ret = 0;
4689
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004690 if (hist_data->attrs->name) {
4691 named_data = find_named_trigger(hist_data->attrs->name);
4692 if (named_data) {
4693 if (!hist_trigger_match(data, named_data, named_data,
4694 true)) {
4695 ret = -EINVAL;
4696 goto out;
4697 }
4698 }
4699 }
4700
4701 if (hist_data->attrs->name && !named_data)
4702 goto new;
4703
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004704 list_for_each_entry_rcu(test, &file->triggers, list) {
4705 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004706 if (!hist_trigger_match(data, test, named_data, false))
Tom Zanussi52a7f162016-03-03 12:54:57 -06004707 continue;
Tom Zanussi83e99912016-03-03 12:54:46 -06004708 if (hist_data->attrs->pause)
4709 test->paused = true;
4710 else if (hist_data->attrs->cont)
4711 test->paused = false;
Tom Zanussie86ae9b2016-03-03 12:54:47 -06004712 else if (hist_data->attrs->clear)
4713 hist_clear(test);
Tom Zanussi83e99912016-03-03 12:54:46 -06004714 else
4715 ret = -EEXIST;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004716 goto out;
4717 }
4718 }
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004719 new:
Tom Zanussie86ae9b2016-03-03 12:54:47 -06004720 if (hist_data->attrs->cont || hist_data->attrs->clear) {
Tom Zanussi83e99912016-03-03 12:54:46 -06004721 ret = -ENOENT;
4722 goto out;
4723 }
4724
Tom Zanussi7522c032016-06-29 19:56:00 -05004725 if (hist_data->attrs->pause)
4726 data->paused = true;
4727
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004728 if (named_data) {
4729 destroy_hist_data(data->private_data);
4730 data->private_data = named_data->private_data;
4731 set_named_trigger_data(data, named_data);
4732 data->ops = &event_hist_trigger_named_ops;
4733 }
4734
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004735 if (data->ops->init) {
4736 ret = data->ops->init(data->ops, data);
4737 if (ret < 0)
4738 goto out;
4739 }
4740
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004741 ret++;
4742
Tom Zanussiad42feb2018-01-15 20:51:45 -06004743 if (hist_data->enable_timestamps)
4744 tracing_set_time_stamp_abs(file->tr, true);
Tom Zanussi067fe032018-01-15 20:51:56 -06004745 out:
4746 return ret;
4747}
4748
4749static int hist_trigger_enable(struct event_trigger_data *data,
4750 struct trace_event_file *file)
4751{
4752 int ret = 0;
4753
4754 list_add_tail_rcu(&data->list, &file->triggers);
4755
4756 update_cond_flag(file);
Tom Zanussiad42feb2018-01-15 20:51:45 -06004757
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004758 if (trace_event_trigger_enable_disable(file, 1) < 0) {
4759 list_del_rcu(&data->list);
4760 update_cond_flag(file);
4761 ret--;
4762 }
Tom Zanussi067fe032018-01-15 20:51:56 -06004763
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004764 return ret;
4765}
4766
Tom Zanussi4b147932018-01-15 20:51:58 -06004767static bool have_hist_trigger_match(struct event_trigger_data *data,
4768 struct trace_event_file *file)
4769{
4770 struct hist_trigger_data *hist_data = data->private_data;
4771 struct event_trigger_data *test, *named_data = NULL;
4772 bool match = false;
4773
4774 if (hist_data->attrs->name)
4775 named_data = find_named_trigger(hist_data->attrs->name);
4776
4777 list_for_each_entry_rcu(test, &file->triggers, list) {
4778 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
4779 if (hist_trigger_match(data, test, named_data, false)) {
4780 match = true;
4781 break;
4782 }
4783 }
4784 }
4785
4786 return match;
4787}
4788
Tom Zanussi067fe032018-01-15 20:51:56 -06004789static bool hist_trigger_check_refs(struct event_trigger_data *data,
4790 struct trace_event_file *file)
4791{
4792 struct hist_trigger_data *hist_data = data->private_data;
4793 struct event_trigger_data *test, *named_data = NULL;
4794
4795 if (hist_data->attrs->name)
4796 named_data = find_named_trigger(hist_data->attrs->name);
4797
4798 list_for_each_entry_rcu(test, &file->triggers, list) {
4799 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
4800 if (!hist_trigger_match(data, test, named_data, false))
4801 continue;
4802 hist_data = test->private_data;
4803 if (check_var_refs(hist_data))
4804 return true;
4805 break;
4806 }
4807 }
4808
4809 return false;
4810}
4811
Tom Zanussi52a7f162016-03-03 12:54:57 -06004812static void hist_unregister_trigger(char *glob, struct event_trigger_ops *ops,
4813 struct event_trigger_data *data,
4814 struct trace_event_file *file)
4815{
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004816 struct hist_trigger_data *hist_data = data->private_data;
4817 struct event_trigger_data *test, *named_data = NULL;
Tom Zanussi52a7f162016-03-03 12:54:57 -06004818 bool unregistered = false;
4819
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004820 if (hist_data->attrs->name)
4821 named_data = find_named_trigger(hist_data->attrs->name);
4822
Tom Zanussi52a7f162016-03-03 12:54:57 -06004823 list_for_each_entry_rcu(test, &file->triggers, list) {
4824 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
Tom Zanussi5463bfd2016-03-03 12:54:59 -06004825 if (!hist_trigger_match(data, test, named_data, false))
Tom Zanussi52a7f162016-03-03 12:54:57 -06004826 continue;
4827 unregistered = true;
4828 list_del_rcu(&test->list);
4829 trace_event_trigger_enable_disable(file, 0);
4830 update_cond_flag(file);
4831 break;
4832 }
4833 }
4834
4835 if (unregistered && test->ops->free)
4836 test->ops->free(test->ops, test);
Tom Zanussiad42feb2018-01-15 20:51:45 -06004837
4838 if (hist_data->enable_timestamps) {
Tom Zanussi30350d62018-01-15 20:51:49 -06004839 if (!hist_data->remove || unregistered)
Tom Zanussiad42feb2018-01-15 20:51:45 -06004840 tracing_set_time_stamp_abs(file->tr, false);
4841 }
Tom Zanussi52a7f162016-03-03 12:54:57 -06004842}
4843
Tom Zanussi067fe032018-01-15 20:51:56 -06004844static bool hist_file_check_refs(struct trace_event_file *file)
4845{
4846 struct hist_trigger_data *hist_data;
4847 struct event_trigger_data *test;
4848
4849 list_for_each_entry_rcu(test, &file->triggers, list) {
4850 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
4851 hist_data = test->private_data;
4852 if (check_var_refs(hist_data))
4853 return true;
4854 }
4855 }
4856
4857 return false;
4858}
4859
Tom Zanussi52a7f162016-03-03 12:54:57 -06004860static void hist_unreg_all(struct trace_event_file *file)
4861{
Steven Rostedt47c18562016-06-29 19:55:59 -05004862 struct event_trigger_data *test, *n;
Tom Zanussiad42feb2018-01-15 20:51:45 -06004863 struct hist_trigger_data *hist_data;
Tom Zanussi4b147932018-01-15 20:51:58 -06004864 struct synth_event *se;
4865 const char *se_name;
Tom Zanussi52a7f162016-03-03 12:54:57 -06004866
Tom Zanussi067fe032018-01-15 20:51:56 -06004867 if (hist_file_check_refs(file))
4868 return;
4869
Steven Rostedt47c18562016-06-29 19:55:59 -05004870 list_for_each_entry_safe(test, n, &file->triggers, list) {
Tom Zanussi52a7f162016-03-03 12:54:57 -06004871 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
Tom Zanussiad42feb2018-01-15 20:51:45 -06004872 hist_data = test->private_data;
Tom Zanussi52a7f162016-03-03 12:54:57 -06004873 list_del_rcu(&test->list);
4874 trace_event_trigger_enable_disable(file, 0);
Tom Zanussi4b147932018-01-15 20:51:58 -06004875
4876 mutex_lock(&synth_event_mutex);
4877 se_name = trace_event_name(file->event_call);
4878 se = find_synth_event(se_name);
4879 if (se)
4880 se->ref--;
4881 mutex_unlock(&synth_event_mutex);
4882
Tom Zanussi52a7f162016-03-03 12:54:57 -06004883 update_cond_flag(file);
Tom Zanussiad42feb2018-01-15 20:51:45 -06004884 if (hist_data->enable_timestamps)
4885 tracing_set_time_stamp_abs(file->tr, false);
Tom Zanussi52a7f162016-03-03 12:54:57 -06004886 if (test->ops->free)
4887 test->ops->free(test->ops, test);
4888 }
4889 }
4890}
4891
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004892static int event_hist_trigger_func(struct event_command *cmd_ops,
4893 struct trace_event_file *file,
4894 char *glob, char *cmd, char *param)
4895{
4896 unsigned int hist_trigger_bits = TRACING_MAP_BITS_DEFAULT;
4897 struct event_trigger_data *trigger_data;
4898 struct hist_trigger_attrs *attrs;
4899 struct event_trigger_ops *trigger_ops;
4900 struct hist_trigger_data *hist_data;
Tom Zanussi4b147932018-01-15 20:51:58 -06004901 struct synth_event *se;
4902 const char *se_name;
Tom Zanussi30350d62018-01-15 20:51:49 -06004903 bool remove = false;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004904 char *trigger;
4905 int ret = 0;
4906
4907 if (!param)
4908 return -EINVAL;
4909
Tom Zanussi30350d62018-01-15 20:51:49 -06004910 if (glob[0] == '!')
4911 remove = true;
4912
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004913 /* separate the trigger from the filter (k:v [if filter]) */
4914 trigger = strsep(&param, " \t");
4915 if (!trigger)
4916 return -EINVAL;
4917
4918 attrs = parse_hist_trigger_attrs(trigger);
4919 if (IS_ERR(attrs))
4920 return PTR_ERR(attrs);
4921
4922 if (attrs->map_bits)
4923 hist_trigger_bits = attrs->map_bits;
4924
Tom Zanussi30350d62018-01-15 20:51:49 -06004925 hist_data = create_hist_data(hist_trigger_bits, attrs, file, remove);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004926 if (IS_ERR(hist_data)) {
4927 destroy_hist_trigger_attrs(attrs);
4928 return PTR_ERR(hist_data);
4929 }
4930
4931 trigger_ops = cmd_ops->get_trigger_ops(cmd, trigger);
4932
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004933 trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL);
Tom Zanussi4b147932018-01-15 20:51:58 -06004934 if (!trigger_data) {
4935 ret = -ENOMEM;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004936 goto out_free;
Tom Zanussi4b147932018-01-15 20:51:58 -06004937 }
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004938
4939 trigger_data->count = -1;
4940 trigger_data->ops = trigger_ops;
4941 trigger_data->cmd_ops = cmd_ops;
4942
4943 INIT_LIST_HEAD(&trigger_data->list);
4944 RCU_INIT_POINTER(trigger_data->filter, NULL);
4945
4946 trigger_data->private_data = hist_data;
4947
Tom Zanussi52a7f162016-03-03 12:54:57 -06004948 /* if param is non-empty, it's supposed to be a filter */
4949 if (param && cmd_ops->set_filter) {
4950 ret = cmd_ops->set_filter(param, trigger_data, file);
4951 if (ret < 0)
4952 goto out_free;
4953 }
4954
Tom Zanussi30350d62018-01-15 20:51:49 -06004955 if (remove) {
Tom Zanussi4b147932018-01-15 20:51:58 -06004956 if (!have_hist_trigger_match(trigger_data, file))
4957 goto out_free;
4958
Tom Zanussi067fe032018-01-15 20:51:56 -06004959 if (hist_trigger_check_refs(trigger_data, file)) {
4960 ret = -EBUSY;
4961 goto out_free;
4962 }
4963
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004964 cmd_ops->unreg(glob+1, trigger_ops, trigger_data, file);
Tom Zanussi4b147932018-01-15 20:51:58 -06004965
4966 mutex_lock(&synth_event_mutex);
4967 se_name = trace_event_name(file->event_call);
4968 se = find_synth_event(se_name);
4969 if (se)
4970 se->ref--;
4971 mutex_unlock(&synth_event_mutex);
4972
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004973 ret = 0;
4974 goto out_free;
4975 }
4976
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004977 ret = cmd_ops->reg(glob, trigger_ops, trigger_data, file);
4978 /*
4979 * The above returns on success the # of triggers registered,
4980 * but if it didn't register any it returns zero. Consider no
4981 * triggers registered a failure too.
4982 */
4983 if (!ret) {
Tom Zanussie86ae9b2016-03-03 12:54:47 -06004984 if (!(attrs->pause || attrs->cont || attrs->clear))
Tom Zanussi83e99912016-03-03 12:54:46 -06004985 ret = -ENOENT;
Tom Zanussi7ef224d2016-03-03 12:54:42 -06004986 goto out_free;
4987 } else if (ret < 0)
4988 goto out_free;
Tom Zanussi067fe032018-01-15 20:51:56 -06004989
4990 if (get_named_trigger_data(trigger_data))
4991 goto enable;
4992
4993 if (has_hist_vars(hist_data))
4994 save_hist_vars(hist_data);
4995
Tom Zanussi0212e2a2018-01-15 20:51:57 -06004996 ret = create_actions(hist_data, file);
4997 if (ret)
4998 goto out_unreg;
4999
Tom Zanussi067fe032018-01-15 20:51:56 -06005000 ret = tracing_map_init(hist_data->map);
5001 if (ret)
5002 goto out_unreg;
5003enable:
5004 ret = hist_trigger_enable(trigger_data, file);
5005 if (ret)
5006 goto out_unreg;
5007
Tom Zanussi4b147932018-01-15 20:51:58 -06005008 mutex_lock(&synth_event_mutex);
5009 se_name = trace_event_name(file->event_call);
5010 se = find_synth_event(se_name);
5011 if (se)
5012 se->ref++;
5013 mutex_unlock(&synth_event_mutex);
5014
Tom Zanussi7ef224d2016-03-03 12:54:42 -06005015 /* Just return zero, not the number of registered triggers */
5016 ret = 0;
5017 out:
5018 return ret;
Tom Zanussi067fe032018-01-15 20:51:56 -06005019 out_unreg:
5020 cmd_ops->unreg(glob+1, trigger_ops, trigger_data, file);
Tom Zanussi7ef224d2016-03-03 12:54:42 -06005021 out_free:
5022 if (cmd_ops->set_filter)
5023 cmd_ops->set_filter(NULL, trigger_data, NULL);
5024
Tom Zanussi067fe032018-01-15 20:51:56 -06005025 remove_hist_vars(hist_data);
5026
Tom Zanussi7ef224d2016-03-03 12:54:42 -06005027 kfree(trigger_data);
5028
5029 destroy_hist_data(hist_data);
5030 goto out;
5031}
5032
5033static struct event_command trigger_hist_cmd = {
5034 .name = "hist",
5035 .trigger_type = ETT_EVENT_HIST,
5036 .flags = EVENT_CMD_FL_NEEDS_REC,
5037 .func = event_hist_trigger_func,
5038 .reg = hist_register_trigger,
Tom Zanussi52a7f162016-03-03 12:54:57 -06005039 .unreg = hist_unregister_trigger,
5040 .unreg_all = hist_unreg_all,
Tom Zanussi7ef224d2016-03-03 12:54:42 -06005041 .get_trigger_ops = event_hist_get_trigger_ops,
5042 .set_filter = set_trigger_filter,
5043};
5044
5045__init int register_trigger_hist_cmd(void)
5046{
5047 int ret;
5048
5049 ret = register_event_command(&trigger_hist_cmd);
5050 WARN_ON(ret < 0);
5051
5052 return ret;
5053}
Tom Zanussid0bad492016-03-03 12:54:55 -06005054
5055static void
Tom Zanussi1ac4f512018-01-15 20:51:42 -06005056hist_enable_trigger(struct event_trigger_data *data, void *rec,
5057 struct ring_buffer_event *event)
Tom Zanussid0bad492016-03-03 12:54:55 -06005058{
5059 struct enable_trigger_data *enable_data = data->private_data;
5060 struct event_trigger_data *test;
5061
5062 list_for_each_entry_rcu(test, &enable_data->file->triggers, list) {
5063 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
5064 if (enable_data->enable)
5065 test->paused = false;
5066 else
5067 test->paused = true;
Tom Zanussid0bad492016-03-03 12:54:55 -06005068 }
5069 }
5070}
5071
5072static void
Tom Zanussi1ac4f512018-01-15 20:51:42 -06005073hist_enable_count_trigger(struct event_trigger_data *data, void *rec,
5074 struct ring_buffer_event *event)
Tom Zanussid0bad492016-03-03 12:54:55 -06005075{
5076 if (!data->count)
5077 return;
5078
5079 if (data->count != -1)
5080 (data->count)--;
5081
Tom Zanussi1ac4f512018-01-15 20:51:42 -06005082 hist_enable_trigger(data, rec, event);
Tom Zanussid0bad492016-03-03 12:54:55 -06005083}
5084
5085static struct event_trigger_ops hist_enable_trigger_ops = {
5086 .func = hist_enable_trigger,
5087 .print = event_enable_trigger_print,
5088 .init = event_trigger_init,
5089 .free = event_enable_trigger_free,
5090};
5091
5092static struct event_trigger_ops hist_enable_count_trigger_ops = {
5093 .func = hist_enable_count_trigger,
5094 .print = event_enable_trigger_print,
5095 .init = event_trigger_init,
5096 .free = event_enable_trigger_free,
5097};
5098
5099static struct event_trigger_ops hist_disable_trigger_ops = {
5100 .func = hist_enable_trigger,
5101 .print = event_enable_trigger_print,
5102 .init = event_trigger_init,
5103 .free = event_enable_trigger_free,
5104};
5105
5106static struct event_trigger_ops hist_disable_count_trigger_ops = {
5107 .func = hist_enable_count_trigger,
5108 .print = event_enable_trigger_print,
5109 .init = event_trigger_init,
5110 .free = event_enable_trigger_free,
5111};
5112
5113static struct event_trigger_ops *
5114hist_enable_get_trigger_ops(char *cmd, char *param)
5115{
5116 struct event_trigger_ops *ops;
5117 bool enable;
5118
5119 enable = (strcmp(cmd, ENABLE_HIST_STR) == 0);
5120
5121 if (enable)
5122 ops = param ? &hist_enable_count_trigger_ops :
5123 &hist_enable_trigger_ops;
5124 else
5125 ops = param ? &hist_disable_count_trigger_ops :
5126 &hist_disable_trigger_ops;
5127
5128 return ops;
5129}
5130
Tom Zanussi52a7f162016-03-03 12:54:57 -06005131static void hist_enable_unreg_all(struct trace_event_file *file)
5132{
Steven Rostedt47c18562016-06-29 19:55:59 -05005133 struct event_trigger_data *test, *n;
Tom Zanussi52a7f162016-03-03 12:54:57 -06005134
Steven Rostedt47c18562016-06-29 19:55:59 -05005135 list_for_each_entry_safe(test, n, &file->triggers, list) {
Tom Zanussi52a7f162016-03-03 12:54:57 -06005136 if (test->cmd_ops->trigger_type == ETT_HIST_ENABLE) {
5137 list_del_rcu(&test->list);
5138 update_cond_flag(file);
5139 trace_event_trigger_enable_disable(file, 0);
5140 if (test->ops->free)
5141 test->ops->free(test->ops, test);
5142 }
5143 }
5144}
5145
Tom Zanussid0bad492016-03-03 12:54:55 -06005146static struct event_command trigger_hist_enable_cmd = {
5147 .name = ENABLE_HIST_STR,
5148 .trigger_type = ETT_HIST_ENABLE,
5149 .func = event_enable_trigger_func,
5150 .reg = event_enable_register_trigger,
5151 .unreg = event_enable_unregister_trigger,
Tom Zanussi52a7f162016-03-03 12:54:57 -06005152 .unreg_all = hist_enable_unreg_all,
Tom Zanussid0bad492016-03-03 12:54:55 -06005153 .get_trigger_ops = hist_enable_get_trigger_ops,
5154 .set_filter = set_trigger_filter,
5155};
5156
5157static struct event_command trigger_hist_disable_cmd = {
5158 .name = DISABLE_HIST_STR,
5159 .trigger_type = ETT_HIST_ENABLE,
5160 .func = event_enable_trigger_func,
5161 .reg = event_enable_register_trigger,
5162 .unreg = event_enable_unregister_trigger,
Tom Zanussi52a7f162016-03-03 12:54:57 -06005163 .unreg_all = hist_enable_unreg_all,
Tom Zanussid0bad492016-03-03 12:54:55 -06005164 .get_trigger_ops = hist_enable_get_trigger_ops,
5165 .set_filter = set_trigger_filter,
5166};
5167
5168static __init void unregister_trigger_hist_enable_disable_cmds(void)
5169{
5170 unregister_event_command(&trigger_hist_enable_cmd);
5171 unregister_event_command(&trigger_hist_disable_cmd);
5172}
5173
5174__init int register_trigger_hist_enable_disable_cmds(void)
5175{
5176 int ret;
5177
5178 ret = register_event_command(&trigger_hist_enable_cmd);
5179 if (WARN_ON(ret < 0))
5180 return ret;
5181 ret = register_event_command(&trigger_hist_disable_cmd);
5182 if (WARN_ON(ret < 0))
5183 unregister_trigger_hist_enable_disable_cmds();
5184
5185 return ret;
5186}
Tom Zanussi4b147932018-01-15 20:51:58 -06005187
5188static __init int trace_events_hist_init(void)
5189{
5190 struct dentry *entry = NULL;
5191 struct dentry *d_tracer;
5192 int err = 0;
5193
5194 d_tracer = tracing_init_dentry();
5195 if (IS_ERR(d_tracer)) {
5196 err = PTR_ERR(d_tracer);
5197 goto err;
5198 }
5199
5200 entry = tracefs_create_file("synthetic_events", 0644, d_tracer,
5201 NULL, &synth_events_fops);
5202 if (!entry) {
5203 err = -ENODEV;
5204 goto err;
5205 }
5206
5207 return err;
5208 err:
5209 pr_warn("Could not create tracefs 'synthetic_events' entry\n");
5210
5211 return err;
5212}
5213
5214fs_initcall(trace_events_hist_init);