History

Merge tag 'trace-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull tracing updates from Steven Rostedt: - Remove a redundant IS_ERR() check trace_pipe_open() already checks for IS_ERR() and does it again in the return path. Remove the return check. - Export seq_buf_putmem_hex() to allow kunit tests against them To add Kunit tests on seq_buf_putmem_hex(), it needs to be exported. - Replace strcat() and strcpy() with seq_buf() logic The code for synthetic events uses a series of strcat() and strcpy() which can be error prone. Replace them with seq_buf() logic that does all the necessary bound checking. - Add a lockdep rcu_is_watching() to trace_##event##_enabled() call The trace_##event##_enabled() is a static branch that is true if the "event" is enabled. But this can hide bugs if this logic is in a location where RCU is disabled and not "watching". It would only trigger if lockdep is enabled and the event is enabled. Add a "rcu_is_watching()" warning if lockdep is enabled in that helper function to trigger regardless if the event is enabled or not. - Remove the local variable in the trace_printk() macro For name space integrity, remove the _______STR variable in the trace_printk() macro for using the sizeof() macro directly. - Use guard()s for the trace_recursion_record.c file - Fix typo in a comment of eventfs_callback() kerneldoc - Use trace_call__##event() in events within trace_##event##_enabled() A couple of events are called within an if block guarded by trace_##event##_enabled(). That is a static key that is only enabled when the event is enabled. The trace_call_##event() calls the tracepoint code directly without adding a redundant static key for that check. - Allow perf to read synthetic events Currently, perf does not have the ability to enable a synthetic event. If it does, it will either cause a kernel warning or error with "No such device". Synthetic events are not much different than kprobes and perf can handle fine with a few modifications. - Replace printk(KERN_WARNING ...) with pr_warn() - Replace krealloc() on an array with krealloc_array() - Fix README file path name for synthetic events - Change tracing_map tracing_map_array to use a flexible array Instead of allocating a separate pointer to hold the pages field of tracing_map_array, allocate the pages field as a flexible array when allocating the structure. - Fold trace_iterator_increment() into trace_find_next_entry_inc() The function trace_iterator_increment() was only used by trace_find_next_entry_inc(). It's not big enough to be a helper function for one user. Fold it into its caller. - Make field_var_str field a flexible array of hist_elt_data Instead of allocating a separate pointer for the field_var_str array of the hist_elt_data structure, allocate it as a flexible array when allocating the structure. - Disable KCOV for trace_irqsoff.c Like trace_preemptirq.c, trace_irqsoff.c has code that will crash when KCOV is enabled on ARM. The irqsoff tracing can be called on ARM because the irqsoff tracing code can be run from early interrupt code and produce coverage unrelated to syscall inputs. - Fix warning in __unregister_ftrace_function() called by perf Perf calls unregister_ftrace_function() without checking if its ftrace_ops has already been unregistered. There's an error path where on clean up it will unregister the ftrace_ops even if it wasn't registered and causes a warning. * tag 'trace-v7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: perf/ftrace: Fix WARNING in __unregister_ftrace_function tracing: Disable KCOV instrumentation for trace_irqsoff.o tracing: Turn hist_elt_data field_var_str into a flexible array tracing: Move trace_iterator_increment() into trace_find_next_entry_inc() tracing: Simplify pages allocation for tracing_map logic tracing: Fix README path for synthetic_events tracing: Use krealloc_array() for trace option array growth tracing/branch: Use pr_warn() instead of printk(KERN_WARNING) tracing: Allow perf to read synthetic events HID: Use trace_call__##name() at guarded tracepoint call sites cpufreq: amd-pstate: Use trace_call__##name() at guarded tracepoint call site tracefs: Fix typo in a comment of eventfs_callback() kerneldoc tracing: Switch trace_recursion_record.c code over to use guard() tracing: Remove local variable for argument detection from trace_printk() tracepoint: Add lockdep rcu_is_watching() check to trace_##name##_enabled() tracing: Bound synthetic-field strings with seq_buf seq_buf: Export seq_buf_putmem_hex() and add KUnit tests tracing: Remove redundant IS_ERR() check in trace_pipe_open()

Linus Torvalds committed 4 months ago

Commit 23b5d042 parents 8c13415 958112317 files · +222 −113Browse files

Showing the changes to kernel (10 of 17 files). Show all

Unified · Split

10 files
  1. kernel/trace/Makefile +3 −2
  2. kernel/trace/trace.c +11 −14
  3. kernel/trace/trace_branch.c +3 −6
  4. kernel/trace/trace_event_perf.c +11 −1
  5. kernel/trace/trace_events_hist.c +40 −32
  6. kernel/trace/trace_events_synth.c +94 −27
  7. kernel/trace/trace_recursion_record.c +3 −5
  8. kernel/trace/trace_remote.c +1 −1
  9. kernel/trace/tracing_map.c +11 −19
  10. kernel/trace/tracing_map.h +1 −1
kernel/trace/Makefile+3−2
@@ -48,9 +48,10 @@ ifdef CONFIG_GCOV_PROFILE_FTRACE · 47 unmodified lines
48GCOV_PROFILE := y48GCOV_PROFILE := y
49endif49endif
50 50
51# Functions in this file could be invoked from early interrupt51# Functions in these files can run from IRQ entry before hardirq context
52# code and produce random code coverage.52# is visible to KCOV, and produce coverage unrelated to syscall inputs.
53KCOV_INSTRUMENT_trace_preemptirq.o := n53KCOV_INSTRUMENT_trace_preemptirq.o := n
54KCOV_INSTRUMENT_trace_irqsoff.o := n
54 55
55CFLAGS_bpf_trace.o := -I$(src)56CFLAGS_bpf_trace.o := -I$(src)
56 57
kernel/trace/trace.c+11−14
@@ -2338,15 +2338,6 @@ void trace_last_func_repeats(struct trace_array *tr, · 2337 unmodified lines
2338 __buffer_unlock_commit(buffer, event);2338 __buffer_unlock_commit(buffer, event);
2339}2339}
2340 2340
2341static void trace_iterator_increment(struct trace_iterator *iter)
2342{
2343 struct ring_buffer_iter *buf_iter = trace_buffer_iter(iter, iter->cpu);
2344
2345 iter->idx++;
2346 if (buf_iter)
2347 ring_buffer_iter_advance(buf_iter);
2348}
2349
2350static struct trace_entry *2341static struct trace_entry *
2351peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts,2342peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts,
2352 unsigned long *lost_events)2343 unsigned long *lost_events)
@@ -2676,11 +2667,17 @@ struct trace_entry *trace_find_next_entry(struct trace_iterator *iter, · 323 unmodified lines
2676/* Find the next real entry, and increment the iterator to the next entry */2667/* Find the next real entry, and increment the iterator to the next entry */
2677void *trace_find_next_entry_inc(struct trace_iterator *iter)2668void *trace_find_next_entry_inc(struct trace_iterator *iter)
2678{2669{
2670 struct ring_buffer_iter *buf_iter;
2671
2679 iter->ent = __find_next_entry(iter, &iter->cpu,2672 iter->ent = __find_next_entry(iter, &iter->cpu,
2680 &iter->lost_events, &iter->ts);2673 &iter->lost_events, &iter->ts);
2681 2674
2682 if (iter->ent)2675 if (iter->ent) {
2683 trace_iterator_increment(iter);2676 iter->idx++;
2677 buf_iter = trace_buffer_iter(iter, iter->cpu);
2678 if (buf_iter)
2679 ring_buffer_iter_advance(buf_iter);
2680 }
2684 2681
2685 return iter->ent ? iter : NULL;2682 return iter->ent ? iter : NULL;
2686}2683}
@@ -4474,7 +4471,7 @@ static const char readme_msg[] = · 1787 unmodified lines
4474 "\t snapshot() - snapshot the trace buffer\n\n"4471 "\t snapshot() - snapshot the trace buffer\n\n"
4475#endif4472#endif
4476#ifdef CONFIG_SYNTH_EVENTS4473#ifdef CONFIG_SYNTH_EVENTS
4477 " events/synthetic_events\t- Create/append/remove/show synthetic events\n"4474 " synthetic_events\t- Create/append/remove/show synthetic events\n"
4478 "\t Write into this file to define/undefine new synthetic events.\n"4475 "\t Write into this file to define/undefine new synthetic events.\n"
4479 "\t example: echo 'myevent u64 lat; char name[]; long[] stack' >> synthetic_events\n"4476 "\t example: echo 'myevent u64 lat; char name[]; long[] stack' >> synthetic_events\n"
4480#endif4477#endif
@@ -7928,8 +7925,8 @@ create_trace_option_files(struct trace_array *tr, struct tracer *tracer, · 3447 unmodified lines
7928 if (!topts)7925 if (!topts)
7929 return 0;7926 return 0;
7930 7927
7931 tr_topts = krealloc(tr->topts, sizeof(*tr->topts) * (tr->nr_topts + 1),7928 tr_topts = krealloc_array(tr->topts, tr->nr_topts + 1, sizeof(*tr->topts),
7932 GFP_KERNEL);7929 GFP_KERNEL);
7933 if (!tr_topts) {7930 if (!tr_topts) {
7934 kfree(topts);7931 kfree(topts);
7935 return -ENOMEM;7932 return -ENOMEM;
kernel/trace/trace_branch.c+3−6
@@ -181,8 +181,7 @@ __init static int init_branch_tracer(void) · 180 unmodified lines
181 181
182 ret = register_trace_event(&trace_branch_event);182 ret = register_trace_event(&trace_branch_event);
183 if (!ret) {183 if (!ret) {
184 printk(KERN_WARNING "Warning: could not register "184 pr_warn("Warning: could not register branch events\n");
185 "branch events\n");
186 return 1;185 return 1;
187 }186 }
188 return register_tracer(&branch_trace);187 return register_tracer(&branch_trace);
@@ -374,8 +373,7 @@ __init static int init_annotated_branch_stats(void) · 185 unmodified lines
374 373
375 ret = register_stat_tracer(&annotated_branch_stats);374 ret = register_stat_tracer(&annotated_branch_stats);
376 if (ret) {375 if (ret) {
377 printk(KERN_WARNING "Warning: could not register "376 pr_warn("Warning: could not register annotated branches stats\n");
378 "annotated branches stats\n");
379 return ret;377 return ret;
380 }378 }
381 return 0;379 return 0;
@@ -439,8 +437,7 @@ __init static int all_annotated_branch_stats(void) · 57 unmodified lines
439 437
440 ret = register_stat_tracer(&all_branch_stats);438 ret = register_stat_tracer(&all_branch_stats);
441 if (ret) {439 if (ret) {
442 printk(KERN_WARNING "Warning: could not register "440 pr_warn("Warning: could not register all branches stats\n");
443 "all branches stats\n");
444 return ret;441 return ret;
445 }442 }
446 return 0;443 return 0;
kernel/trace/trace_event_perf.c+11−1
@@ -497,7 +497,17 @@ static int perf_ftrace_function_register(struct perf_event *event) · 496 unmodified lines
497static int perf_ftrace_function_unregister(struct perf_event *event)497static int perf_ftrace_function_unregister(struct perf_event *event)
498{498{
499 struct ftrace_ops *ops = &event->ftrace_ops;499 struct ftrace_ops *ops = &event->ftrace_ops;
500 int ret = unregister_ftrace_function(ops);500 int ret = 0;
501
502 /*
503 * Perf will call this unconditionally even if the ops is not
504 * enabled. The unregister_ftrace_function() will warn if called
505 * when not enabled. Just bypass the unregistering if ops isn't
506 * enabled here.
507 */
508 if (ops->flags & FTRACE_OPS_FL_ENABLED)
509 ret = unregister_ftrace_function(ops);
510
501 ftrace_free_filter(ops);511 ftrace_free_filter(ops);
502 return ret;512 return ret;
503}513}
kernel/trace/trace_events_hist.c+40−32
@@ -8,6 +8,7 @@ · 7 unmodified lines
8#include <linux/module.h>8#include <linux/module.h>
9#include <linux/kallsyms.h>9#include <linux/kallsyms.h>
10#include <linux/security.h>10#include <linux/security.h>
11#include <linux/seq_buf.h>
11#include <linux/mutex.h>12#include <linux/mutex.h>
12#include <linux/slab.h>13#include <linux/slab.h>
13#include <linux/stacktrace.h>14#include <linux/stacktrace.h>
@@ -682,8 +683,8 @@ struct track_data { · 668 unmodified lines
682struct hist_elt_data {683struct hist_elt_data {
683 char *comm;684 char *comm;
684 u64 *var_ref_vals;685 u64 *var_ref_vals;
685 char **field_var_str;
686 int n_field_var_str;686 int n_field_var_str;
687 char *field_var_str[] __counted_by(n_field_var_str);
687};688};
688 689
689struct snapshot_context {690struct snapshot_context {
@@ -1628,8 +1629,6 @@ static void hist_elt_data_free(struct hist_elt_data *elt_data) · 938 unmodified lines
1628 for (i = 0; i < elt_data->n_field_var_str; i++)1629 for (i = 0; i < elt_data->n_field_var_str; i++)
1629 kfree(elt_data->field_var_str[i]);1630 kfree(elt_data->field_var_str[i]);
1630 1631
1631 kfree(elt_data->field_var_str);
1632
1633 kfree(elt_data->comm);1632 kfree(elt_data->comm);
1634 kfree(elt_data);1633 kfree(elt_data);
1635}1634}
@@ -1649,10 +1648,19 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt) · 13 unmodified lines
1649 struct hist_field *hist_field;1648 struct hist_field *hist_field;
1650 unsigned int i, n_str;1649 unsigned int i, n_str;
1651 1650
1652 elt_data = kzalloc_obj(*elt_data);1651 BUILD_BUG_ON(STR_VAR_LEN_MAX & (sizeof(u64) - 1));
1652
1653 n_str = hist_data->n_field_var_str + hist_data->n_save_var_str +
1654 hist_data->n_var_str;
1655 if (n_str > SYNTH_FIELDS_MAX)
1656 return -EINVAL;
1657
1658 elt_data = kzalloc_flex(*elt_data, field_var_str, n_str);
1653 if (!elt_data)1659 if (!elt_data)
1654 return -ENOMEM;1660 return -ENOMEM;
1655 1661
1662 elt_data->n_field_var_str = n_str;
1663
1656 for_each_hist_field(i, hist_data) {1664 for_each_hist_field(i, hist_data) {
1657 hist_field = hist_data->fields[i];1665 hist_field = hist_data->fields[i];
1658 1666
@@ -1666,24 +1674,8 @@ static int hist_trigger_elt_data_alloc(struct tracing_map_elt *elt) · 7 unmodified lines
1666 }1674 }
1667 }1675 }
1668 1676
1669 n_str = hist_data->n_field_var_str + hist_data->n_save_var_str +
1670 hist_data->n_var_str;
1671 if (n_str > SYNTH_FIELDS_MAX) {
1672 hist_elt_data_free(elt_data);
1673 return -EINVAL;
1674 }
1675
1676 BUILD_BUG_ON(STR_VAR_LEN_MAX & (sizeof(u64) - 1));
1677
1678 size = STR_VAR_LEN_MAX;1677 size = STR_VAR_LEN_MAX;
1679 1678
1680 elt_data->field_var_str = kcalloc(n_str, sizeof(char *), GFP_KERNEL);
1681 if (!elt_data->field_var_str) {
1682 hist_elt_data_free(elt_data);
1683 return -EINVAL;
1684 }
1685 elt_data->n_field_var_str = n_str;
1686
1687 for (i = 0; i < n_str; i++) {1679 for (i = 0; i < n_str; i++) {
1688 elt_data->field_var_str[i] = kzalloc(size, GFP_KERNEL);1680 elt_data->field_var_str[i] = kzalloc(size, GFP_KERNEL);
1689 if (!elt_data->field_var_str[i]) {1681 if (!elt_data->field_var_str[i]) {
@@ -2967,13 +2959,22 @@ find_synthetic_field_var(struct hist_trigger_data *target_hist_data, · 1277 unmodified lines
2967{2959{
2968 struct hist_field *event_var;2960 struct hist_field *event_var;
2969 char *synthetic_name;2961 char *synthetic_name;
2962 struct seq_buf s;
2970 2963
2971 synthetic_name = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);2964 synthetic_name = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL);
2972 if (!synthetic_name)2965 if (!synthetic_name)
2973 return ERR_PTR(-ENOMEM);2966 return ERR_PTR(-ENOMEM);
2974 2967
2975 strcpy(synthetic_name, "synthetic_");2968 seq_buf_init(&s, synthetic_name, MAX_FILTER_STR_VAL);
2976 strcat(synthetic_name, field_name);2969 seq_buf_printf(&s, "synthetic_%s", field_name);
2970
2971 /* Terminate synthetic_name with a NUL. */
2972 seq_buf_str(&s);
2973
2974 if (seq_buf_has_overflowed(&s)) {
2975 kfree(synthetic_name);
2976 return ERR_PTR(-E2BIG);
2977 }
2977 2978
2978 event_var = find_event_var(target_hist_data, system, event_name, synthetic_name);2979 event_var = find_event_var(target_hist_data, system, event_name, synthetic_name);
2979 2980
@@ -3019,6 +3020,7 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data, · 39 unmodified lines
3019 struct hist_field *key_field;3020 struct hist_field *key_field;
3020 struct hist_field *event_var;3021 struct hist_field *event_var;
3021 char *saved_filter;3022 char *saved_filter;
3023 struct seq_buf s;
3022 char *cmd;3024 char *cmd;
3023 int ret;3025 int ret;
3024 3026
@@ -3063,28 +3065,34 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data, · 38 unmodified lines
3063 return ERR_PTR(-ENOMEM);3065 return ERR_PTR(-ENOMEM);
3064 }3066 }
3065 3067
3068 seq_buf_init(&s, cmd, MAX_FILTER_STR_VAL);
3069
3066 /* Use the same keys as the compatible histogram */3070 /* Use the same keys as the compatible histogram */
3067 strcat(cmd, "keys=");3071 seq_buf_puts(&s, "keys=");
3068 3072
3069 for_each_hist_key_field(i, hist_data) {3073 for_each_hist_key_field(i, hist_data) {
3070 key_field = hist_data->fields[i];3074 key_field = hist_data->fields[i];
3071 if (!first)3075 if (!first)
3072 strcat(cmd, ",");3076 seq_buf_putc(&s, ',');
3073 strcat(cmd, key_field->field->name);3077 seq_buf_puts(&s, key_field->field->name);
3074 first = false;3078 first = false;
3075 }3079 }
3076 3080
3077 /* Create the synthetic field variable specification */3081 /* Create the synthetic field variable specification */
3078 strcat(cmd, ":synthetic_");3082 seq_buf_printf(&s, ":synthetic_%s=%s", field_name, field_name);
3079 strcat(cmd, field_name);
3080 strcat(cmd, "=");
3081 strcat(cmd, field_name);
3082 3083
3083 /* Use the same filter as the compatible histogram */3084 /* Use the same filter as the compatible histogram */
3084 saved_filter = find_trigger_filter(hist_data, file);3085 saved_filter = find_trigger_filter(hist_data, file);
3085 if (saved_filter) {3086 if (saved_filter)
3086 strcat(cmd, " if ");3087 seq_buf_printf(&s, " if %s", saved_filter);
3087 strcat(cmd, saved_filter);3088
3089 /* Terminate cmd with a NUL. */
3090 seq_buf_str(&s);
3091
3092 if (seq_buf_has_overflowed(&s)) {
3093 kfree(cmd);
3094 kfree(var_hist);
3095 return ERR_PTR(-E2BIG);
3088 }3096 }
3089 3097
3090 var_hist->cmd = kstrdup(cmd, GFP_KERNEL);3098 var_hist->cmd = kstrdup(cmd, GFP_KERNEL);
kernel/trace/trace_events_synth.c+94−27
@@ -499,28 +499,19 @@ static unsigned int trace_stack(struct synth_trace_event *entry, · 498 unmodified lines
499 return len;499 return len;
500}500}
501 501
502static void trace_event_raw_event_synth(void *__data,502static __always_inline int get_field_size(struct synth_event *event,
503 u64 *var_ref_vals,503 u64 *var_ref_vals,
504 unsigned int *var_ref_idx)504 unsigned int *var_ref_idx)
505{505{
506 unsigned int i, n_u64, val_idx, len, data_size = 0;506 int fields_size;
507 struct trace_event_file *trace_file = __data;
508 struct synth_trace_event *entry;
509 struct trace_event_buffer fbuffer;
510 struct trace_buffer *buffer;
511 struct synth_event *event;
512 int fields_size = 0;
513
514 event = trace_file->event_call->data;
515
516 if (trace_trigger_soft_disabled(trace_file))
517 return;
518 507
519 fields_size = event->n_u64 * sizeof(u64);508 fields_size = event->n_u64 * sizeof(u64);
520 509
521 for (i = 0; i < event->n_dynamic_fields; i++) {510 for (int i = 0; i < event->n_dynamic_fields; i++) {
522 unsigned int field_pos = event->dynamic_fields[i]->field_pos;511 unsigned int field_pos = event->dynamic_fields[i]->field_pos;
523 char *str_val;512 char *str_val;
513 int val_idx;
514 int len;
524 515
525 val_idx = var_ref_idx[field_pos];516 val_idx = var_ref_idx[field_pos];
526 str_val = (char *)(long)var_ref_vals[val_idx];517 str_val = (char *)(long)var_ref_vals[val_idx];
@@ -535,18 +526,18 @@ static void trace_event_raw_event_synth(void *__data, · 8 unmodified lines
535 526
536 fields_size += len;527 fields_size += len;
537 }528 }
529 return fields_size;
530}
538 531
539 /*532static __always_inline void write_synth_entry(struct synth_event *event,
540 * Avoid ring buffer recursion detection, as this event533 struct synth_trace_event *entry,
541 * is being performed within another event.534 u64 *var_ref_vals,
542 */535 unsigned int *var_ref_idx)
543 buffer = trace_file->tr->array_buffer.buffer;536{
544 guard(ring_buffer_nest)(buffer);537 int data_size = 0;
545 538 int i, n_u64;
546 entry = trace_event_buffer_reserve(&fbuffer, trace_file,539 int val_idx;
547 sizeof(*entry) + fields_size);540 int len;
548 if (!entry)
549 return;
550 541
551 for (i = 0, n_u64 = 0; i < event->n_fields; i++) {542 for (i = 0, n_u64 = 0; i < event->n_fields; i++) {
552 val_idx = var_ref_idx[i];543 val_idx = var_ref_idx[i];
@@ -587,10 +578,83 @@ static void trace_event_raw_event_synth(void *__data, · 34 unmodified lines
587 n_u64++;578 n_u64++;
588 }579 }
589 }580 }
581}
582
583static void trace_event_raw_event_synth(void *__data,
584 u64 *var_ref_vals,
585 unsigned int *var_ref_idx)
586{
587 struct trace_event_file *trace_file = __data;
588 struct synth_trace_event *entry;
589 struct trace_event_buffer fbuffer;
590 struct trace_buffer *buffer;
591 struct synth_event *event;
592 int fields_size;
593
594 event = trace_file->event_call->data;
595
596 if (trace_trigger_soft_disabled(trace_file))
597 return;
598
599 fields_size = get_field_size(event, var_ref_vals, var_ref_idx);
600
601 /*
602 * Avoid ring buffer recursion detection, as this event
603 * is being performed within another event.
604 */
605 buffer = trace_file->tr->array_buffer.buffer;
606 guard(ring_buffer_nest)(buffer);
607
608 entry = trace_event_buffer_reserve(&fbuffer, trace_file,
609 sizeof(*entry) + fields_size);
610 if (!entry)
611 return;
612
613 write_synth_entry(event, entry, var_ref_vals, var_ref_idx);
590 614
591 trace_event_buffer_commit(&fbuffer);615 trace_event_buffer_commit(&fbuffer);
592}616}
593 617
618#ifdef CONFIG_PERF_EVENTS
619static void perf_event_raw_event_synth(void *__data,
620 u64 *var_ref_vals,
621 unsigned int *var_ref_idx)
622{
623 struct trace_event_call *call = __data;
624 struct synth_trace_event *entry;
625 struct hlist_head *perf_head;
626 struct synth_event *event;
627 struct pt_regs *regs;
628 int fields_size;
629 size_t size;
630 int context;
631
632 event = call->data;
633
634 perf_head = this_cpu_ptr(call->perf_events);
635
636 if (!perf_head || hlist_empty(perf_head))
637 return;
638
639 fields_size = get_field_size(event, var_ref_vals, var_ref_idx);
640
641 size = ALIGN(sizeof(*entry) + fields_size, 8);
642
643 entry = perf_trace_buf_alloc(size, &regs, &context);
644
645 if (unlikely(!entry))
646 return;
647
648 write_synth_entry(event, entry, var_ref_vals, var_ref_idx);
649
650 perf_fetch_caller_regs(regs);
651
652 perf_trace_buf_submit(entry, size, context,
653 call->event.type, 1, regs,
654 perf_head, NULL);
655}
656#endif
657
594static void free_synth_event_print_fmt(struct trace_event_call *call)658static void free_synth_event_print_fmt(struct trace_event_call *call)
595{659{
596 if (call) {660 if (call) {
@@ -917,6 +981,9 @@ static int register_synth_event(struct synth_event *event) · 320 unmodified lines
917 call->flags = TRACE_EVENT_FL_TRACEPOINT;981 call->flags = TRACE_EVENT_FL_TRACEPOINT;
918 call->class->reg = synth_event_reg;982 call->class->reg = synth_event_reg;
919 call->class->probe = trace_event_raw_event_synth;983 call->class->probe = trace_event_raw_event_synth;
984#ifdef CONFIG_PERF_EVENTS
985 call->class->perf_probe = perf_event_raw_event_synth;
986#endif
920 call->data = event;987 call->data = event;
921 call->tp = event->tp;988 call->tp = event->tp;
922 989
kernel/trace/trace_recursion_record.c+3−5
@@ -180,9 +180,8 @@ static const struct seq_operations recursed_function_seq_ops = { · 179 unmodified lines
180 180
181static int recursed_function_open(struct inode *inode, struct file *file)181static int recursed_function_open(struct inode *inode, struct file *file)
182{182{
183 int ret = 0;183 guard(mutex)(&recursed_function_lock);
184 184
185 mutex_lock(&recursed_function_lock);
186 /* If this file was opened for write, then erase contents */185 /* If this file was opened for write, then erase contents */
187 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {186 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
188 /* disable updating records */187 /* disable updating records */
@@ -194,10 +193,9 @@ static int recursed_function_open(struct inode *inode, struct file *file) · 5 unmodified lines
194 atomic_set(&nr_records, 0);193 atomic_set(&nr_records, 0);
195 }194 }
196 if (file->f_mode & FMODE_READ)195 if (file->f_mode & FMODE_READ)
197 ret = seq_open(file, &recursed_function_seq_ops);196 return seq_open(file, &recursed_function_seq_ops);
198 mutex_unlock(&recursed_function_lock);
199 197
200 return ret;198 return 0;
201}199}
202 200
203static ssize_t recursed_function_write(struct file *file,201static ssize_t recursed_function_write(struct file *file,
kernel/trace/trace_remote.c+1−1
@@ -602,7 +602,7 @@ static int trace_pipe_open(struct inode *inode, struct file *filp) · 601 unmodified lines
602 602
603 filp->private_data = iter;603 filp->private_data = iter;
604 604
605 return IS_ERR(iter) ? PTR_ERR(iter) : 0;605 return 0;
606}606}
607 607
608static int trace_pipe_release(struct inode *inode, struct file *filp)608static int trace_pipe_release(struct inode *inode, struct file *filp)
kernel/trace/tracing_map.c+11−19
@@ -288,9 +288,6 @@ static void tracing_map_array_clear(struct tracing_map_array *a) · 287 unmodified lines
288{288{
289 unsigned int i;289 unsigned int i;
290 290
291 if (!a->pages)
292 return;
293
294 for (i = 0; i < a->n_pages; i++)291 for (i = 0; i < a->n_pages; i++)
295 memset(a->pages[i], 0, PAGE_SIZE);292 memset(a->pages[i], 0, PAGE_SIZE);
296}293}
@@ -302,9 +299,6 @@ static void tracing_map_array_free(struct tracing_map_array *a) · 5 unmodified lines
302 if (!a)299 if (!a)
303 return;300 return;
304 301
305 if (!a->pages)
306 goto free;
307
308 for (i = 0; i < a->n_pages; i++) {302 for (i = 0; i < a->n_pages; i++) {
309 if (!a->pages[i])303 if (!a->pages[i])
310 break;304 break;
@@ -312,9 +306,6 @@ static void tracing_map_array_free(struct tracing_map_array *a) · 1 unmodified line
312 free_page((unsigned long)a->pages[i]);306 free_page((unsigned long)a->pages[i]);
313 }307 }
314 308
315 kfree(a->pages);
316
317 free:
318 kfree(a);309 kfree(a);
319}310}
320 311
@@ -322,24 +313,25 @@ static struct tracing_map_array *tracing_map_array_alloc(unsigned int n_elts, · 1 unmodified line
322 unsigned int entry_size)313 unsigned int entry_size)
323{314{
324 struct tracing_map_array *a;315 struct tracing_map_array *a;
316 unsigned int entry_size_shift;
317 unsigned int entries_per_page;
318 unsigned int n_pages;
325 unsigned int i;319 unsigned int i;
326 320
327 a = kzalloc_obj(*a);321 entry_size_shift = fls(roundup_pow_of_two(entry_size) - 1);
322 entries_per_page = PAGE_SIZE / (1 << entry_size_shift);
323 n_pages = max(1, n_elts / entries_per_page);
324
325 a = kzalloc_flex(*a, pages, n_pages);
328 if (!a)326 if (!a)
329 return NULL;327 return NULL;
330 328
331 a->entry_size_shift = fls(roundup_pow_of_two(entry_size) - 1);329 a->entry_size_shift = entry_size_shift;
332 a->entries_per_page = PAGE_SIZE / (1 << a->entry_size_shift);330 a->entries_per_page = entries_per_page;
333 a->n_pages = n_elts / a->entries_per_page;331 a->n_pages = n_pages;
334 if (!a->n_pages)
335 a->n_pages = 1;
336 a->entry_shift = fls(a->entries_per_page) - 1;332 a->entry_shift = fls(a->entries_per_page) - 1;
337 a->entry_mask = (1 << a->entry_shift) - 1;333 a->entry_mask = (1 << a->entry_shift) - 1;
338 334
339 a->pages = kcalloc(a->n_pages, sizeof(void *), GFP_KERNEL);
340 if (!a->pages)
341 goto free;
342
343 for (i = 0; i < a->n_pages; i++) {335 for (i = 0; i < a->n_pages; i++) {
344 a->pages[i] = (void *)get_zeroed_page(GFP_KERNEL);336 a->pages[i] = (void *)get_zeroed_page(GFP_KERNEL);
345 if (!a->pages[i])337 if (!a->pages[i])
kernel/trace/tracing_map.h+1−1
@@ -167,7 +167,7 @@ struct tracing_map_array { · 166 unmodified lines
167 unsigned int entry_shift;167 unsigned int entry_shift;
168 unsigned int entry_mask;168 unsigned int entry_mask;
169 unsigned int n_pages;169 unsigned int n_pages;
170 void **pages;170 void *pages[] __counted_by(n_pages);
171};171};
172 172
173#define TRACING_MAP_ARRAY_ELT(array, idx) \173#define TRACING_MAP_ARRAY_ELT(array, idx) \