tracing: Add hist trigger support for clearing a trace
[linux-2.6-block.git] / kernel / trace / trace_events_hist.c
CommitLineData
7ef224d1
TZ
1/*
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>
22
23#include "tracing_map.h"
24#include "trace.h"
25
26struct hist_field;
27
28typedef u64 (*hist_field_fn_t) (struct hist_field *field, void *event);
29
30struct hist_field {
31 struct ftrace_event_field *field;
32 unsigned long flags;
33 hist_field_fn_t fn;
34 unsigned int size;
76a3b0c8 35 unsigned int offset;
7ef224d1
TZ
36};
37
38static u64 hist_field_counter(struct hist_field *field, void *event)
39{
40 return 1;
41}
42
43static u64 hist_field_string(struct hist_field *hist_field, void *event)
44{
45 char *addr = (char *)(event + hist_field->field->offset);
46
47 return (u64)(unsigned long)addr;
48}
49
50#define DEFINE_HIST_FIELD_FN(type) \
51static u64 hist_field_##type(struct hist_field *hist_field, void *event)\
52{ \
53 type *addr = (type *)(event + hist_field->field->offset); \
54 \
55 return (u64)*addr; \
56}
57
58DEFINE_HIST_FIELD_FN(s64);
59DEFINE_HIST_FIELD_FN(u64);
60DEFINE_HIST_FIELD_FN(s32);
61DEFINE_HIST_FIELD_FN(u32);
62DEFINE_HIST_FIELD_FN(s16);
63DEFINE_HIST_FIELD_FN(u16);
64DEFINE_HIST_FIELD_FN(s8);
65DEFINE_HIST_FIELD_FN(u8);
66
67#define for_each_hist_field(i, hist_data) \
68 for ((i) = 0; (i) < (hist_data)->n_fields; (i)++)
69
70#define for_each_hist_val_field(i, hist_data) \
71 for ((i) = 0; (i) < (hist_data)->n_vals; (i)++)
72
73#define for_each_hist_key_field(i, hist_data) \
74 for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++)
75
76#define HITCOUNT_IDX 0
76a3b0c8 77#define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + sizeof(u64))
7ef224d1
TZ
78
79enum hist_field_flags {
80 HIST_FIELD_FL_HITCOUNT = 1,
81 HIST_FIELD_FL_KEY = 2,
82 HIST_FIELD_FL_STRING = 4,
83};
84
85struct hist_trigger_attrs {
86 char *keys_str;
f2606835 87 char *vals_str;
e62347d2 88 char *sort_key_str;
83e99914
TZ
89 bool pause;
90 bool cont;
e86ae9ba 91 bool clear;
7ef224d1
TZ
92 unsigned int map_bits;
93};
94
95struct hist_trigger_data {
96 struct hist_field *fields[TRACING_MAP_FIELDS_MAX];
97 unsigned int n_vals;
98 unsigned int n_keys;
99 unsigned int n_fields;
100 unsigned int key_size;
101 struct tracing_map_sort_key sort_keys[TRACING_MAP_SORT_KEYS_MAX];
102 unsigned int n_sort_keys;
103 struct trace_event_file *event_file;
104 struct hist_trigger_attrs *attrs;
105 struct tracing_map *map;
106};
107
108static hist_field_fn_t select_value_fn(int field_size, int field_is_signed)
109{
110 hist_field_fn_t fn = NULL;
111
112 switch (field_size) {
113 case 8:
114 if (field_is_signed)
115 fn = hist_field_s64;
116 else
117 fn = hist_field_u64;
118 break;
119 case 4:
120 if (field_is_signed)
121 fn = hist_field_s32;
122 else
123 fn = hist_field_u32;
124 break;
125 case 2:
126 if (field_is_signed)
127 fn = hist_field_s16;
128 else
129 fn = hist_field_u16;
130 break;
131 case 1:
132 if (field_is_signed)
133 fn = hist_field_s8;
134 else
135 fn = hist_field_u8;
136 break;
137 }
138
139 return fn;
140}
141
142static int parse_map_size(char *str)
143{
144 unsigned long size, map_bits;
145 int ret;
146
147 strsep(&str, "=");
148 if (!str) {
149 ret = -EINVAL;
150 goto out;
151 }
152
153 ret = kstrtoul(str, 0, &size);
154 if (ret)
155 goto out;
156
157 map_bits = ilog2(roundup_pow_of_two(size));
158 if (map_bits < TRACING_MAP_BITS_MIN ||
159 map_bits > TRACING_MAP_BITS_MAX)
160 ret = -EINVAL;
161 else
162 ret = map_bits;
163 out:
164 return ret;
165}
166
167static void destroy_hist_trigger_attrs(struct hist_trigger_attrs *attrs)
168{
169 if (!attrs)
170 return;
171
e62347d2 172 kfree(attrs->sort_key_str);
7ef224d1 173 kfree(attrs->keys_str);
f2606835 174 kfree(attrs->vals_str);
7ef224d1
TZ
175 kfree(attrs);
176}
177
178static struct hist_trigger_attrs *parse_hist_trigger_attrs(char *trigger_str)
179{
180 struct hist_trigger_attrs *attrs;
181 int ret = 0;
182
183 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
184 if (!attrs)
185 return ERR_PTR(-ENOMEM);
186
187 while (trigger_str) {
188 char *str = strsep(&trigger_str, ":");
189
190 if ((strncmp(str, "key=", strlen("key=")) == 0) ||
191 (strncmp(str, "keys=", strlen("keys=")) == 0))
192 attrs->keys_str = kstrdup(str, GFP_KERNEL);
f2606835
TZ
193 else if ((strncmp(str, "val=", strlen("val=")) == 0) ||
194 (strncmp(str, "vals=", strlen("vals=")) == 0) ||
195 (strncmp(str, "values=", strlen("values=")) == 0))
196 attrs->vals_str = kstrdup(str, GFP_KERNEL);
e62347d2
TZ
197 else if (strncmp(str, "sort=", strlen("sort=")) == 0)
198 attrs->sort_key_str = kstrdup(str, GFP_KERNEL);
83e99914
TZ
199 else if (strcmp(str, "pause") == 0)
200 attrs->pause = true;
201 else if ((strcmp(str, "cont") == 0) ||
202 (strcmp(str, "continue") == 0))
203 attrs->cont = true;
e86ae9ba
TZ
204 else if (strcmp(str, "clear") == 0)
205 attrs->clear = true;
7ef224d1
TZ
206 else if (strncmp(str, "size=", strlen("size=")) == 0) {
207 int map_bits = parse_map_size(str);
208
209 if (map_bits < 0) {
210 ret = map_bits;
211 goto free;
212 }
213 attrs->map_bits = map_bits;
214 } else {
215 ret = -EINVAL;
216 goto free;
217 }
218 }
219
220 if (!attrs->keys_str) {
221 ret = -EINVAL;
222 goto free;
223 }
224
225 return attrs;
226 free:
227 destroy_hist_trigger_attrs(attrs);
228
229 return ERR_PTR(ret);
230}
231
232static void destroy_hist_field(struct hist_field *hist_field)
233{
234 kfree(hist_field);
235}
236
237static struct hist_field *create_hist_field(struct ftrace_event_field *field,
238 unsigned long flags)
239{
240 struct hist_field *hist_field;
241
242 if (field && is_function_field(field))
243 return NULL;
244
245 hist_field = kzalloc(sizeof(struct hist_field), GFP_KERNEL);
246 if (!hist_field)
247 return NULL;
248
249 if (flags & HIST_FIELD_FL_HITCOUNT) {
250 hist_field->fn = hist_field_counter;
251 goto out;
252 }
253
254 if (is_string_field(field)) {
255 flags |= HIST_FIELD_FL_STRING;
256 hist_field->fn = hist_field_string;
257 } else {
258 hist_field->fn = select_value_fn(field->size,
259 field->is_signed);
260 if (!hist_field->fn) {
261 destroy_hist_field(hist_field);
262 return NULL;
263 }
264 }
265 out:
266 hist_field->field = field;
267 hist_field->flags = flags;
268
269 return hist_field;
270}
271
272static void destroy_hist_fields(struct hist_trigger_data *hist_data)
273{
274 unsigned int i;
275
276 for (i = 0; i < TRACING_MAP_FIELDS_MAX; i++) {
277 if (hist_data->fields[i]) {
278 destroy_hist_field(hist_data->fields[i]);
279 hist_data->fields[i] = NULL;
280 }
281 }
282}
283
284static int create_hitcount_val(struct hist_trigger_data *hist_data)
285{
286 hist_data->fields[HITCOUNT_IDX] =
287 create_hist_field(NULL, HIST_FIELD_FL_HITCOUNT);
288 if (!hist_data->fields[HITCOUNT_IDX])
289 return -ENOMEM;
290
291 hist_data->n_vals++;
292
293 if (WARN_ON(hist_data->n_vals > TRACING_MAP_VALS_MAX))
294 return -EINVAL;
295
296 return 0;
297}
298
f2606835
TZ
299static int create_val_field(struct hist_trigger_data *hist_data,
300 unsigned int val_idx,
301 struct trace_event_file *file,
302 char *field_str)
303{
304 struct ftrace_event_field *field = NULL;
305 unsigned long flags = 0;
306 int ret = 0;
307
308 if (WARN_ON(val_idx >= TRACING_MAP_VALS_MAX))
309 return -EINVAL;
310 field = trace_find_event_field(file->event_call, field_str);
311 if (!field) {
312 ret = -EINVAL;
313 goto out;
314 }
315
316 hist_data->fields[val_idx] = create_hist_field(field, flags);
317 if (!hist_data->fields[val_idx]) {
318 ret = -ENOMEM;
319 goto out;
320 }
321
322 ++hist_data->n_vals;
323
324 if (WARN_ON(hist_data->n_vals > TRACING_MAP_VALS_MAX))
325 ret = -EINVAL;
326 out:
327 return ret;
328}
329
7ef224d1
TZ
330static int create_val_fields(struct hist_trigger_data *hist_data,
331 struct trace_event_file *file)
332{
f2606835
TZ
333 char *fields_str, *field_str;
334 unsigned int i, j;
7ef224d1
TZ
335 int ret;
336
337 ret = create_hitcount_val(hist_data);
f2606835
TZ
338 if (ret)
339 goto out;
7ef224d1 340
f2606835
TZ
341 fields_str = hist_data->attrs->vals_str;
342 if (!fields_str)
343 goto out;
344
345 strsep(&fields_str, "=");
346 if (!fields_str)
347 goto out;
348
349 for (i = 0, j = 1; i < TRACING_MAP_VALS_MAX &&
350 j < TRACING_MAP_VALS_MAX; i++) {
351 field_str = strsep(&fields_str, ",");
352 if (!field_str)
353 break;
354 if (strcmp(field_str, "hitcount") == 0)
355 continue;
356 ret = create_val_field(hist_data, j++, file, field_str);
357 if (ret)
358 goto out;
359 }
360 if (fields_str && (strcmp(fields_str, "hitcount") != 0))
361 ret = -EINVAL;
362 out:
7ef224d1
TZ
363 return ret;
364}
365
366static int create_key_field(struct hist_trigger_data *hist_data,
367 unsigned int key_idx,
76a3b0c8 368 unsigned int key_offset,
7ef224d1
TZ
369 struct trace_event_file *file,
370 char *field_str)
371{
372 struct ftrace_event_field *field = NULL;
373 unsigned long flags = 0;
374 unsigned int key_size;
375 int ret = 0;
376
377 if (WARN_ON(key_idx >= TRACING_MAP_FIELDS_MAX))
378 return -EINVAL;
379
380 flags |= HIST_FIELD_FL_KEY;
381
382 field = trace_find_event_field(file->event_call, field_str);
383 if (!field) {
384 ret = -EINVAL;
385 goto out;
386 }
387
388 key_size = field->size;
389
390 hist_data->fields[key_idx] = create_hist_field(field, flags);
391 if (!hist_data->fields[key_idx]) {
392 ret = -ENOMEM;
393 goto out;
394 }
395
396 key_size = ALIGN(key_size, sizeof(u64));
397 hist_data->fields[key_idx]->size = key_size;
76a3b0c8
TZ
398 hist_data->fields[key_idx]->offset = key_offset;
399 hist_data->key_size += key_size;
7ef224d1
TZ
400 if (hist_data->key_size > HIST_KEY_SIZE_MAX) {
401 ret = -EINVAL;
402 goto out;
403 }
404
405 hist_data->n_keys++;
406
407 if (WARN_ON(hist_data->n_keys > TRACING_MAP_KEYS_MAX))
408 return -EINVAL;
409
410 ret = key_size;
411 out:
412 return ret;
413}
414
415static int create_key_fields(struct hist_trigger_data *hist_data,
416 struct trace_event_file *file)
417{
76a3b0c8 418 unsigned int i, key_offset = 0, n_vals = hist_data->n_vals;
7ef224d1
TZ
419 char *fields_str, *field_str;
420 int ret = -EINVAL;
421
422 fields_str = hist_data->attrs->keys_str;
423 if (!fields_str)
424 goto out;
425
426 strsep(&fields_str, "=");
427 if (!fields_str)
428 goto out;
429
76a3b0c8 430 for (i = n_vals; i < n_vals + TRACING_MAP_KEYS_MAX; i++) {
7ef224d1
TZ
431 field_str = strsep(&fields_str, ",");
432 if (!field_str)
433 break;
76a3b0c8
TZ
434 ret = create_key_field(hist_data, i, key_offset,
435 file, field_str);
7ef224d1
TZ
436 if (ret < 0)
437 goto out;
76a3b0c8 438 key_offset += ret;
7ef224d1
TZ
439 }
440 if (fields_str) {
441 ret = -EINVAL;
442 goto out;
443 }
444 ret = 0;
445 out:
446 return ret;
447}
448
449static int create_hist_fields(struct hist_trigger_data *hist_data,
450 struct trace_event_file *file)
451{
452 int ret;
453
454 ret = create_val_fields(hist_data, file);
455 if (ret)
456 goto out;
457
458 ret = create_key_fields(hist_data, file);
459 if (ret)
460 goto out;
461
462 hist_data->n_fields = hist_data->n_vals + hist_data->n_keys;
463 out:
464 return ret;
465}
466
e62347d2
TZ
467static int is_descending(const char *str)
468{
469 if (!str)
470 return 0;
471
472 if (strcmp(str, "descending") == 0)
473 return 1;
474
475 if (strcmp(str, "ascending") == 0)
476 return 0;
477
478 return -EINVAL;
479}
480
7ef224d1
TZ
481static int create_sort_keys(struct hist_trigger_data *hist_data)
482{
e62347d2
TZ
483 char *fields_str = hist_data->attrs->sort_key_str;
484 struct ftrace_event_field *field = NULL;
485 struct tracing_map_sort_key *sort_key;
486 int descending, ret = 0;
487 unsigned int i, j;
488
489 hist_data->n_sort_keys = 1; /* we always have at least one, hitcount */
490
491 if (!fields_str)
492 goto out;
493
494 strsep(&fields_str, "=");
495 if (!fields_str) {
496 ret = -EINVAL;
497 goto out;
498 }
499
500 for (i = 0; i < TRACING_MAP_SORT_KEYS_MAX; i++) {
501 char *field_str, *field_name;
502
503 sort_key = &hist_data->sort_keys[i];
504
505 field_str = strsep(&fields_str, ",");
506 if (!field_str) {
507 if (i == 0)
508 ret = -EINVAL;
509 break;
510 }
511
512 if ((i == TRACING_MAP_SORT_KEYS_MAX - 1) && fields_str) {
513 ret = -EINVAL;
514 break;
515 }
7ef224d1 516
e62347d2
TZ
517 field_name = strsep(&field_str, ".");
518 if (!field_name) {
519 ret = -EINVAL;
520 break;
521 }
522
523 if (strcmp(field_name, "hitcount") == 0) {
524 descending = is_descending(field_str);
525 if (descending < 0) {
526 ret = descending;
527 break;
528 }
529 sort_key->descending = descending;
530 continue;
531 }
7ef224d1 532
e62347d2
TZ
533 for (j = 1; j < hist_data->n_fields; j++) {
534 field = hist_data->fields[j]->field;
535 if (field && (strcmp(field_name, field->name) == 0)) {
536 sort_key->field_idx = j;
537 descending = is_descending(field_str);
538 if (descending < 0) {
539 ret = descending;
540 goto out;
541 }
542 sort_key->descending = descending;
543 break;
544 }
545 }
546 if (j == hist_data->n_fields) {
547 ret = -EINVAL;
548 break;
549 }
550 }
551 hist_data->n_sort_keys = i;
552 out:
7ef224d1
TZ
553 return ret;
554}
555
556static void destroy_hist_data(struct hist_trigger_data *hist_data)
557{
558 destroy_hist_trigger_attrs(hist_data->attrs);
559 destroy_hist_fields(hist_data);
560 tracing_map_destroy(hist_data->map);
561 kfree(hist_data);
562}
563
564static int create_tracing_map_fields(struct hist_trigger_data *hist_data)
565{
566 struct tracing_map *map = hist_data->map;
567 struct ftrace_event_field *field;
568 struct hist_field *hist_field;
569 unsigned int i, idx;
570
571 for_each_hist_field(i, hist_data) {
572 hist_field = hist_data->fields[i];
573 if (hist_field->flags & HIST_FIELD_FL_KEY) {
574 tracing_map_cmp_fn_t cmp_fn;
575
576 field = hist_field->field;
577
578 if (is_string_field(field))
579 cmp_fn = tracing_map_cmp_string;
580 else
581 cmp_fn = tracing_map_cmp_num(field->size,
582 field->is_signed);
76a3b0c8
TZ
583 idx = tracing_map_add_key_field(map,
584 hist_field->offset,
585 cmp_fn);
586
7ef224d1
TZ
587 } else
588 idx = tracing_map_add_sum_field(map);
589
590 if (idx < 0)
591 return idx;
592 }
593
594 return 0;
595}
596
597static struct hist_trigger_data *
598create_hist_data(unsigned int map_bits,
599 struct hist_trigger_attrs *attrs,
600 struct trace_event_file *file)
601{
602 struct hist_trigger_data *hist_data;
603 int ret = 0;
604
605 hist_data = kzalloc(sizeof(*hist_data), GFP_KERNEL);
606 if (!hist_data)
607 return ERR_PTR(-ENOMEM);
608
609 hist_data->attrs = attrs;
610
611 ret = create_hist_fields(hist_data, file);
612 if (ret)
613 goto free;
614
615 ret = create_sort_keys(hist_data);
616 if (ret)
617 goto free;
618
619 hist_data->map = tracing_map_create(map_bits, hist_data->key_size,
620 NULL, hist_data);
621 if (IS_ERR(hist_data->map)) {
622 ret = PTR_ERR(hist_data->map);
623 hist_data->map = NULL;
624 goto free;
625 }
626
627 ret = create_tracing_map_fields(hist_data);
628 if (ret)
629 goto free;
630
631 ret = tracing_map_init(hist_data->map);
632 if (ret)
633 goto free;
634
635 hist_data->event_file = file;
636 out:
637 return hist_data;
638 free:
639 hist_data->attrs = NULL;
640
641 destroy_hist_data(hist_data);
642
643 hist_data = ERR_PTR(ret);
644
645 goto out;
646}
647
648static void hist_trigger_elt_update(struct hist_trigger_data *hist_data,
649 struct tracing_map_elt *elt,
650 void *rec)
651{
652 struct hist_field *hist_field;
653 unsigned int i;
654 u64 hist_val;
655
656 for_each_hist_val_field(i, hist_data) {
657 hist_field = hist_data->fields[i];
658 hist_val = hist_field->fn(hist_field, rec);
659 tracing_map_update_sum(elt, i, hist_val);
660 }
661}
662
663static void event_hist_trigger(struct event_trigger_data *data, void *rec)
664{
665 struct hist_trigger_data *hist_data = data->private_data;
76a3b0c8 666 char compound_key[HIST_KEY_SIZE_MAX];
7ef224d1
TZ
667 struct hist_field *key_field;
668 struct tracing_map_elt *elt;
669 u64 field_contents;
670 void *key = NULL;
671 unsigned int i;
672
76a3b0c8
TZ
673 if (hist_data->n_keys > 1)
674 memset(compound_key, 0, hist_data->key_size);
675
7ef224d1
TZ
676 for_each_hist_key_field(i, hist_data) {
677 key_field = hist_data->fields[i];
678
679 field_contents = key_field->fn(key_field, rec);
680 if (key_field->flags & HIST_FIELD_FL_STRING)
681 key = (void *)(unsigned long)field_contents;
682 else
683 key = (void *)&field_contents;
76a3b0c8
TZ
684
685 if (hist_data->n_keys > 1) {
686 memcpy(compound_key + key_field->offset, key,
687 key_field->size);
688 }
7ef224d1
TZ
689 }
690
76a3b0c8
TZ
691 if (hist_data->n_keys > 1)
692 key = compound_key;
693
7ef224d1
TZ
694 elt = tracing_map_insert(hist_data->map, key);
695 if (elt)
696 hist_trigger_elt_update(hist_data, elt, rec);
697}
698
699static void
700hist_trigger_entry_print(struct seq_file *m,
701 struct hist_trigger_data *hist_data, void *key,
702 struct tracing_map_elt *elt)
703{
704 struct hist_field *key_field;
705 unsigned int i;
706 u64 uval;
707
708 seq_puts(m, "{ ");
709
710 for_each_hist_key_field(i, hist_data) {
711 key_field = hist_data->fields[i];
712
713 if (i > hist_data->n_vals)
714 seq_puts(m, ", ");
715
716 if (key_field->flags & HIST_FIELD_FL_STRING) {
717 seq_printf(m, "%s: %-50s", key_field->field->name,
76a3b0c8 718 (char *)(key + key_field->offset));
7ef224d1 719 } else {
76a3b0c8
TZ
720 uval = *(u64 *)(key + key_field->offset);
721 seq_printf(m, "%s: %10llu", key_field->field->name,
722 uval);
7ef224d1
TZ
723 }
724 }
725
726 seq_puts(m, " }");
727
728 seq_printf(m, " hitcount: %10llu",
729 tracing_map_read_sum(elt, HITCOUNT_IDX));
730
f2606835
TZ
731 for (i = 1; i < hist_data->n_vals; i++) {
732 seq_printf(m, " %s: %10llu",
733 hist_data->fields[i]->field->name,
734 tracing_map_read_sum(elt, i));
735 }
736
7ef224d1
TZ
737 seq_puts(m, "\n");
738}
739
740static int print_entries(struct seq_file *m,
741 struct hist_trigger_data *hist_data)
742{
743 struct tracing_map_sort_entry **sort_entries = NULL;
744 struct tracing_map *map = hist_data->map;
745 unsigned int i, n_entries;
746
747 n_entries = tracing_map_sort_entries(map, hist_data->sort_keys,
748 hist_data->n_sort_keys,
749 &sort_entries);
750 if (n_entries < 0)
751 return n_entries;
752
753 for (i = 0; i < n_entries; i++)
754 hist_trigger_entry_print(m, hist_data,
755 sort_entries[i]->key,
756 sort_entries[i]->elt);
757
758 tracing_map_destroy_sort_entries(sort_entries, n_entries);
759
760 return n_entries;
761}
762
763static int hist_show(struct seq_file *m, void *v)
764{
765 struct event_trigger_data *test, *data = NULL;
766 struct trace_event_file *event_file;
767 struct hist_trigger_data *hist_data;
768 int n_entries, ret = 0;
769
770 mutex_lock(&event_mutex);
771
772 event_file = event_file_data(m->private);
773 if (unlikely(!event_file)) {
774 ret = -ENODEV;
775 goto out_unlock;
776 }
777
778 list_for_each_entry_rcu(test, &event_file->triggers, list) {
779 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
780 data = test;
781 break;
782 }
783 }
784 if (!data)
785 goto out_unlock;
786
787 seq_puts(m, "# event histogram\n#\n# trigger info: ");
788 data->ops->print(m, data->ops, data);
789 seq_puts(m, "\n");
790
791 hist_data = data->private_data;
792 n_entries = print_entries(m, hist_data);
793 if (n_entries < 0) {
794 ret = n_entries;
795 n_entries = 0;
796 }
797
798 seq_printf(m, "\nTotals:\n Hits: %llu\n Entries: %u\n Dropped: %llu\n",
799 (u64)atomic64_read(&hist_data->map->hits),
800 n_entries, (u64)atomic64_read(&hist_data->map->drops));
801 out_unlock:
802 mutex_unlock(&event_mutex);
803
804 return ret;
805}
806
807static int event_hist_open(struct inode *inode, struct file *file)
808{
809 return single_open(file, hist_show, file);
810}
811
812const struct file_operations event_hist_fops = {
813 .open = event_hist_open,
814 .read = seq_read,
815 .llseek = seq_lseek,
816 .release = single_release,
817};
818
819static void hist_field_print(struct seq_file *m, struct hist_field *hist_field)
820{
821 seq_printf(m, "%s", hist_field->field->name);
822}
823
824static int event_hist_trigger_print(struct seq_file *m,
825 struct event_trigger_ops *ops,
826 struct event_trigger_data *data)
827{
828 struct hist_trigger_data *hist_data = data->private_data;
829 struct hist_field *key_field;
830 unsigned int i;
831
832 seq_puts(m, "hist:keys=");
833
834 for_each_hist_key_field(i, hist_data) {
835 key_field = hist_data->fields[i];
836
837 if (i > hist_data->n_vals)
838 seq_puts(m, ",");
839
840 hist_field_print(m, key_field);
841 }
842
843 seq_puts(m, ":vals=");
f2606835
TZ
844
845 for_each_hist_val_field(i, hist_data) {
846 if (i == HITCOUNT_IDX)
847 seq_puts(m, "hitcount");
848 else {
849 seq_puts(m, ",");
850 hist_field_print(m, hist_data->fields[i]);
851 }
852 }
7ef224d1
TZ
853
854 seq_puts(m, ":sort=");
e62347d2
TZ
855
856 for (i = 0; i < hist_data->n_sort_keys; i++) {
857 struct tracing_map_sort_key *sort_key;
858
859 sort_key = &hist_data->sort_keys[i];
860
861 if (i > 0)
862 seq_puts(m, ",");
863
864 if (sort_key->field_idx == HITCOUNT_IDX)
865 seq_puts(m, "hitcount");
866 else {
867 unsigned int idx = sort_key->field_idx;
868
869 if (WARN_ON(idx >= TRACING_MAP_FIELDS_MAX))
870 return -EINVAL;
871
872 hist_field_print(m, hist_data->fields[idx]);
873 }
874
875 if (sort_key->descending)
876 seq_puts(m, ".descending");
877 }
7ef224d1
TZ
878
879 seq_printf(m, ":size=%u", (1 << hist_data->map->map_bits));
880
881 if (data->filter_str)
882 seq_printf(m, " if %s", data->filter_str);
883
83e99914
TZ
884 if (data->paused)
885 seq_puts(m, " [paused]");
886 else
887 seq_puts(m, " [active]");
7ef224d1
TZ
888
889 seq_putc(m, '\n');
890
891 return 0;
892}
893
894static void event_hist_trigger_free(struct event_trigger_ops *ops,
895 struct event_trigger_data *data)
896{
897 struct hist_trigger_data *hist_data = data->private_data;
898
899 if (WARN_ON_ONCE(data->ref <= 0))
900 return;
901
902 data->ref--;
903 if (!data->ref) {
904 trigger_data_free(data);
905 destroy_hist_data(hist_data);
906 }
907}
908
909static struct event_trigger_ops event_hist_trigger_ops = {
910 .func = event_hist_trigger,
911 .print = event_hist_trigger_print,
912 .init = event_trigger_init,
913 .free = event_hist_trigger_free,
914};
915
916static struct event_trigger_ops *event_hist_get_trigger_ops(char *cmd,
917 char *param)
918{
919 return &event_hist_trigger_ops;
920}
921
e86ae9ba
TZ
922static void hist_clear(struct event_trigger_data *data)
923{
924 struct hist_trigger_data *hist_data = data->private_data;
925 bool paused;
926
927 paused = data->paused;
928 data->paused = true;
929
930 synchronize_sched();
931
932 tracing_map_clear(hist_data->map);
933
934 data->paused = paused;
935}
936
7ef224d1
TZ
937static int hist_register_trigger(char *glob, struct event_trigger_ops *ops,
938 struct event_trigger_data *data,
939 struct trace_event_file *file)
940{
83e99914 941 struct hist_trigger_data *hist_data = data->private_data;
7ef224d1
TZ
942 struct event_trigger_data *test;
943 int ret = 0;
944
945 list_for_each_entry_rcu(test, &file->triggers, list) {
946 if (test->cmd_ops->trigger_type == ETT_EVENT_HIST) {
83e99914
TZ
947 if (hist_data->attrs->pause)
948 test->paused = true;
949 else if (hist_data->attrs->cont)
950 test->paused = false;
e86ae9ba
TZ
951 else if (hist_data->attrs->clear)
952 hist_clear(test);
83e99914
TZ
953 else
954 ret = -EEXIST;
7ef224d1
TZ
955 goto out;
956 }
957 }
958
e86ae9ba 959 if (hist_data->attrs->cont || hist_data->attrs->clear) {
83e99914
TZ
960 ret = -ENOENT;
961 goto out;
962 }
963
964 if (hist_data->attrs->pause)
965 data->paused = true;
966
7ef224d1
TZ
967 if (data->ops->init) {
968 ret = data->ops->init(data->ops, data);
969 if (ret < 0)
970 goto out;
971 }
972
973 list_add_rcu(&data->list, &file->triggers);
974 ret++;
975
976 update_cond_flag(file);
977 if (trace_event_trigger_enable_disable(file, 1) < 0) {
978 list_del_rcu(&data->list);
979 update_cond_flag(file);
980 ret--;
981 }
982 out:
983 return ret;
984}
985
986static int event_hist_trigger_func(struct event_command *cmd_ops,
987 struct trace_event_file *file,
988 char *glob, char *cmd, char *param)
989{
990 unsigned int hist_trigger_bits = TRACING_MAP_BITS_DEFAULT;
991 struct event_trigger_data *trigger_data;
992 struct hist_trigger_attrs *attrs;
993 struct event_trigger_ops *trigger_ops;
994 struct hist_trigger_data *hist_data;
995 char *trigger;
996 int ret = 0;
997
998 if (!param)
999 return -EINVAL;
1000
1001 /* separate the trigger from the filter (k:v [if filter]) */
1002 trigger = strsep(&param, " \t");
1003 if (!trigger)
1004 return -EINVAL;
1005
1006 attrs = parse_hist_trigger_attrs(trigger);
1007 if (IS_ERR(attrs))
1008 return PTR_ERR(attrs);
1009
1010 if (attrs->map_bits)
1011 hist_trigger_bits = attrs->map_bits;
1012
1013 hist_data = create_hist_data(hist_trigger_bits, attrs, file);
1014 if (IS_ERR(hist_data)) {
1015 destroy_hist_trigger_attrs(attrs);
1016 return PTR_ERR(hist_data);
1017 }
1018
1019 trigger_ops = cmd_ops->get_trigger_ops(cmd, trigger);
1020
1021 ret = -ENOMEM;
1022 trigger_data = kzalloc(sizeof(*trigger_data), GFP_KERNEL);
1023 if (!trigger_data)
1024 goto out_free;
1025
1026 trigger_data->count = -1;
1027 trigger_data->ops = trigger_ops;
1028 trigger_data->cmd_ops = cmd_ops;
1029
1030 INIT_LIST_HEAD(&trigger_data->list);
1031 RCU_INIT_POINTER(trigger_data->filter, NULL);
1032
1033 trigger_data->private_data = hist_data;
1034
1035 if (glob[0] == '!') {
1036 cmd_ops->unreg(glob+1, trigger_ops, trigger_data, file);
1037 ret = 0;
1038 goto out_free;
1039 }
1040
1041 if (!param) /* if param is non-empty, it's supposed to be a filter */
1042 goto out_reg;
1043
1044 if (!cmd_ops->set_filter)
1045 goto out_reg;
1046
1047 ret = cmd_ops->set_filter(param, trigger_data, file);
1048 if (ret < 0)
1049 goto out_free;
1050 out_reg:
1051 ret = cmd_ops->reg(glob, trigger_ops, trigger_data, file);
1052 /*
1053 * The above returns on success the # of triggers registered,
1054 * but if it didn't register any it returns zero. Consider no
1055 * triggers registered a failure too.
1056 */
1057 if (!ret) {
e86ae9ba 1058 if (!(attrs->pause || attrs->cont || attrs->clear))
83e99914 1059 ret = -ENOENT;
7ef224d1
TZ
1060 goto out_free;
1061 } else if (ret < 0)
1062 goto out_free;
1063 /* Just return zero, not the number of registered triggers */
1064 ret = 0;
1065 out:
1066 return ret;
1067 out_free:
1068 if (cmd_ops->set_filter)
1069 cmd_ops->set_filter(NULL, trigger_data, NULL);
1070
1071 kfree(trigger_data);
1072
1073 destroy_hist_data(hist_data);
1074 goto out;
1075}
1076
1077static struct event_command trigger_hist_cmd = {
1078 .name = "hist",
1079 .trigger_type = ETT_EVENT_HIST,
1080 .flags = EVENT_CMD_FL_NEEDS_REC,
1081 .func = event_hist_trigger_func,
1082 .reg = hist_register_trigger,
1083 .unreg = unregister_trigger,
1084 .get_trigger_ops = event_hist_get_trigger_ops,
1085 .set_filter = set_trigger_filter,
1086};
1087
1088__init int register_trigger_hist_cmd(void)
1089{
1090 int ret;
1091
1092 ret = register_event_command(&trigger_hist_cmd);
1093 WARN_ON(ret < 0);
1094
1095 return ret;
1096}