History

Merge tag 'trace-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull tracing updates from Steven Rostedt: - Add function names as a way to filter function addresses - Add sample module to test ftrace ops and dynamic trampolines - Allow stack traces to be passed from beginning event to end event for synthetic events. This will allow seeing the stack trace of when a task is scheduled out and recorded when it gets scheduled back in. - Add trace event helper __get_buf() to use as a temporary buffer when printing out trace event output. - Add kernel command line to create trace instances on boot up. - Add enabling of events to instances created at boot up. - Add trace_array_puts() to write into instances. - Allow boot instances to take a snapshot at the end of boot up. - Allow live patch modules to include trace events - Minor fixes and clean ups * tag 'trace-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: (31 commits) tracing: Remove unnecessary NULL assignment tracepoint: Allow livepatch module add trace event tracing: Always use canonical ftrace path tracing/histogram: Fix stacktrace histogram Documententation tracing/histogram: Fix stacktrace key tracing/histogram: Fix a few problems with stacktrace variable printing tracing: Add BUILD_BUG() to make sure stacktrace fits in strings tracing/histogram: Don't use strlen to find length of stacktrace variables tracing: Allow boot instances to have snapshot buffers tracing: Add trace_array_puts() to write into instance tracing: Add enabling of events to boot instances tracing: Add creation of instances at boot command line tracing: Fix trace_event_raw_event_synth() if else statement samples: ftrace: Make some global variables static ftrace: sample: avoid open-coded 64-bit division samples: ftrace: Include the nospec-branch.h only for x86 tracing: Acquire buffer from temparary trace sequence tracing/histogram: Wrap remaining shell snippets in code blocks tracing/osnoise: No need for schedule_hrtimeout range bpf/tracing: Use stage6 of tracing to not duplicate macros ...

Linus Torvalds committed 3 years ago

Commit b72b5fe2 parents 9191423 7568a2142 files · +1113 −221Browse files

Showing the changes to kernel (14 of 42 files). Show all

Unified · Split

14 files
  1. kernel/trace/Kconfig +10 −10
  2. kernel/trace/kprobe_event_gen_test.c +1 −1
  3. kernel/trace/ring_buffer.c +7 −2
  4. kernel/trace/synth_event_gen_test.c +1 −1
  5. kernel/trace/trace.c +145 −19
  6. kernel/trace/trace.h +6 −0
  7. kernel/trace/trace_events.c +5 −8
  8. kernel/trace/trace_events_filter.c +92 −1
  9. kernel/trace/trace_events_hist.c +103 −23
  10. kernel/trace/trace_events_synth.c +86 −4
  11. kernel/trace/trace_osnoise.c +1 −1
  12. kernel/trace/trace_seq.c +23 −0
  13. kernel/trace/trace_synth.h +1 −0
  14. kernel/tracepoint.c +2 −2
kernel/trace/Kconfig+10−10
@@ -242,7 +242,7 @@ config DYNAMIC_FTRACE · 241 unmodified lines
242 enabled, and the functions not enabled will not affect242 enabled, and the functions not enabled will not affect
243 performance of the system.243 performance of the system.
244 244
245 See the files in /sys/kernel/debug/tracing:245 See the files in /sys/kernel/tracing:
246 available_filter_functions246 available_filter_functions
247 set_ftrace_filter247 set_ftrace_filter
248 set_ftrace_notrace248 set_ftrace_notrace
@@ -306,7 +306,7 @@ config STACK_TRACER · 57 unmodified lines
306 select KALLSYMS306 select KALLSYMS
307 help307 help
308 This special tracer records the maximum stack footprint of the308 This special tracer records the maximum stack footprint of the
309 kernel and displays it in /sys/kernel/debug/tracing/stack_trace.309 kernel and displays it in /sys/kernel/tracing/stack_trace.
310 310
311 This tracer works by hooking into every function call that the311 This tracer works by hooking into every function call that the
312 kernel executes, and keeping a maximum stack depth value and312 kernel executes, and keeping a maximum stack depth value and
@@ -346,7 +346,7 @@ config IRQSOFF_TRACER · 33 unmodified lines
346 disabled by default and can be runtime (re-)started346 disabled by default and can be runtime (re-)started
347 via:347 via:
348 348
349 echo 0 > /sys/kernel/debug/tracing/tracing_max_latency349 echo 0 > /sys/kernel/tracing/tracing_max_latency
350 350
351 (Note that kernel size and overhead increase with this option351 (Note that kernel size and overhead increase with this option
352 enabled. This option and the preempt-off timing option can be352 enabled. This option and the preempt-off timing option can be
@@ -370,7 +370,7 @@ config PREEMPT_TRACER · 17 unmodified lines
370 disabled by default and can be runtime (re-)started370 disabled by default and can be runtime (re-)started
371 via:371 via:
372 372
373 echo 0 > /sys/kernel/debug/tracing/tracing_max_latency373 echo 0 > /sys/kernel/tracing/tracing_max_latency
374 374
375 (Note that kernel size and overhead increase with this option375 (Note that kernel size and overhead increase with this option
376 enabled. This option and the irqs-off timing option can be376 enabled. This option and the irqs-off timing option can be
@@ -522,7 +522,7 @@ config TRACER_SNAPSHOT · 145 unmodified lines
522 Allow tracing users to take snapshot of the current buffer using the522 Allow tracing users to take snapshot of the current buffer using the
523 ftrace interface, e.g.:523 ftrace interface, e.g.:
524 524
525 echo 1 > /sys/kernel/debug/tracing/snapshot525 echo 1 > /sys/kernel/tracing/snapshot
526 cat snapshot526 cat snapshot
527 527
528config TRACER_SNAPSHOT_PER_CPU_SWAP528config TRACER_SNAPSHOT_PER_CPU_SWAP
@@ -534,7 +534,7 @@ config TRACER_SNAPSHOT_PER_CPU_SWAP · 5 unmodified lines
534 full swap (all buffers). If this is set, then the following is534 full swap (all buffers). If this is set, then the following is
535 allowed:535 allowed:
536 536
537 echo 1 > /sys/kernel/debug/tracing/per_cpu/cpu2/snapshot537 echo 1 > /sys/kernel/tracing/per_cpu/cpu2/snapshot
538 538
539 After which, only the tracing buffer for CPU 2 was swapped with539 After which, only the tracing buffer for CPU 2 was swapped with
540 the main tracing buffer, and the other CPU buffers remain the same.540 the main tracing buffer, and the other CPU buffers remain the same.
@@ -581,7 +581,7 @@ config PROFILE_ANNOTATED_BRANCHES · 40 unmodified lines
581 This tracer profiles all likely and unlikely macros581 This tracer profiles all likely and unlikely macros
582 in the kernel. It will display the results in:582 in the kernel. It will display the results in:
583 583
584 /sys/kernel/debug/tracing/trace_stat/branch_annotated584 /sys/kernel/tracing/trace_stat/branch_annotated
585 585
586 Note: this will add a significant overhead; only turn this586 Note: this will add a significant overhead; only turn this
587 on if you need to profile the system's use of these macros.587 on if you need to profile the system's use of these macros.
@@ -594,7 +594,7 @@ config PROFILE_ALL_BRANCHES · 6 unmodified lines
594 taken in the kernel is recorded whether it hit or miss.594 taken in the kernel is recorded whether it hit or miss.
595 The results will be displayed in:595 The results will be displayed in:
596 596
597 /sys/kernel/debug/tracing/trace_stat/branch_all597 /sys/kernel/tracing/trace_stat/branch_all
598 598
599 This option also enables the likely/unlikely profiler.599 This option also enables the likely/unlikely profiler.
600 600
@@ -645,8 +645,8 @@ config BLK_DEV_IO_TRACE · 44 unmodified lines
645 Tracing also is possible using the ftrace interface, e.g.:645 Tracing also is possible using the ftrace interface, e.g.:
646 646
647 echo 1 > /sys/block/sda/sda1/trace/enable647 echo 1 > /sys/block/sda/sda1/trace/enable
648 echo blk > /sys/kernel/debug/tracing/current_tracer648 echo blk > /sys/kernel/tracing/current_tracer
649 cat /sys/kernel/debug/tracing/trace_pipe649 cat /sys/kernel/tracing/trace_pipe
650 650
651 If unsure, say N.651 If unsure, say N.
652 652
kernel/trace/kprobe_event_gen_test.c+1−1
@@ -21,7 +21,7 @@ · 20 unmodified lines
21 * Then:21 * Then:
22 *22 *
23 * # insmod kernel/trace/kprobe_event_gen_test.ko23 * # insmod kernel/trace/kprobe_event_gen_test.ko
24 * # cat /sys/kernel/debug/tracing/trace24 * # cat /sys/kernel/tracing/trace
25 *25 *
26 * You should see many instances of the "gen_kprobe_test" and26 * You should see many instances of the "gen_kprobe_test" and
27 * "gen_kretprobe_test" events in the trace buffer.27 * "gen_kretprobe_test" events in the trace buffer.
kernel/trace/ring_buffer.c+7−2
@@ -2864,7 +2864,7 @@ rb_check_timestamp(struct ring_buffer_per_cpu *cpu_buffer, · 2863 unmodified lines
2864 sched_clock_stable() ? "" :2864 sched_clock_stable() ? "" :
2865 "If you just came from a suspend/resume,\n"2865 "If you just came from a suspend/resume,\n"
2866 "please switch to the trace global clock:\n"2866 "please switch to the trace global clock:\n"
2867 " echo global > /sys/kernel/debug/tracing/trace_clock\n"2867 " echo global > /sys/kernel/tracing/trace_clock\n"
2868 "or add trace_clock=global to the kernel command line\n");2868 "or add trace_clock=global to the kernel command line\n");
2869}2869}
2870 2870
@@ -5604,11 +5604,16 @@ EXPORT_SYMBOL_GPL(ring_buffer_alloc_read_page); · 2733 unmodified lines
5604 */5604 */
5605void ring_buffer_free_read_page(struct trace_buffer *buffer, int cpu, void *data)5605void ring_buffer_free_read_page(struct trace_buffer *buffer, int cpu, void *data)
5606{5606{
5607 struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu];5607 struct ring_buffer_per_cpu *cpu_buffer;
5608 struct buffer_data_page *bpage = data;5608 struct buffer_data_page *bpage = data;
5609 struct page *page = virt_to_page(bpage);5609 struct page *page = virt_to_page(bpage);
5610 unsigned long flags;5610 unsigned long flags;
5611 5611
5612 if (!buffer || !buffer->buffers || !buffer->buffers[cpu])
5613 return;
5614
5615 cpu_buffer = buffer->buffers[cpu];
5616
5612 /* If the page is still in use someplace else, we can't reuse it */5617 /* If the page is still in use someplace else, we can't reuse it */
5613 if (page_ref_count(page) > 1)5618 if (page_ref_count(page) > 1)
5614 goto out;5619 goto out;
kernel/trace/synth_event_gen_test.c+1−1
@@ -22,7 +22,7 @@ · 21 unmodified lines
22 * Then:22 * Then:
23 *23 *
24 * # insmod kernel/trace/synth_event_gen_test.ko24 * # insmod kernel/trace/synth_event_gen_test.ko
25 * # cat /sys/kernel/debug/tracing/trace25 * # cat /sys/kernel/tracing/trace
26 *26 *
27 * You should see several events in the trace buffer -27 * You should see several events in the trace buffer -
28 * "create_synth_test", "empty_synth_test", and several instances of28 * "create_synth_test", "empty_synth_test", and several instances of
kernel/trace/trace.c+145−19
@@ -49,6 +49,8 @@ · 48 unmodified lines
49#include <linux/irq_work.h>49#include <linux/irq_work.h>
50#include <linux/workqueue.h>50#include <linux/workqueue.h>
51 51
52#include <asm/setup.h> /* COMMAND_LINE_SIZE */
53
52#include "trace.h"54#include "trace.h"
53#include "trace_output.h"55#include "trace_output.h"
54 56
@@ -186,6 +188,12 @@ static char *default_bootup_tracer; · 131 unmodified lines
186static bool allocate_snapshot;188static bool allocate_snapshot;
187static bool snapshot_at_boot;189static bool snapshot_at_boot;
188 190
191static char boot_instance_info[COMMAND_LINE_SIZE] __initdata;
192static int boot_instance_index;
193
194static char boot_snapshot_info[COMMAND_LINE_SIZE] __initdata;
195static int boot_snapshot_index;
196
189static int __init set_cmdline_ftrace(char *str)197static int __init set_cmdline_ftrace(char *str)
190{198{
191 strlcpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);199 strlcpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
@@ -222,9 +230,22 @@ __setup("traceoff_on_warning", stop_trace_on_warning); · 30 unmodified lines
222 230
223static int __init boot_alloc_snapshot(char *str)231static int __init boot_alloc_snapshot(char *str)
224{232{
225 allocate_snapshot = true;233 char *slot = boot_snapshot_info + boot_snapshot_index;
226 /* We also need the main ring buffer expanded */234 int left = sizeof(boot_snapshot_info) - boot_snapshot_index;
227 ring_buffer_expanded = true;235 int ret;
236
237 if (str[0] == '=') {
238 str++;
239 if (strlen(str) >= left)
240 return -1;
241
242 ret = snprintf(slot, left, "%s\t", str);
243 boot_snapshot_index += ret;
244 } else {
245 allocate_snapshot = true;
246 /* We also need the main ring buffer expanded */
247 ring_buffer_expanded = true;
248 }
228 return 1;249 return 1;
229}250}
230__setup("alloc_snapshot", boot_alloc_snapshot);251__setup("alloc_snapshot", boot_alloc_snapshot);
@@ -239,6 +260,23 @@ static int __init boot_snapshot(char *str) · 8 unmodified lines
239__setup("ftrace_boot_snapshot", boot_snapshot);260__setup("ftrace_boot_snapshot", boot_snapshot);
240 261
241 262
263static int __init boot_instance(char *str)
264{
265 char *slot = boot_instance_info + boot_instance_index;
266 int left = sizeof(boot_instance_info) - boot_instance_index;
267 int ret;
268
269 if (strlen(str) >= left)
270 return -1;
271
272 ret = snprintf(slot, left, "%s\t", str);
273 boot_instance_index += ret;
274
275 return 1;
276}
277__setup("trace_instance=", boot_instance);
278
279
242static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata;280static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata;
243 281
244static int __init set_trace_boot_options(char *str)282static int __init set_trace_boot_options(char *str)
@@ -1001,13 +1039,8 @@ __buffer_unlock_commit(struct trace_buffer *buffer, struct ring_buffer_event *ev · 756 unmodified lines
1001 ring_buffer_unlock_commit(buffer);1039 ring_buffer_unlock_commit(buffer);
1002}1040}
1003 1041
1004/**1042int __trace_array_puts(struct trace_array *tr, unsigned long ip,
1005 * __trace_puts - write a constant string into the trace buffer.1043 const char *str, int size)
1006 * @ip: The address of the caller
1007 * @str: The constant string to write
1008 * @size: The size of the string.
1009 */
1010int __trace_puts(unsigned long ip, const char *str, int size)
1011{1044{
1012 struct ring_buffer_event *event;1045 struct ring_buffer_event *event;
1013 struct trace_buffer *buffer;1046 struct trace_buffer *buffer;
@@ -1015,7 +1048,7 @@ int __trace_puts(unsigned long ip, const char *str, int size) · 1 unmodified line
1015 unsigned int trace_ctx;1048 unsigned int trace_ctx;
1016 int alloc;1049 int alloc;
1017 1050
1018 if (!(global_trace.trace_flags & TRACE_ITER_PRINTK))1051 if (!(tr->trace_flags & TRACE_ITER_PRINTK))
1019 return 0;1052 return 0;
1020 1053
1021 if (unlikely(tracing_selftest_running || tracing_disabled))1054 if (unlikely(tracing_selftest_running || tracing_disabled))
@@ -1024,7 +1057,7 @@ int __trace_puts(unsigned long ip, const char *str, int size) · 2 unmodified lines
1024 alloc = sizeof(*entry) + size + 2; /* possible \n added */1057 alloc = sizeof(*entry) + size + 2; /* possible \n added */
1025 1058
1026 trace_ctx = tracing_gen_ctx();1059 trace_ctx = tracing_gen_ctx();
1027 buffer = global_trace.array_buffer.buffer;1060 buffer = tr->array_buffer.buffer;
1028 ring_buffer_nest_start(buffer);1061 ring_buffer_nest_start(buffer);
1029 event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, alloc,1062 event = __trace_buffer_lock_reserve(buffer, TRACE_PRINT, alloc,
1030 trace_ctx);1063 trace_ctx);
@@ -1046,11 +1079,23 @@ int __trace_puts(unsigned long ip, const char *str, int size) · 15 unmodified lines
1046 entry->buf[size] = '\0';1079 entry->buf[size] = '\0';
1047 1080
1048 __buffer_unlock_commit(buffer, event);1081 __buffer_unlock_commit(buffer, event);
1049 ftrace_trace_stack(&global_trace, buffer, trace_ctx, 4, NULL);1082 ftrace_trace_stack(tr, buffer, trace_ctx, 4, NULL);
1050 out:1083 out:
1051 ring_buffer_nest_end(buffer);1084 ring_buffer_nest_end(buffer);
1052 return size;1085 return size;
1053}1086}
1087EXPORT_SYMBOL_GPL(__trace_array_puts);
1088
1089/**
1090 * __trace_puts - write a constant string into the trace buffer.
1091 * @ip: The address of the caller
1092 * @str: The constant string to write
1093 * @size: The size of the string.
1094 */
1095int __trace_puts(unsigned long ip, const char *str, int size)
1096{
1097 return __trace_array_puts(&global_trace, ip, str, size);
1098}
1054EXPORT_SYMBOL_GPL(__trace_puts);1099EXPORT_SYMBOL_GPL(__trace_puts);
1055 1100
1056/**1101/**
@@ -1142,7 +1187,7 @@ void tracing_snapshot_instance(struct trace_array *tr) · 85 unmodified lines
1142 *1187 *
1143 * Note, make sure to allocate the snapshot with either1188 * Note, make sure to allocate the snapshot with either
1144 * a tracing_snapshot_alloc(), or by doing it manually1189 * a tracing_snapshot_alloc(), or by doing it manually
1145 * with: echo 1 > /sys/kernel/debug/tracing/snapshot1190 * with: echo 1 > /sys/kernel/tracing/snapshot
1146 *1191 *
1147 * If the snapshot buffer is not allocated, it will stop tracing.1192 * If the snapshot buffer is not allocated, it will stop tracing.
1148 * Basically making a permanent snapshot.1193 * Basically making a permanent snapshot.
@@ -5760,7 +5805,7 @@ static const char readme_msg[] = · 4611 unmodified lines
5760#ifdef CONFIG_SYNTH_EVENTS5805#ifdef CONFIG_SYNTH_EVENTS
5761 " events/synthetic_events\t- Create/append/remove/show synthetic events\n"5806 " events/synthetic_events\t- Create/append/remove/show synthetic events\n"
5762 "\t Write into this file to define/undefine new synthetic events.\n"5807 "\t Write into this file to define/undefine new synthetic events.\n"
5763 "\t example: echo 'myevent u64 lat; char name[]' >> synthetic_events\n"5808 "\t example: echo 'myevent u64 lat; char name[]; long[] stack' >> synthetic_events\n"
5764#endif5809#endif
5765#endif5810#endif
5766;5811;
@@ -9225,10 +9270,6 @@ static int allocate_trace_buffers(struct trace_array *tr, int size) · 3458 unmodified lines
9225 }9270 }
9226 tr->allocated_snapshot = allocate_snapshot;9271 tr->allocated_snapshot = allocate_snapshot;
9227 9272
9228 /*
9229 * Only the top level trace array gets its snapshot allocated
9230 * from the kernel command line.
9231 */
9232 allocate_snapshot = false;9273 allocate_snapshot = false;
9233#endif9274#endif
9234 9275
@@ -10144,6 +10185,79 @@ out: · 909 unmodified lines
10144 return ret;10185 return ret;
10145}10186}
10146 10187
10188#ifdef CONFIG_TRACER_MAX_TRACE
10189__init static bool tr_needs_alloc_snapshot(const char *name)
10190{
10191 char *test;
10192 int len = strlen(name);
10193 bool ret;
10194
10195 if (!boot_snapshot_index)
10196 return false;
10197
10198 if (strncmp(name, boot_snapshot_info, len) == 0 &&
10199 boot_snapshot_info[len] == '\t')
10200 return true;
10201
10202 test = kmalloc(strlen(name) + 3, GFP_KERNEL);
10203 if (!test)
10204 return false;
10205
10206 sprintf(test, "\t%s\t", name);
10207 ret = strstr(boot_snapshot_info, test) == NULL;
10208 kfree(test);
10209 return ret;
10210}
10211
10212__init static void do_allocate_snapshot(const char *name)
10213{
10214 if (!tr_needs_alloc_snapshot(name))
10215 return;
10216
10217 /*
10218 * When allocate_snapshot is set, the next call to
10219 * allocate_trace_buffers() (called by trace_array_get_by_name())
10220 * will allocate the snapshot buffer. That will alse clear
10221 * this flag.
10222 */
10223 allocate_snapshot = true;
10224}
10225#else
10226static inline void do_allocate_snapshot(const char *name) { }
10227#endif
10228
10229__init static void enable_instances(void)
10230{
10231 struct trace_array *tr;
10232 char *curr_str;
10233 char *str;
10234 char *tok;
10235
10236 /* A tab is always appended */
10237 boot_instance_info[boot_instance_index - 1] = '\0';
10238 str = boot_instance_info;
10239
10240 while ((curr_str = strsep(&str, "\t"))) {
10241
10242 tok = strsep(&curr_str, ",");
10243
10244 if (IS_ENABLED(CONFIG_TRACER_MAX_TRACE))
10245 do_allocate_snapshot(tok);
10246
10247 tr = trace_array_get_by_name(tok);
10248 if (!tr) {
10249 pr_warn("Failed to create instance buffer %s\n", curr_str);
10250 continue;
10251 }
10252 /* Allow user space to delete it */
10253 trace_array_put(tr);
10254
10255 while ((tok = strsep(&curr_str, ","))) {
10256 early_enable_events(tr, tok, true);
10257 }
10258 }
10259}
10260
10147__init static int tracer_alloc_buffers(void)10261__init static int tracer_alloc_buffers(void)
10148{10262{
10149 int ring_buf_size;10263 int ring_buf_size;
@@ -10277,10 +10391,19 @@ out: · 127 unmodified lines
10277 10391
10278void __init ftrace_boot_snapshot(void)10392void __init ftrace_boot_snapshot(void)
10279{10393{
10394 struct trace_array *tr;
10395
10280 if (snapshot_at_boot) {10396 if (snapshot_at_boot) {
10281 tracing_snapshot();10397 tracing_snapshot();
10282 internal_trace_puts("** Boot snapshot taken **\n");10398 internal_trace_puts("** Boot snapshot taken **\n");
10283 }10399 }
10400
10401 list_for_each_entry(tr, &ftrace_trace_arrays, list) {
10402 if (tr == &global_trace)
10403 continue;
10404 trace_array_puts(tr, "** Boot snapshot taken **\n");
10405 tracing_snapshot_instance(tr);
10406 }
10284}10407}
10285 10408
10286void __init early_trace_init(void)10409void __init early_trace_init(void)
@@ -10302,6 +10425,9 @@ void __init early_trace_init(void) · 15 unmodified lines
10302void __init trace_init(void)10425void __init trace_init(void)
10303{10426{
10304 trace_event_init();10427 trace_event_init();
10428
10429 if (boot_instance_index)
10430 enable_instances();
10305}10431}
10306 10432
10307__init static void clear_boot_tracer(void)10433__init static void clear_boot_tracer(void)
kernel/trace/trace.h+6−0
@@ -113,6 +113,10 @@ enum trace_type { · 112 unmodified lines
113#define MEM_FAIL(condition, fmt, ...) \113#define MEM_FAIL(condition, fmt, ...) \
114 DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__)114 DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__)
115 115
116#define HIST_STACKTRACE_DEPTH 16
117#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long))
118#define HIST_STACKTRACE_SKIP 5
119
116/*120/*
117 * syscalls are special, and need special handling, this is why121 * syscalls are special, and need special handling, this is why
118 * they are not included in trace_entries.h122 * they are not included in trace_entries.h
@@ -1331,6 +1335,8 @@ DECLARE_PER_CPU(int, trace_buffered_event_cnt); · 1212 unmodified lines
1331void trace_buffered_event_disable(void);1335void trace_buffered_event_disable(void);
1332void trace_buffered_event_enable(void);1336void trace_buffered_event_enable(void);
1333 1337
1338void early_enable_events(struct trace_array *tr, char *buf, bool disable_first);
1339
1334static inline void1340static inline void
1335__trace_event_discard_commit(struct trace_buffer *buffer,1341__trace_event_discard_commit(struct trace_buffer *buffer,
1336 struct ring_buffer_event *event)1342 struct ring_buffer_event *event)
kernel/trace/trace_events.c+5−8
@@ -2281,8 +2281,6 @@ create_new_subsystem(const char *name) · 2280 unmodified lines
2281 if (!system->name)2281 if (!system->name)
2282 goto out_free;2282 goto out_free;
2283 2283
2284 system->filter = NULL;
2285
2286 system->filter = kzalloc(sizeof(struct event_filter), GFP_KERNEL);2284 system->filter = kzalloc(sizeof(struct event_filter), GFP_KERNEL);
2287 if (!system->filter)2285 if (!system->filter)
2288 goto out_free;2286 goto out_free;
@@ -2843,7 +2841,7 @@ static __init int setup_trace_triggers(char *str) · 554 unmodified lines
2843 if (!trigger)2841 if (!trigger)
2844 break;2842 break;
2845 bootup_triggers[i].event = strsep(&trigger, ".");2843 bootup_triggers[i].event = strsep(&trigger, ".");
2846 bootup_triggers[i].trigger = strsep(&trigger, ".");2844 bootup_triggers[i].trigger = trigger;
2847 if (!bootup_triggers[i].trigger)2845 if (!bootup_triggers[i].trigger)
2848 break;2846 break;
2849 }2847 }
@@ -3771,10 +3769,9 @@ static __init int event_trace_memsetup(void) · 921 unmodified lines
3771 return 0;3769 return 0;
3772}3770}
3773 3771
3774static __init void3772__init void
3775early_enable_events(struct trace_array *tr, bool disable_first)3773early_enable_events(struct trace_array *tr, char *buf, bool disable_first)
3776{3774{
3777 char *buf = bootup_event_buf;
3778 char *token;3775 char *token;
3779 int ret;3776 int ret;
3780 3777
@@ -3827,7 +3824,7 @@ static __init int event_trace_enable(void) · 46 unmodified lines
3827 */3824 */
3828 __trace_early_add_events(tr);3825 __trace_early_add_events(tr);
3829 3826
3830 early_enable_events(tr, false);3827 early_enable_events(tr, bootup_event_buf, false);
3831 3828
3832 trace_printk_start_comm();3829 trace_printk_start_comm();
3833 3830
@@ -3855,7 +3852,7 @@ static __init int event_trace_enable_again(void) · 21 unmodified lines
3855 if (!tr)3852 if (!tr)
3856 return -ENODEV;3853 return -ENODEV;
3857 3854
3858 early_enable_events(tr, true);3855 early_enable_events(tr, bootup_event_buf, true);
3859 3856
3860 return 0;3857 return 0;
3861}3858}
kernel/trace/trace_events_filter.c+92−1
@@ -64,6 +64,7 @@ enum filter_pred_fn { · 63 unmodified lines
64 FILTER_PRED_FN_PCHAR_USER,64 FILTER_PRED_FN_PCHAR_USER,
65 FILTER_PRED_FN_PCHAR,65 FILTER_PRED_FN_PCHAR,
66 FILTER_PRED_FN_CPU,66 FILTER_PRED_FN_CPU,
67 FILTER_PRED_FN_FUNCTION,
67 FILTER_PRED_FN_,68 FILTER_PRED_FN_,
68 FILTER_PRED_TEST_VISITED,69 FILTER_PRED_TEST_VISITED,
69};70};
@@ -71,6 +72,7 @@ enum filter_pred_fn { · 1 unmodified line
71struct filter_pred {72struct filter_pred {
72 enum filter_pred_fn fn_num;73 enum filter_pred_fn fn_num;
73 u64 val;74 u64 val;
75 u64 val2;
74 struct regex regex;76 struct regex regex;
75 unsigned short *ops;77 unsigned short *ops;
76 struct ftrace_event_field *field;78 struct ftrace_event_field *field;
@@ -103,6 +105,7 @@ struct filter_pred { · 26 unmodified lines
103 C(INVALID_FILTER, "Meaningless filter expression"), \105 C(INVALID_FILTER, "Meaningless filter expression"), \
104 C(IP_FIELD_ONLY, "Only 'ip' field is supported for function trace"), \106 C(IP_FIELD_ONLY, "Only 'ip' field is supported for function trace"), \
105 C(INVALID_VALUE, "Invalid value (did you forget quotes)?"), \107 C(INVALID_VALUE, "Invalid value (did you forget quotes)?"), \
108 C(NO_FUNCTION, "Function not found"), \
106 C(ERRNO, "Error"), \109 C(ERRNO, "Error"), \
107 C(NO_FILTER, "No filter found")110 C(NO_FILTER, "No filter found")
108 111
@@ -876,6 +879,17 @@ static int filter_pred_comm(struct filter_pred *pred, void *event) · 767 unmodified lines
876 return cmp ^ pred->not;879 return cmp ^ pred->not;
877}880}
878 881
882/* Filter predicate for functions. */
883static int filter_pred_function(struct filter_pred *pred, void *event)
884{
885 unsigned long *addr = (unsigned long *)(event + pred->offset);
886 unsigned long start = (unsigned long)pred->val;
887 unsigned long end = (unsigned long)pred->val2;
888 int ret = *addr >= start && *addr < end;
889
890 return pred->op == OP_EQ ? ret : !ret;
891}
892
879/*893/*
880 * regex_match_foo - Basic regex callbacks894 * regex_match_foo - Basic regex callbacks
881 *895 *
@@ -1335,6 +1349,8 @@ static int filter_pred_fn_call(struct filter_pred *pred, void *event) · 453 unmodified lines
1335 return filter_pred_pchar(pred, event);1349 return filter_pred_pchar(pred, event);
1336 case FILTER_PRED_FN_CPU:1350 case FILTER_PRED_FN_CPU:
1337 return filter_pred_cpu(pred, event);1351 return filter_pred_cpu(pred, event);
1352 case FILTER_PRED_FN_FUNCTION:
1353 return filter_pred_function(pred, event);
1338 case FILTER_PRED_TEST_VISITED:1354 case FILTER_PRED_TEST_VISITED:
1339 return test_pred_visited_fn(pred, event);1355 return test_pred_visited_fn(pred, event);
1340 default:1356 default:
@@ -1350,8 +1366,13 @@ static int parse_pred(const char *str, void *data, · 9 unmodified lines
1350 struct trace_event_call *call = data;1366 struct trace_event_call *call = data;
1351 struct ftrace_event_field *field;1367 struct ftrace_event_field *field;
1352 struct filter_pred *pred = NULL;1368 struct filter_pred *pred = NULL;
1369 unsigned long offset;
1370 unsigned long size;
1371 unsigned long ip;
1353 char num_buf[24]; /* Big enough to hold an address */1372 char num_buf[24]; /* Big enough to hold an address */
1354 char *field_name;1373 char *field_name;
1374 char *name;
1375 bool function = false;
1355 bool ustring = false;1376 bool ustring = false;
1356 char q;1377 char q;
1357 u64 val;1378 u64 val;
@@ -1393,6 +1414,12 @@ static int parse_pred(const char *str, void *data, · 35 unmodified lines
1393 i += len;1414 i += len;
1394 }1415 }
1395 1416
1417 /* See if the field is a kernel function name */
1418 if ((len = str_has_prefix(str + i, ".function"))) {
1419 function = true;
1420 i += len;
1421 }
1422
1396 while (isspace(str[i]))1423 while (isspace(str[i]))
1397 i++;1424 i++;
1398 1425
@@ -1423,7 +1450,71 @@ static int parse_pred(const char *str, void *data, · 24 unmodified lines
1423 pred->offset = field->offset;1450 pred->offset = field->offset;
1424 pred->op = op;1451 pred->op = op;
1425 1452
1426 if (ftrace_event_is_function(call)) {1453 if (function) {
1454 /* The field must be the same size as long */
1455 if (field->size != sizeof(long)) {
1456 parse_error(pe, FILT_ERR_ILLEGAL_FIELD_OP, pos + i);
1457 goto err_free;
1458 }
1459
1460 /* Function only works with '==' or '!=' and an unquoted string */
1461 switch (op) {
1462 case OP_NE:
1463 case OP_EQ:
1464 break;
1465 default:
1466 parse_error(pe, FILT_ERR_INVALID_OP, pos + i);
1467 goto err_free;
1468 }
1469
1470 if (isdigit(str[i])) {
1471 /* We allow 0xDEADBEEF */
1472 while (isalnum(str[i]))
1473 i++;
1474
1475 len = i - s;
1476 /* 0xfeedfacedeadbeef is 18 chars max */
1477 if (len >= sizeof(num_buf)) {
1478 parse_error(pe, FILT_ERR_OPERAND_TOO_LONG, pos + i);
1479 goto err_free;
1480 }
1481
1482 strncpy(num_buf, str + s, len);
1483 num_buf[len] = 0;
1484
1485 ret = kstrtoul(num_buf, 0, &ip);
1486 if (ret) {
1487 parse_error(pe, FILT_ERR_INVALID_VALUE, pos + i);
1488 goto err_free;
1489 }
1490 } else {
1491 s = i;
1492 for (; str[i] && !isspace(str[i]); i++)
1493 ;
1494
1495 len = i - s;
1496 name = kmemdup_nul(str + s, len, GFP_KERNEL);
1497 if (!name)
1498 goto err_mem;
1499 ip = kallsyms_lookup_name(name);
1500 kfree(name);
1501 if (!ip) {
1502 parse_error(pe, FILT_ERR_NO_FUNCTION, pos + i);
1503 goto err_free;
1504 }
1505 }
1506
1507 /* Now find the function start and end address */
1508 if (!kallsyms_lookup_size_offset(ip, &size, &offset)) {
1509 parse_error(pe, FILT_ERR_NO_FUNCTION, pos + i);
1510 goto err_free;
1511 }
1512
1513 pred->fn_num = FILTER_PRED_FN_FUNCTION;
1514 pred->val = ip - offset;
1515 pred->val2 = pred->val + size;
1516
1517 } else if (ftrace_event_is_function(call)) {
1427 /*1518 /*
1428 * Perf does things different with function events.1519 * Perf does things different with function events.
1429 * It only allows an "ip" field, and expects a string.1520 * It only allows an "ip" field, and expects a string.
kernel/trace/trace_events_hist.c+103−23
@@ -135,6 +135,7 @@ enum hist_field_fn { · 134 unmodified lines
135 HIST_FIELD_FN_DIV_NOT_POWER2,135 HIST_FIELD_FN_DIV_NOT_POWER2,
136 HIST_FIELD_FN_DIV_MULT_SHIFT,136 HIST_FIELD_FN_DIV_MULT_SHIFT,
137 HIST_FIELD_FN_EXECNAME,137 HIST_FIELD_FN_EXECNAME,
138 HIST_FIELD_FN_STACK,
138};139};
139 140
140/*141/*
@@ -480,10 +481,6 @@ DEFINE_HIST_FIELD_FN(u8); · 339 unmodified lines
480#define for_each_hist_key_field(i, hist_data) \481#define for_each_hist_key_field(i, hist_data) \
481 for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++)482 for ((i) = (hist_data)->n_vals; (i) < (hist_data)->n_fields; (i)++)
482 483
483#define HIST_STACKTRACE_DEPTH 16
484#define HIST_STACKTRACE_SIZE (HIST_STACKTRACE_DEPTH * sizeof(unsigned long))
485#define HIST_STACKTRACE_SKIP 5
486
487#define HITCOUNT_IDX 0484#define HITCOUNT_IDX 0
488#define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + HIST_STACKTRACE_SIZE)485#define HIST_KEY_SIZE_MAX (MAX_FILTER_STR_VAL + HIST_STACKTRACE_SIZE)
489 486
@@ -1360,7 +1357,12 @@ static const char *hist_field_name(struct hist_field *field, · 870 unmodified lines
1360 field_name = field->name;1357 field_name = field->name;
1361 } else if (field->flags & HIST_FIELD_FL_TIMESTAMP)1358 } else if (field->flags & HIST_FIELD_FL_TIMESTAMP)
1362 field_name = "common_timestamp";1359 field_name = "common_timestamp";
1363 else if (field->flags & HIST_FIELD_FL_HITCOUNT)1360 else if (field->flags & HIST_FIELD_FL_STACKTRACE) {
1361 if (field->field)
1362 field_name = field->field->name;
1363 else
1364 field_name = "stacktrace";
1365 } else if (field->flags & HIST_FIELD_FL_HITCOUNT)
1364 field_name = "hitcount";1366 field_name = "hitcount";
1365 1367
1366 if (field_name == NULL)1368 if (field_name == NULL)
@@ -1718,6 +1720,8 @@ static const char *get_hist_field_flags(struct hist_field *hist_field) · 351 unmodified lines
1718 flags_str = "percent";1720 flags_str = "percent";
1719 else if (hist_field->flags & HIST_FIELD_FL_GRAPH)1721 else if (hist_field->flags & HIST_FIELD_FL_GRAPH)
1720 flags_str = "graph";1722 flags_str = "graph";
1723 else if (hist_field->flags & HIST_FIELD_FL_STACKTRACE)
1724 flags_str = "stacktrace";
1721 1725
1722 return flags_str;1726 return flags_str;
1723}1727}
@@ -1979,7 +1983,14 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data, · 255 unmodified lines
1979 }1983 }
1980 1984
1981 if (flags & HIST_FIELD_FL_STACKTRACE) {1985 if (flags & HIST_FIELD_FL_STACKTRACE) {
1982 hist_field->fn_num = HIST_FIELD_FN_NOP;1986 if (field)
1987 hist_field->fn_num = HIST_FIELD_FN_STACK;
1988 else
1989 hist_field->fn_num = HIST_FIELD_FN_NOP;
1990 hist_field->size = HIST_STACKTRACE_SIZE;
1991 hist_field->type = kstrdup_const("unsigned long[]", GFP_KERNEL);
1992 if (!hist_field->type)
1993 goto free;
1983 goto out;1994 goto out;
1984 }1995 }
1985 1996
@@ -2312,6 +2323,8 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file, · 326 unmodified lines
2312 *flags |= HIST_FIELD_FL_EXECNAME;2323 *flags |= HIST_FIELD_FL_EXECNAME;
2313 else if (strcmp(modifier, "syscall") == 0)2324 else if (strcmp(modifier, "syscall") == 0)
2314 *flags |= HIST_FIELD_FL_SYSCALL;2325 *flags |= HIST_FIELD_FL_SYSCALL;
2326 else if (strcmp(modifier, "stacktrace") == 0)
2327 *flags |= HIST_FIELD_FL_STACKTRACE;
2315 else if (strcmp(modifier, "log2") == 0)2328 else if (strcmp(modifier, "log2") == 0)
2316 *flags |= HIST_FIELD_FL_LOG2;2329 *flags |= HIST_FIELD_FL_LOG2;
2317 else if (strcmp(modifier, "usecs") == 0)2330 else if (strcmp(modifier, "usecs") == 0)
@@ -2351,6 +2364,8 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file, · 33 unmodified lines
2351 hist_data->enable_timestamps = true;2364 hist_data->enable_timestamps = true;
2352 if (*flags & HIST_FIELD_FL_TIMESTAMP_USECS)2365 if (*flags & HIST_FIELD_FL_TIMESTAMP_USECS)
2353 hist_data->attrs->ts_in_usecs = true;2366 hist_data->attrs->ts_in_usecs = true;
2367 } else if (strcmp(field_name, "stacktrace") == 0) {
2368 *flags |= HIST_FIELD_FL_STACKTRACE;
2354 } else if (strcmp(field_name, "common_cpu") == 0)2369 } else if (strcmp(field_name, "common_cpu") == 0)
2355 *flags |= HIST_FIELD_FL_CPU;2370 *flags |= HIST_FIELD_FL_CPU;
2356 else if (strcmp(field_name, "hitcount") == 0)2371 else if (strcmp(field_name, "hitcount") == 0)
@@ -3111,6 +3126,9 @@ static inline void __update_field_vars(struct tracing_map_elt *elt, · 754 unmodified lines
3111 unsigned int i, j, var_idx;3126 unsigned int i, j, var_idx;
3112 u64 var_val;3127 u64 var_val;
3113 3128
3129 /* Make sure stacktrace can fit in the string variable length */
3130 BUILD_BUG_ON((HIST_STACKTRACE_DEPTH + 1) * sizeof(long) >= STR_VAR_LEN_MAX);
3131
3114 for (i = 0, j = field_var_str_start; i < n_field_vars; i++) {3132 for (i = 0, j = field_var_str_start; i < n_field_vars; i++) {
3115 struct field_var *field_var = field_vars[i];3133 struct field_var *field_var = field_vars[i];
3116 struct hist_field *var = field_var->var;3134 struct hist_field *var = field_var->var;
@@ -3119,13 +3137,26 @@ static inline void __update_field_vars(struct tracing_map_elt *elt, · 2 unmodified lines
3119 var_val = hist_fn_call(val, elt, buffer, rbe, rec);3137 var_val = hist_fn_call(val, elt, buffer, rbe, rec);
3120 var_idx = var->var.idx;3138 var_idx = var->var.idx;
3121 3139
3122 if (val->flags & HIST_FIELD_FL_STRING) {3140 if (val->flags & (HIST_FIELD_FL_STRING |
3141 HIST_FIELD_FL_STACKTRACE)) {
3123 char *str = elt_data->field_var_str[j++];3142 char *str = elt_data->field_var_str[j++];
3124 char *val_str = (char *)(uintptr_t)var_val;3143 char *val_str = (char *)(uintptr_t)var_val;
3125 unsigned int size;3144 unsigned int size;
3126 3145
3127 size = min(val->size, STR_VAR_LEN_MAX);3146 if (val->flags & HIST_FIELD_FL_STRING) {
3128 strscpy(str, val_str, size);3147 size = min(val->size, STR_VAR_LEN_MAX);
3148 strscpy(str, val_str, size);
3149 } else {
3150 char *stack_start = str + sizeof(unsigned long);
3151 int e;
3152
3153 e = stack_trace_save((void *)stack_start,
3154 HIST_STACKTRACE_DEPTH,
3155 HIST_STACKTRACE_SKIP);
3156 if (e < HIST_STACKTRACE_DEPTH - 1)
3157 ((unsigned long *)stack_start)[e] = 0;
3158 *((unsigned long *)str) = e;
3159 }
3129 var_val = (u64)(uintptr_t)str;3160 var_val = (u64)(uintptr_t)str;
3130 }3161 }
3131 tracing_map_set_var(elt, var_idx, var_val);3162 tracing_map_set_var(elt, var_idx, var_val);
@@ -3824,7 +3855,8 @@ static void save_field_var(struct hist_trigger_data *hist_data, · 692 unmodified lines
3824{3855{
3825 hist_data->field_vars[hist_data->n_field_vars++] = field_var;3856 hist_data->field_vars[hist_data->n_field_vars++] = field_var;
3826 3857
3827 if (field_var->val->flags & HIST_FIELD_FL_STRING)3858 /* Stack traces are saved in the string storage too */
3859 if (field_var->val->flags & (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE))
3828 hist_data->n_field_var_str++;3860 hist_data->n_field_var_str++;
3829}3861}
3830 3862
@@ -3849,6 +3881,9 @@ static int check_synth_field(struct synth_event *event, · 18 unmodified lines
3849 && field->is_dynamic)3881 && field->is_dynamic)
3850 return 0;3882 return 0;
3851 3883
3884 if (strstr(hist_field->type, "long[") && field->is_stack)
3885 return 0;
3886
3852 if (strcmp(field->type, hist_field->type) != 0) {3887 if (strcmp(field->type, hist_field->type) != 0) {
3853 if (field->size != hist_field->size ||3888 if (field->size != hist_field->size ||
3854 (!field->is_string && field->is_signed != hist_field->is_signed))3889 (!field->is_string && field->is_signed != hist_field->is_signed))
@@ -4103,7 +4138,8 @@ static int action_create(struct hist_trigger_data *hist_data, · 248 unmodified lines
4103 }4138 }
4104 4139
4105 hist_data->save_vars[hist_data->n_save_vars++] = field_var;4140 hist_data->save_vars[hist_data->n_save_vars++] = field_var;
4106 if (field_var->val->flags & HIST_FIELD_FL_STRING)4141 if (field_var->val->flags &
4142 (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE))
4107 hist_data->n_save_var_str++;4143 hist_data->n_save_var_str++;
4108 kfree(param);4144 kfree(param);
4109 }4145 }
@@ -4242,6 +4278,19 @@ static u64 hist_field_execname(struct hist_field *hist_field, · 132 unmodified lines
4242 return (u64)(unsigned long)(elt_data->comm);4278 return (u64)(unsigned long)(elt_data->comm);
4243}4279}
4244 4280
4281static u64 hist_field_stack(struct hist_field *hist_field,
4282 struct tracing_map_elt *elt,
4283 struct trace_buffer *buffer,
4284 struct ring_buffer_event *rbe,
4285 void *event)
4286{
4287 u32 str_item = *(u32 *)(event + hist_field->field->offset);
4288 int str_loc = str_item & 0xffff;
4289 char *addr = (char *)(event + str_loc);
4290
4291 return (u64)(unsigned long)addr;
4292}
4293
4245static u64 hist_fn_call(struct hist_field *hist_field,4294static u64 hist_fn_call(struct hist_field *hist_field,
4246 struct tracing_map_elt *elt,4295 struct tracing_map_elt *elt,
4247 struct trace_buffer *buffer,4296 struct trace_buffer *buffer,
@@ -4305,6 +4354,8 @@ static u64 hist_fn_call(struct hist_field *hist_field, · 57 unmodified lines
4305 return div_by_mult_and_shift(hist_field, elt, buffer, rbe, event);4354 return div_by_mult_and_shift(hist_field, elt, buffer, rbe, event);
4306 case HIST_FIELD_FN_EXECNAME:4355 case HIST_FIELD_FN_EXECNAME:
4307 return hist_field_execname(hist_field, elt, buffer, rbe, event);4356 return hist_field_execname(hist_field, elt, buffer, rbe, event);
4357 case HIST_FIELD_FN_STACK:
4358 return hist_field_stack(hist_field, elt, buffer, rbe, event);
4308 default:4359 default:
4309 return 0;4360 return 0;
4310 }4361 }
@@ -4351,7 +4402,8 @@ static int create_var_field(struct hist_trigger_data *hist_data, · 40 unmodified lines
4351 if (!ret && hist_data->fields[val_idx]->flags & HIST_FIELD_FL_EXECNAME)4402 if (!ret && hist_data->fields[val_idx]->flags & HIST_FIELD_FL_EXECNAME)
4352 update_var_execname(hist_data->fields[val_idx]);4403 update_var_execname(hist_data->fields[val_idx]);
4353 4404
4354 if (!ret && hist_data->fields[val_idx]->flags & HIST_FIELD_FL_STRING)4405 if (!ret && hist_data->fields[val_idx]->flags &
4406 (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE))
4355 hist_data->fields[val_idx]->var_str_idx = hist_data->n_var_str++;4407 hist_data->fields[val_idx]->var_str_idx = hist_data->n_var_str++;
4356 4408
4357 return ret;4409 return ret;
@@ -5092,7 +5144,8 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, · 734 unmodified lines
5092 if (hist_field->flags & HIST_FIELD_FL_VAR) {5144 if (hist_field->flags & HIST_FIELD_FL_VAR) {
5093 var_idx = hist_field->var.idx;5145 var_idx = hist_field->var.idx;
5094 5146
5095 if (hist_field->flags & HIST_FIELD_FL_STRING) {5147 if (hist_field->flags &
5148 (HIST_FIELD_FL_STRING | HIST_FIELD_FL_STACKTRACE)) {
5096 unsigned int str_start, var_str_idx, idx;5149 unsigned int str_start, var_str_idx, idx;
5097 char *str, *val_str;5150 char *str, *val_str;
5098 unsigned int size;5151 unsigned int size;
@@ -5105,9 +5158,20 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data, · 6 unmodified lines
5105 str = elt_data->field_var_str[idx];5158 str = elt_data->field_var_str[idx];
5106 val_str = (char *)(uintptr_t)hist_val;5159 val_str = (char *)(uintptr_t)hist_val;
5107 5160
5108 size = min(hist_field->size, STR_VAR_LEN_MAX);5161 if (hist_field->flags & HIST_FIELD_FL_STRING) {
5109 strscpy(str, val_str, size);5162 size = min(hist_field->size, STR_VAR_LEN_MAX);
5110 5163 strscpy(str, val_str, size);
5164 } else {
5165 char *stack_start = str + sizeof(unsigned long);
5166 int e;
5167
5168 e = stack_trace_save((void *)stack_start,
5169 HIST_STACKTRACE_DEPTH,
5170 HIST_STACKTRACE_SKIP);
5171 if (e < HIST_STACKTRACE_DEPTH - 1)
5172 ((unsigned long *)stack_start)[e] = 0;
5173 *((unsigned long *)str) = e;
5174 }
5111 hist_val = (u64)(uintptr_t)str;5175 hist_val = (u64)(uintptr_t)str;
5112 }5176 }
5113 tracing_map_set_var(elt, var_idx, hist_val);5177 tracing_map_set_var(elt, var_idx, hist_val);
@@ -5193,8 +5257,17 @@ static void event_hist_trigger(struct event_trigger_data *data, · 79 unmodified lines
5193 5257
5194 if (key_field->flags & HIST_FIELD_FL_STACKTRACE) {5258 if (key_field->flags & HIST_FIELD_FL_STACKTRACE) {
5195 memset(entries, 0, HIST_STACKTRACE_SIZE);5259 memset(entries, 0, HIST_STACKTRACE_SIZE);
5196 stack_trace_save(entries, HIST_STACKTRACE_DEPTH,5260 if (key_field->field) {
5197 HIST_STACKTRACE_SKIP);5261 unsigned long *stack, n_entries;
5262
5263 field_contents = hist_fn_call(key_field, elt, buffer, rbe, rec);
5264 stack = (unsigned long *)(long)field_contents;
5265 n_entries = *stack;
5266 memcpy(entries, ++stack, n_entries * sizeof(unsigned long));
5267 } else {
5268 stack_trace_save(entries, HIST_STACKTRACE_DEPTH,
5269 HIST_STACKTRACE_SKIP);
5270 }
5198 key = entries;5271 key = entries;
5199 } else {5272 } else {
5200 field_contents = hist_fn_call(key_field, elt, buffer, rbe, rec);5273 field_contents = hist_fn_call(key_field, elt, buffer, rbe, rec);
@@ -5297,7 +5370,10 @@ static void hist_trigger_print_key(struct seq_file *m, · 96 unmodified lines
5297 seq_printf(m, "%s: %-30s[%3llu]", field_name,5370 seq_printf(m, "%s: %-30s[%3llu]", field_name,
5298 syscall_name, uval);5371 syscall_name, uval);
5299 } else if (key_field->flags & HIST_FIELD_FL_STACKTRACE) {5372 } else if (key_field->flags & HIST_FIELD_FL_STACKTRACE) {
5300 seq_puts(m, "stacktrace:\n");5373 if (key_field->field)
5374 seq_printf(m, "%s.stacktrace", key_field->field->name);
5375 else
5376 seq_puts(m, "stacktrace:\n");
5301 hist_trigger_stacktrace_print(m,5377 hist_trigger_stacktrace_print(m,
5302 key + key_field->offset,5378 key + key_field->offset,
5303 HIST_STACKTRACE_DEPTH);5379 HIST_STACKTRACE_DEPTH);
@@ -5842,7 +5918,8 @@ static void hist_field_print(struct seq_file *m, struct hist_field *hist_field) · 538 unmodified lines
5842 5918
5843 if (hist_field->flags) {5919 if (hist_field->flags) {
5844 if (!(hist_field->flags & HIST_FIELD_FL_VAR_REF) &&5920 if (!(hist_field->flags & HIST_FIELD_FL_VAR_REF) &&
5845 !(hist_field->flags & HIST_FIELD_FL_EXPR)) {5921 !(hist_field->flags & HIST_FIELD_FL_EXPR) &&
5922 !(hist_field->flags & HIST_FIELD_FL_STACKTRACE)) {
5846 const char *flags = get_hist_field_flags(hist_field);5923 const char *flags = get_hist_field_flags(hist_field);
5847 5924
5848 if (flags)5925 if (flags)
@@ -5875,9 +5952,12 @@ static int event_hist_trigger_print(struct seq_file *m, · 26 unmodified lines
5875 if (i > hist_data->n_vals)5952 if (i > hist_data->n_vals)
5876 seq_puts(m, ",");5953 seq_puts(m, ",");
5877 5954
5878 if (field->flags & HIST_FIELD_FL_STACKTRACE)5955 if (field->flags & HIST_FIELD_FL_STACKTRACE) {
5879 seq_puts(m, "stacktrace");5956 if (field->field)
5880 else5957 seq_printf(m, "%s.stacktrace", field->field->name);
5958 else
5959 seq_puts(m, "stacktrace");
5960 } else
5881 hist_field_print(m, field);5961 hist_field_print(m, field);
5882 }5962 }
5883 5963
kernel/trace/trace_events_synth.c+86−4
@@ -173,6 +173,14 @@ static int synth_field_is_string(char *type) · 172 unmodified lines
173 return false;173 return false;
174}174}
175 175
176static int synth_field_is_stack(char *type)
177{
178 if (strstr(type, "long[") != NULL)
179 return true;
180
181 return false;
182}
183
176static int synth_field_string_size(char *type)184static int synth_field_string_size(char *type)
177{185{
178 char buf[4], *end, *start;186 char buf[4], *end, *start;
@@ -248,6 +256,8 @@ static int synth_field_size(char *type) · 69 unmodified lines
248 size = sizeof(gfp_t);256 size = sizeof(gfp_t);
249 else if (synth_field_is_string(type))257 else if (synth_field_is_string(type))
250 size = synth_field_string_size(type);258 size = synth_field_string_size(type);
259 else if (synth_field_is_stack(type))
260 size = 0;
251 261
252 return size;262 return size;
253}263}
@@ -292,6 +302,8 @@ static const char *synth_field_fmt(char *type) · 38 unmodified lines
292 fmt = "%x";302 fmt = "%x";
293 else if (synth_field_is_string(type))303 else if (synth_field_is_string(type))
294 fmt = "%.*s";304 fmt = "%.*s";
305 else if (synth_field_is_stack(type))
306 fmt = "%s";
295 307
296 return fmt;308 return fmt;
297}309}
@@ -371,6 +383,23 @@ static enum print_line_t print_synth_event(struct trace_iterator *iter, · 73 unmodified lines
371 i == se->n_fields - 1 ? "" : " ");383 i == se->n_fields - 1 ? "" : " ");
372 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);384 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
373 }385 }
386 } else if (se->fields[i]->is_stack) {
387 u32 offset, data_offset, len;
388 unsigned long *p, *end;
389
390 offset = (u32)entry->fields[n_u64];
391 data_offset = offset & 0xffff;
392 len = offset >> 16;
393
394 p = (void *)entry + data_offset;
395 end = (void *)p + len - (sizeof(long) - 1);
396
397 trace_seq_printf(s, "%s=STACK:\n", se->fields[i]->name);
398
399 for (; *p && p < end; p++)
400 trace_seq_printf(s, "=> %pS\n", (void *)*p);
401 n_u64++;
402
374 } else {403 } else {
375 struct trace_print_flags __flags[] = {404 struct trace_print_flags __flags[] = {
376 __def_gfpflag_names, {-1, NULL} };405 __def_gfpflag_names, {-1, NULL} };
@@ -416,8 +445,7 @@ static unsigned int trace_string(struct synth_trace_event *entry, · 39 unmodified lines
416 if (is_dynamic) {445 if (is_dynamic) {
417 u32 data_offset;446 u32 data_offset;
418 447
419 data_offset = offsetof(typeof(*entry), fields);448 data_offset = struct_size(entry, fields, event->n_u64);
420 data_offset += event->n_u64 * sizeof(u64);
421 data_offset += data_size;449 data_offset += data_size;
422 450
423 len = kern_fetch_store_strlen((unsigned long)str_val);451 len = kern_fetch_store_strlen((unsigned long)str_val);
@@ -447,6 +475,43 @@ static unsigned int trace_string(struct synth_trace_event *entry, · 23 unmodified lines
447 return len;475 return len;
448}476}
449 477
478static unsigned int trace_stack(struct synth_trace_event *entry,
479 struct synth_event *event,
480 long *stack,
481 unsigned int data_size,
482 unsigned int *n_u64)
483{
484 unsigned int len;
485 u32 data_offset;
486 void *data_loc;
487
488 data_offset = struct_size(entry, fields, event->n_u64);
489 data_offset += data_size;
490
491 for (len = 0; len < HIST_STACKTRACE_DEPTH; len++) {
492 if (!stack[len])
493 break;
494 }
495
496 /* Include the zero'd element if it fits */
497 if (len < HIST_STACKTRACE_DEPTH)
498 len++;
499
500 len *= sizeof(long);
501
502 /* Find the dynamic section to copy the stack into. */
503 data_loc = (void *)entry + data_offset;
504 memcpy(data_loc, stack, len);
505
506 /* Fill in the field that holds the offset/len combo */
507 data_offset |= len << 16;
508 *(u32 *)&entry->fields[*n_u64] = data_offset;
509
510 (*n_u64)++;
511
512 return len;
513}
514
450static notrace void trace_event_raw_event_synth(void *__data,515static notrace void trace_event_raw_event_synth(void *__data,
451 u64 *var_ref_vals,516 u64 *var_ref_vals,
452 unsigned int *var_ref_idx)517 unsigned int *var_ref_idx)
@@ -473,7 +538,12 @@ static notrace void trace_event_raw_event_synth(void *__data, · 20 unmodified lines
473 val_idx = var_ref_idx[field_pos];538 val_idx = var_ref_idx[field_pos];
474 str_val = (char *)(long)var_ref_vals[val_idx];539 str_val = (char *)(long)var_ref_vals[val_idx];
475 540
476 len = kern_fetch_store_strlen((unsigned long)str_val);541 if (event->dynamic_fields[i]->is_stack) {
542 len = *((unsigned long *)str_val);
543 len *= sizeof(unsigned long);
544 } else {
545 len = kern_fetch_store_strlen((unsigned long)str_val);
546 }
477 547
478 fields_size += len;548 fields_size += len;
479 }549 }
@@ -499,6 +569,12 @@ static notrace void trace_event_raw_event_synth(void *__data, · 19 unmodified lines
499 event->fields[i]->is_dynamic,569 event->fields[i]->is_dynamic,
500 data_size, &n_u64);570 data_size, &n_u64);
501 data_size += len; /* only dynamic string increments */571 data_size += len; /* only dynamic string increments */
572 } else if (event->fields[i]->is_stack) {
573 long *stack = (long *)(long)var_ref_vals[val_idx];
574
575 len = trace_stack(entry, event, stack,
576 data_size, &n_u64);
577 data_size += len;
502 } else {578 } else {
503 struct synth_field *field = event->fields[i];579 struct synth_field *field = event->fields[i];
504 u64 val = var_ref_vals[val_idx];580 u64 val = var_ref_vals[val_idx];
@@ -561,6 +637,9 @@ static int __set_synth_event_print_fmt(struct synth_event *event, · 56 unmodified lines
561 event->fields[i]->is_dynamic)637 event->fields[i]->is_dynamic)
562 pos += snprintf(buf + pos, LEN_OR_ZERO,638 pos += snprintf(buf + pos, LEN_OR_ZERO,
563 ", __get_str(%s)", event->fields[i]->name);639 ", __get_str(%s)", event->fields[i]->name);
640 else if (event->fields[i]->is_stack)
641 pos += snprintf(buf + pos, LEN_OR_ZERO,
642 ", __get_stacktrace(%s)", event->fields[i]->name);
564 else643 else
565 pos += snprintf(buf + pos, LEN_OR_ZERO,644 pos += snprintf(buf + pos, LEN_OR_ZERO,
566 ", REC->%s", event->fields[i]->name);645 ", REC->%s", event->fields[i]->name);
@@ -697,7 +776,8 @@ static struct synth_field *parse_synth_field(int argc, char **argv, · 130 unmodified lines
697 ret = -EINVAL;776 ret = -EINVAL;
698 goto free;777 goto free;
699 } else if (size == 0) {778 } else if (size == 0) {
700 if (synth_field_is_string(field->type)) {779 if (synth_field_is_string(field->type) ||
780 synth_field_is_stack(field->type)) {
701 char *type;781 char *type;
702 782
703 len = sizeof("__data_loc ") + strlen(field->type) + 1;783 len = sizeof("__data_loc ") + strlen(field->type) + 1;
@@ -728,6 +808,8 @@ static struct synth_field *parse_synth_field(int argc, char **argv, · 24 unmodified lines
728 808
729 if (synth_field_is_string(field->type))809 if (synth_field_is_string(field->type))
730 field->is_string = true;810 field->is_string = true;
811 else if (synth_field_is_stack(field->type))
812 field->is_stack = true;
731 813
732 field->is_signed = synth_field_signed(field->type);814 field->is_signed = synth_field_signed(field->type);
733 out:815 out:
kernel/trace/trace_osnoise.c+1−1
@@ -1539,7 +1539,7 @@ static void osnoise_sleep(void) · 1538 unmodified lines
1539 wake_time = ktime_add_us(ktime_get(), interval);1539 wake_time = ktime_add_us(ktime_get(), interval);
1540 __set_current_state(TASK_INTERRUPTIBLE);1540 __set_current_state(TASK_INTERRUPTIBLE);
1541 1541
1542 while (schedule_hrtimeout_range(&wake_time, 0, HRTIMER_MODE_ABS)) {1542 while (schedule_hrtimeout(&wake_time, HRTIMER_MODE_ABS)) {
1543 if (kthread_should_stop())1543 if (kthread_should_stop())
1544 break;1544 break;
1545 }1545 }
kernel/trace/trace_seq.c+23−0
@@ -403,3 +403,26 @@ int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str, · 402 unmodified lines
403 return 1;403 return 1;
404}404}
405EXPORT_SYMBOL(trace_seq_hex_dump);405EXPORT_SYMBOL(trace_seq_hex_dump);
406
407/*
408 * trace_seq_acquire - acquire seq buffer with size len
409 * @s: trace sequence descriptor
410 * @len: size of buffer to be acquired
411 *
412 * acquire buffer with size of @len from trace_seq for output usage,
413 * user can fill string into that buffer.
414 *
415 * Returns start address of acquired buffer.
416 *
417 * it allow multiple usage in one trace output function call.
418 */
419char *trace_seq_acquire(struct trace_seq *s, unsigned int len)
420{
421 char *ret = trace_seq_buffer_ptr(s);
422
423 if (!WARN_ON_ONCE(seq_buf_buffer_left(&s->seq) < len))
424 seq_buf_commit(&s->seq, len);
425
426 return ret;
427}
428EXPORT_SYMBOL(trace_seq_acquire);
kernel/trace/trace_synth.h+1−0
@@ -18,6 +18,7 @@ struct synth_field { · 17 unmodified lines
18 bool is_signed;18 bool is_signed;
19 bool is_string;19 bool is_string;
20 bool is_dynamic;20 bool is_dynamic;
21 bool is_stack;
21};22};
22 23
23struct synth_event {24struct synth_event {
kernel/tracepoint.c+2−2
@@ -571,8 +571,8 @@ static void for_each_tracepoint_range( · 570 unmodified lines
571bool trace_module_has_bad_taint(struct module *mod)571bool trace_module_has_bad_taint(struct module *mod)
572{572{
573 return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP) |573 return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP) |
574 (1 << TAINT_UNSIGNED_MODULE) |574 (1 << TAINT_UNSIGNED_MODULE) | (1 << TAINT_TEST) |
575 (1 << TAINT_TEST));575 (1 << TAINT_LIVEPATCH));
576}576}
577 577
578static BLOCKING_NOTIFIER_HEAD(tracepoint_notify_list);578static BLOCKING_NOTIFIER_HEAD(tracepoint_notify_list);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t