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

Unified · Split

42 files
  1. Documentation/admin-guide/kernel-parameters.txt +29 −0
  2. Documentation/trace/events.rst +12 −0
  3. Documentation/trace/histogram.rst +198 −44
  4. include/linux/kernel.h +1 −1
  5. include/linux/trace.h +12 −0
  6. include/linux/trace_seq.h +5 −0
  7. include/linux/tracepoint.h +2 −2
  8. include/trace/bpf_probe.h +1 −44
  9. include/trace/perf.h +1 −45
  10. include/trace/stages/stage3_trace_output.h +3 −0
  11. include/trace/stages/stage6_event_callback.h +3 −0
  12. include/trace/stages/stage7_class_define.h +1 −0
  13. kernel/trace/Kconfig +10 −10
  14. kernel/trace/kprobe_event_gen_test.c +1 −1
  15. kernel/trace/ring_buffer.c +7 −2
  16. kernel/trace/synth_event_gen_test.c +1 −1
  17. kernel/trace/trace.c +145 −19
  18. kernel/trace/trace.h +6 −0
  19. kernel/trace/trace_events.c +5 −8
  20. kernel/trace/trace_events_filter.c +92 −1
  21. kernel/trace/trace_events_hist.c +103 −23
  22. kernel/trace/trace_events_synth.c +86 −4
  23. kernel/trace/trace_osnoise.c +1 −1
  24. kernel/trace/trace_seq.c +23 −0
  25. kernel/trace/trace_synth.h +1 −0
  26. kernel/tracepoint.c +2 −2
  27. samples/Kconfig +7 −0
  28. samples/Makefile +1 −0
  29. samples/ftrace/Makefile +1 −0
  30. samples/ftrace/ftrace-direct-modify.c +1 −1
  31. samples/ftrace/ftrace-direct-multi-modify.c +1 −1
  32. samples/ftrace/ftrace-direct-multi.c +1 −1
  33. samples/ftrace/ftrace-direct-too.c +1 −1
  34. samples/ftrace/ftrace-direct.c +1 −1
  35. samples/ftrace/ftrace-ops.c +252 −0
  36. samples/user_events/example.c +2 −2
  37. scripts/tracing/draw_functrace.py +3 −3
  38. tools/lib/api/fs/tracing_path.c +2 −2
  39. tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc +58 −0
  40. tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack.tc +24 −0
  41. tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc +6 −0
  42. tools/tracing/latency/latency-collector.c +1 −1
Documentation/admin-guide/kernel-parameters.txt+29−0
@@ -1509,6 +1509,15 @@ · 1508 unmodified lines
1509 boot up that is likely to be overridden by user space1509 boot up that is likely to be overridden by user space
1510 start up functionality.1510 start up functionality.
1511 1511
1512 Optionally, the snapshot can also be defined for a tracing
1513 instance that was created by the trace_instance= command
1514 line parameter.
1515
1516 trace_instance=foo,sched_switch ftrace_boot_snapshot=foo
1517
1518 The above will cause the "foo" tracing instance to trigger
1519 a snapshot at the end of boot up.
1520
1512 ftrace_dump_on_oops[=orig_cpu]1521 ftrace_dump_on_oops[=orig_cpu]
1513 [FTRACE] will dump the trace buffers on oops.1522 [FTRACE] will dump the trace buffers on oops.
1514 If no parameter is passed, ftrace will dump1523 If no parameter is passed, ftrace will dump
@@ -6283,6 +6292,26 @@ · 4768 unmodified lines
6283 comma-separated list of trace events to enable. See6292 comma-separated list of trace events to enable. See
6284 also Documentation/trace/events.rst6293 also Documentation/trace/events.rst
6285 6294
6295 trace_instance=[instance-info]
6296 [FTRACE] Create a ring buffer instance early in boot up.
6297 This will be listed in:
6298
6299 /sys/kernel/tracing/instances
6300
6301 Events can be enabled at the time the instance is created
6302 via:
6303
6304 trace_instance=<name>,<system1>:<event1>,<system2>:<event2>
6305
6306 Note, the "<system*>:" portion is optional if the event is
6307 unique.
6308
6309 trace_instance=foo,sched:sched_switch,irq_handler_entry,initcall
6310
6311 will enable the "sched_switch" event (note, the "sched:" is optional, and
6312 the same thing would happen if it was left off). The irq_handler_entry
6313 event, and all events under the "initcall" system.
6314
6286 trace_options=[option-list]6315 trace_options=[option-list]
6287 [FTRACE] Enable or disable tracer options at boot.6316 [FTRACE] Enable or disable tracer options at boot.
6288 The option-list is a comma delimited list of options6317 The option-list is a comma delimited list of options
Documentation/trace/events.rst+12−0
@@ -207,6 +207,18 @@ field name:: · 206 unmodified lines
207As the kernel will have to know how to retrieve the memory that the pointer207As the kernel will have to know how to retrieve the memory that the pointer
208is at from user space.208is at from user space.
209 209
210You can convert any long type to a function address and search by function name::
211
212 call_site.function == security_prepare_creds
213
214The above will filter when the field "call_site" falls on the address within
215"security_prepare_creds". That is, it will compare the value of "call_site" and
216the filter will return true if it is greater than or equal to the start of
217the function "security_prepare_creds" and less than the end of that function.
218
219The ".function" postfix can only be attached to values of size long, and can only
220be compared with "==" or "!=".
221
2105.2 Setting filters2225.2 Setting filters
211-------------------223-------------------
212 224
Documentation/trace/histogram.rst+198−44
@@ -81,6 +81,7 @@ Documentation written by Tom Zanussi · 80 unmodified lines
81 .usecs display a common_timestamp in microseconds81 .usecs display a common_timestamp in microseconds
82 .percent display a number of percentage value82 .percent display a number of percentage value
83 .graph display a bar-graph of a value83 .graph display a bar-graph of a value
84 .stacktrace display as a stacktrace (must by a long[] type)
84 ============= =================================================85 ============= =================================================
85 86
86 Note that in general the semantics of a given field aren't87 Note that in general the semantics of a given field aren't
@@ -1786,6 +1787,8 @@ or assigned to a variable and referenced in a subsequent expression:: · 1699 unmodified lines
1786 # echo 'hist:keys=next_pid:us_per_sec=1000000 ...' >> event/trigger1787 # echo 'hist:keys=next_pid:us_per_sec=1000000 ...' >> event/trigger
1787 # echo 'hist:keys=next_pid:timestamp_secs=common_timestamp/$us_per_sec ...' >> event/trigger1788 # echo 'hist:keys=next_pid:timestamp_secs=common_timestamp/$us_per_sec ...' >> event/trigger
1788 1789
1790Variables can even hold stacktraces, which are useful with synthetic events.
1791
17892.2.2 Synthetic Events17922.2.2 Synthetic Events
1790----------------------1793----------------------
1791 1794
@@ -1861,7 +1864,7 @@ A histogram can now be defined for the new synthetic event:: · 69 unmodified lines
1861The above shows the latency "lat" in a power of 2 grouping.1864The above shows the latency "lat" in a power of 2 grouping.
1862 1865
1863Like any other event, once a histogram is enabled for the event, the1866Like any other event, once a histogram is enabled for the event, the
1864output can be displayed by reading the event's 'hist' file.1867output can be displayed by reading the event's 'hist' file::
1865 1868
1866 # cat /sys/kernel/tracing/events/synthetic/wakeup_latency/hist1869 # cat /sys/kernel/tracing/events/synthetic/wakeup_latency/hist
1867 1870
@@ -1908,7 +1911,7 @@ output can be displayed by reading the event's 'hist' file. · 40 unmodified lines
1908 1911
1909 1912
1910The latency values can also be grouped linearly by a given size with1913The latency values can also be grouped linearly by a given size with
1911the ".buckets" modifier and specify a size (in this case groups of 10).1914the ".buckets" modifier and specify a size (in this case groups of 10)::
1912 1915
1913 # echo 'hist:keys=pid,prio,lat.buckets=10:sort=lat' >> \1916 # echo 'hist:keys=pid,prio,lat.buckets=10:sort=lat' >> \
1914 /sys/kernel/tracing/events/synthetic/wakeup_latency/trigger1917 /sys/kernel/tracing/events/synthetic/wakeup_latency/trigger
@@ -1940,6 +1943,157 @@ the ".buckets" modifier and specify a size (in this case groups of 10). · 25 unmodified lines
1940 Entries: 161943 Entries: 16
1941 Dropped: 01944 Dropped: 0
1942 1945
1946To save stacktraces, create a synthetic event with a field of type "unsigned long[]"
1947or even just "long[]". For example, to see how long a task is blocked in an
1948uninterruptible state::
1949
1950 # cd /sys/kernel/tracing
1951 # echo 's:block_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events
1952 # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace if prev_state == 2' >> events/sched/sched_switch/trigger
1953 # echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(block_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger
1954 # echo 1 > events/synthetic/block_lat/enable
1955 # cat trace
1956
1957 # tracer: nop
1958 #
1959 # entries-in-buffer/entries-written: 2/2 #P:8
1960 #
1961 # _-----=> irqs-off/BH-disabled
1962 # / _----=> need-resched
1963 # | / _---=> hardirq/softirq
1964 # || / _--=> preempt-depth
1965 # ||| / _-=> migrate-disable
1966 # |||| / delay
1967 # TASK-PID CPU# ||||| TIMESTAMP FUNCTION
1968 # | | | ||||| | |
1969 <idle>-0 [005] d..4. 521.164922: block_lat: pid=0 delta=8322 stack=STACK:
1970 => __schedule+0x448/0x7b0
1971 => schedule+0x5a/0xb0
1972 => io_schedule+0x42/0x70
1973 => bit_wait_io+0xd/0x60
1974 => __wait_on_bit+0x4b/0x140
1975 => out_of_line_wait_on_bit+0x91/0xb0
1976 => jbd2_journal_commit_transaction+0x1679/0x1a70
1977 => kjournald2+0xa9/0x280
1978 => kthread+0xe9/0x110
1979 => ret_from_fork+0x2c/0x50
1980
1981 <...>-2 [004] d..4. 525.184257: block_lat: pid=2 delta=76 stack=STACK:
1982 => __schedule+0x448/0x7b0
1983 => schedule+0x5a/0xb0
1984 => schedule_timeout+0x11a/0x150
1985 => wait_for_completion_killable+0x144/0x1f0
1986 => __kthread_create_on_node+0xe7/0x1e0
1987 => kthread_create_on_node+0x51/0x70
1988 => create_worker+0xcc/0x1a0
1989 => worker_thread+0x2ad/0x380
1990 => kthread+0xe9/0x110
1991 => ret_from_fork+0x2c/0x50
1992
1993A synthetic event that has a stacktrace field may use it as a key in
1994histogram::
1995
1996 # echo 'hist:keys=delta.buckets=100,stack.stacktrace:sort=delta' > events/synthetic/block_lat/trigger
1997 # cat events/synthetic/block_lat/hist
1998
1999 # event histogram
2000 #
2001 # trigger info: hist:keys=delta.buckets=100,stack.stacktrace:vals=hitcount:sort=delta.buckets=100:size=2048 [active]
2002 #
2003 { delta: ~ 0-99, stack.stacktrace __schedule+0xa19/0x1520
2004 schedule+0x6b/0x110
2005 io_schedule+0x46/0x80
2006 bit_wait_io+0x11/0x80
2007 __wait_on_bit+0x4e/0x120
2008 out_of_line_wait_on_bit+0x8d/0xb0
2009 __wait_on_buffer+0x33/0x40
2010 jbd2_journal_commit_transaction+0x155a/0x19b0
2011 kjournald2+0xab/0x270
2012 kthread+0xfa/0x130
2013 ret_from_fork+0x29/0x50
2014 } hitcount: 1
2015 { delta: ~ 0-99, stack.stacktrace __schedule+0xa19/0x1520
2016 schedule+0x6b/0x110
2017 io_schedule+0x46/0x80
2018 rq_qos_wait+0xd0/0x170
2019 wbt_wait+0x9e/0xf0
2020 __rq_qos_throttle+0x25/0x40
2021 blk_mq_submit_bio+0x2c3/0x5b0
2022 __submit_bio+0xff/0x190
2023 submit_bio_noacct_nocheck+0x25b/0x2b0
2024 submit_bio_noacct+0x20b/0x600
2025 submit_bio+0x28/0x90
2026 ext4_bio_write_page+0x1e0/0x8c0
2027 mpage_submit_page+0x60/0x80
2028 mpage_process_page_bufs+0x16c/0x180
2029 mpage_prepare_extent_to_map+0x23f/0x530
2030 } hitcount: 1
2031 { delta: ~ 0-99, stack.stacktrace __schedule+0xa19/0x1520
2032 schedule+0x6b/0x110
2033 schedule_hrtimeout_range_clock+0x97/0x110
2034 schedule_hrtimeout_range+0x13/0x20
2035 usleep_range_state+0x65/0x90
2036 __intel_wait_for_register+0x1c1/0x230 [i915]
2037 intel_psr_wait_for_idle_locked+0x171/0x2a0 [i915]
2038 intel_pipe_update_start+0x169/0x360 [i915]
2039 intel_update_crtc+0x112/0x490 [i915]
2040 skl_commit_modeset_enables+0x199/0x600 [i915]
2041 intel_atomic_commit_tail+0x7c4/0x1080 [i915]
2042 intel_atomic_commit_work+0x12/0x20 [i915]
2043 process_one_work+0x21c/0x3f0
2044 worker_thread+0x50/0x3e0
2045 kthread+0xfa/0x130
2046 } hitcount: 3
2047 { delta: ~ 0-99, stack.stacktrace __schedule+0xa19/0x1520
2048 schedule+0x6b/0x110
2049 schedule_timeout+0x11e/0x160
2050 __wait_for_common+0x8f/0x190
2051 wait_for_completion+0x24/0x30
2052 __flush_work.isra.0+0x1cc/0x360
2053 flush_work+0xe/0x20
2054 drm_mode_rmfb+0x18b/0x1d0 [drm]
2055 drm_mode_rmfb_ioctl+0x10/0x20 [drm]
2056 drm_ioctl_kernel+0xb8/0x150 [drm]
2057 drm_ioctl+0x243/0x560 [drm]
2058 __x64_sys_ioctl+0x92/0xd0
2059 do_syscall_64+0x59/0x90
2060 entry_SYSCALL_64_after_hwframe+0x72/0xdc
2061 } hitcount: 1
2062 { delta: ~ 0-99, stack.stacktrace __schedule+0xa19/0x1520
2063 schedule+0x6b/0x110
2064 schedule_timeout+0x87/0x160
2065 __wait_for_common+0x8f/0x190
2066 wait_for_completion_timeout+0x1d/0x30
2067 drm_atomic_helper_wait_for_flip_done+0x57/0x90 [drm_kms_helper]
2068 intel_atomic_commit_tail+0x8ce/0x1080 [i915]
2069 intel_atomic_commit_work+0x12/0x20 [i915]
2070 process_one_work+0x21c/0x3f0
2071 worker_thread+0x50/0x3e0
2072 kthread+0xfa/0x130
2073 ret_from_fork+0x29/0x50
2074 } hitcount: 1
2075 { delta: ~ 100-199, stack.stacktrace __schedule+0xa19/0x1520
2076 schedule+0x6b/0x110
2077 schedule_hrtimeout_range_clock+0x97/0x110
2078 schedule_hrtimeout_range+0x13/0x20
2079 usleep_range_state+0x65/0x90
2080 pci_set_low_power_state+0x17f/0x1f0
2081 pci_set_power_state+0x49/0x250
2082 pci_finish_runtime_suspend+0x4a/0x90
2083 pci_pm_runtime_suspend+0xcb/0x1b0
2084 __rpm_callback+0x48/0x120
2085 rpm_callback+0x67/0x70
2086 rpm_suspend+0x167/0x780
2087 rpm_idle+0x25a/0x380
2088 pm_runtime_work+0x93/0xc0
2089 process_one_work+0x21c/0x3f0
2090 } hitcount: 1
2091
2092 Totals:
2093 Hits: 10
2094 Entries: 7
2095 Dropped: 0
2096
19432.2.3 Hist trigger 'handlers' and 'actions'20972.2.3 Hist trigger 'handlers' and 'actions'
1944-------------------------------------------2098-------------------------------------------
1945 2099
@@ -2054,11 +2208,11 @@ The following commonly-used handler.action pairs are available: · 108 unmodified lines
2054 wakeup_new_test($testpid) if comm=="cyclictest"' >> \2208 wakeup_new_test($testpid) if comm=="cyclictest"' >> \
2055 /sys/kernel/tracing/events/sched/sched_wakeup_new/trigger2209 /sys/kernel/tracing/events/sched/sched_wakeup_new/trigger
2056 2210
2057 Or, equivalently, using the 'trace' keyword syntax:2211 Or, equivalently, using the 'trace' keyword syntax::
2058 2212
2059 # echo 'hist:keys=$testpid:testpid=pid:onmatch(sched.sched_wakeup_new).\2213 # echo 'hist:keys=$testpid:testpid=pid:onmatch(sched.sched_wakeup_new).\
2060 trace(wakeup_new_test,$testpid) if comm=="cyclictest"' >> \2214 trace(wakeup_new_test,$testpid) if comm=="cyclictest"' >> \
2061 /sys/kernel/tracing/events/sched/sched_wakeup_new/trigger2215 /sys/kernel/tracing/events/sched/sched_wakeup_new/trigger
2062 2216
2063 Creating and displaying a histogram based on those events is now2217 Creating and displaying a histogram based on those events is now
2064 just a matter of using the fields and new synthetic event in the2218 just a matter of using the fields and new synthetic event in the
@@ -2191,48 +2345,48 @@ The following commonly-used handler.action pairs are available: · 126 unmodified lines
2191 resulting latency, stored in wakeup_lat, exceeds the current2345 resulting latency, stored in wakeup_lat, exceeds the current
2192 maximum latency, a snapshot is taken. As part of the setup, all2346 maximum latency, a snapshot is taken. As part of the setup, all
2193 the scheduler events are also enabled, which are the events that2347 the scheduler events are also enabled, which are the events that
2194 will show up in the snapshot when it is taken at some point:2348 will show up in the snapshot when it is taken at some point::
2195 2349
2196 # echo 1 > /sys/kernel/tracing/events/sched/enable2350 # echo 1 > /sys/kernel/tracing/events/sched/enable
2197 2351
2198 # echo 'hist:keys=pid:ts0=common_timestamp.usecs \2352 # echo 'hist:keys=pid:ts0=common_timestamp.usecs \
2199 if comm=="cyclictest"' >> \2353 if comm=="cyclictest"' >> \
2200 /sys/kernel/tracing/events/sched/sched_waking/trigger2354 /sys/kernel/tracing/events/sched/sched_waking/trigger
2201 2355
2202 # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0: \2356 # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0: \
2203 onmax($wakeup_lat).save(next_prio,next_comm,prev_pid,prev_prio, \2357 onmax($wakeup_lat).save(next_prio,next_comm,prev_pid,prev_prio, \
2204 prev_comm):onmax($wakeup_lat).snapshot() \2358 prev_comm):onmax($wakeup_lat).snapshot() \
2205 if next_comm=="cyclictest"' >> \2359 if next_comm=="cyclictest"' >> \
2206 /sys/kernel/tracing/events/sched/sched_switch/trigger2360 /sys/kernel/tracing/events/sched/sched_switch/trigger
2207 2361
2208 When the histogram is displayed, for each bucket the max value2362 When the histogram is displayed, for each bucket the max value
2209 and the saved values corresponding to the max are displayed2363 and the saved values corresponding to the max are displayed
2210 following the rest of the fields.2364 following the rest of the fields.
2211 2365
2212 If a snapshot was taken, there is also a message indicating that,2366 If a snapshot was taken, there is also a message indicating that,
2213 along with the value and event that triggered the global maximum:2367 along with the value and event that triggered the global maximum::
2214 2368
2215 # cat /sys/kernel/tracing/events/sched/sched_switch/hist2369 # cat /sys/kernel/tracing/events/sched/sched_switch/hist
2216 { next_pid: 2101 } hitcount: 2002370 { next_pid: 2101 } hitcount: 200
2217 max: 52 next_prio: 120 next_comm: cyclictest \2371 max: 52 next_prio: 120 next_comm: cyclictest \
2218 prev_pid: 0 prev_prio: 120 prev_comm: swapper/62372 prev_pid: 0 prev_prio: 120 prev_comm: swapper/6
2219 2373
2220 { next_pid: 2103 } hitcount: 13262374 { next_pid: 2103 } hitcount: 1326
2221 max: 572 next_prio: 19 next_comm: cyclictest \2375 max: 572 next_prio: 19 next_comm: cyclictest \
2222 prev_pid: 0 prev_prio: 120 prev_comm: swapper/12376 prev_pid: 0 prev_prio: 120 prev_comm: swapper/1
2223 2377
2224 { next_pid: 2102 } hitcount: 1982 \2378 { next_pid: 2102 } hitcount: 1982 \
2225 max: 74 next_prio: 19 next_comm: cyclictest \2379 max: 74 next_prio: 19 next_comm: cyclictest \
2226 prev_pid: 0 prev_prio: 120 prev_comm: swapper/52380 prev_pid: 0 prev_prio: 120 prev_comm: swapper/5
2227 2381
2228 Snapshot taken (see tracing/snapshot). Details:2382 Snapshot taken (see tracing/snapshot). Details:
2229 triggering value { onmax($wakeup_lat) }: 572 \2383 triggering value { onmax($wakeup_lat) }: 572 \
2230 triggered by event with key: { next_pid: 2103 }2384 triggered by event with key: { next_pid: 2103 }
2231 2385
2232 Totals:2386 Totals:
2233 Hits: 35082387 Hits: 3508
2234 Entries: 32388 Entries: 3
2235 Dropped: 02389 Dropped: 0
2236 2390
2237 In the above case, the event that triggered the global maximum has2391 In the above case, the event that triggered the global maximum has
2238 the key with next_pid == 2103. If you look at the bucket that has2392 the key with next_pid == 2103. If you look at the bucket that has
@@ -2310,15 +2464,15 @@ The following commonly-used handler.action pairs are available: · 71 unmodified lines
2310 $cwnd variable. If the value has changed, a snapshot is taken.2464 $cwnd variable. If the value has changed, a snapshot is taken.
2311 As part of the setup, all the scheduler and tcp events are also2465 As part of the setup, all the scheduler and tcp events are also
2312 enabled, which are the events that will show up in the snapshot2466 enabled, which are the events that will show up in the snapshot
2313 when it is taken at some point:2467 when it is taken at some point::
2314 2468
2315 # echo 1 > /sys/kernel/tracing/events/sched/enable2469 # echo 1 > /sys/kernel/tracing/events/sched/enable
2316 # echo 1 > /sys/kernel/tracing/events/tcp/enable2470 # echo 1 > /sys/kernel/tracing/events/tcp/enable
2317 2471
2318 # echo 'hist:keys=dport:cwnd=snd_cwnd: \2472 # echo 'hist:keys=dport:cwnd=snd_cwnd: \
2319 onchange($cwnd).save(snd_wnd,srtt,rcv_wnd): \2473 onchange($cwnd).save(snd_wnd,srtt,rcv_wnd): \
2320 onchange($cwnd).snapshot()' >> \2474 onchange($cwnd).snapshot()' >> \
2321 /sys/kernel/tracing/events/tcp/tcp_probe/trigger2475 /sys/kernel/tracing/events/tcp/tcp_probe/trigger
2322 2476
2323 When the histogram is displayed, for each bucket the tracked value2477 When the histogram is displayed, for each bucket the tracked value
2324 and the saved values corresponding to that value are displayed2478 and the saved values corresponding to that value are displayed
@@ -2341,10 +2495,10 @@ The following commonly-used handler.action pairs are available: · 16 unmodified lines
2341 { dport: 443 } hitcount: 2112495 { dport: 443 } hitcount: 211
2342 changed: 10 snd_wnd: 26960 srtt: 17379 rcv_wnd: 288002496 changed: 10 snd_wnd: 26960 srtt: 17379 rcv_wnd: 28800
2343 2497
2344 Snapshot taken (see tracing/snapshot). Details::2498 Snapshot taken (see tracing/snapshot). Details:
2345 2499
2346 triggering value { onchange($cwnd) }: 102500 triggering value { onchange($cwnd) }: 10
2347 triggered by event with key: { dport: 80 }2501 triggered by event with key: { dport: 80 }
2348 2502
2349 Totals:2503 Totals:
2350 Hits: 4142504 Hits: 414
include/linux/kernel.h+1−1
@@ -297,7 +297,7 @@ bool mac_pton(const char *s, u8 *mac); · 296 unmodified lines
297 *297 *
298 * Use tracing_on/tracing_off when you want to quickly turn on or off298 * Use tracing_on/tracing_off when you want to quickly turn on or off
299 * tracing. It simply enables or disables the recording of the trace events.299 * tracing. It simply enables or disables the recording of the trace events.
300 * This also corresponds to the user space /sys/kernel/debug/tracing/tracing_on300 * This also corresponds to the user space /sys/kernel/tracing/tracing_on
301 * file, which gives a means for the kernel and userspace to interact.301 * file, which gives a means for the kernel and userspace to interact.
302 * Place a tracing_off() in the kernel where you want tracing to end.302 * Place a tracing_off() in the kernel where you want tracing to end.
303 * From user space, examine the trace, and then echo 1 > tracing_on303 * From user space, examine the trace, and then echo 1 > tracing_on
include/linux/trace.h+12−0
@@ -33,6 +33,18 @@ struct trace_array; · 32 unmodified lines
33int register_ftrace_export(struct trace_export *export);33int register_ftrace_export(struct trace_export *export);
34int unregister_ftrace_export(struct trace_export *export);34int unregister_ftrace_export(struct trace_export *export);
35 35
36/**
37 * trace_array_puts - write a constant string into the trace buffer.
38 * @tr: The trace array to write to
39 * @str: The constant string to write
40 */
41#define trace_array_puts(tr, str) \
42 ({ \
43 str ? __trace_array_puts(tr, _THIS_IP_, str, strlen(str)) : -1; \
44 })
45int __trace_array_puts(struct trace_array *tr, unsigned long ip,
46 const char *str, int size);
47
36void trace_printk_init_buffers(void);48void trace_printk_init_buffers(void);
37__printf(3, 4)49__printf(3, 4)
38int trace_array_printk(struct trace_array *tr, unsigned long ip,50int trace_array_printk(struct trace_array *tr, unsigned long ip,
include/linux/trace_seq.h+5−0
@@ -95,6 +95,7 @@ extern void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp, · 94 unmodified lines
95extern int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,95extern int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,
96 int prefix_type, int rowsize, int groupsize,96 int prefix_type, int rowsize, int groupsize,
97 const void *buf, size_t len, bool ascii);97 const void *buf, size_t len, bool ascii);
98char *trace_seq_acquire(struct trace_seq *s, unsigned int len);
98 99
99#else /* CONFIG_TRACING */100#else /* CONFIG_TRACING */
100static inline __printf(2, 3)101static inline __printf(2, 3)
@@ -139,6 +140,10 @@ static inline int trace_seq_path(struct trace_seq *s, const struct path *path) · 38 unmodified lines
139{140{
140 return 0;141 return 0;
141}142}
143static inline char *trace_seq_acquire(struct trace_seq *s, unsigned int len)
144{
145 return NULL;
146}
142#endif /* CONFIG_TRACING */147#endif /* CONFIG_TRACING */
143 148
144#endif /* _LINUX_TRACE_SEQ_H */149#endif /* _LINUX_TRACE_SEQ_H */
include/linux/tracepoint.h+2−2
@@ -482,7 +482,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · 481 unmodified lines
482 * * This is how the trace record is structured and will482 * * This is how the trace record is structured and will
483 * * be saved into the ring buffer. These are the fields483 * * be saved into the ring buffer. These are the fields
484 * * that will be exposed to user-space in484 * * that will be exposed to user-space in
485 * * /sys/kernel/debug/tracing/events/<*>/format.485 * * /sys/kernel/tracing/events/<*>/format.
486 * *486 * *
487 * * The declared 'local variable' is called '__entry'487 * * The declared 'local variable' is called '__entry'
488 * *488 * *
@@ -542,7 +542,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · 53 unmodified lines
542 * tracepoint callback (this is used by programmatic plugins and542 * tracepoint callback (this is used by programmatic plugins and
543 * can also by used by generic instrumentation like SystemTap), and543 * can also by used by generic instrumentation like SystemTap), and
544 * it is also used to expose a structured trace record in544 * it is also used to expose a structured trace record in
545 * /sys/kernel/debug/tracing/events/.545 * /sys/kernel/tracing/events/.
546 *546 *
547 * A set of (un)registration functions can be passed to the variant547 * A set of (un)registration functions can be passed to the variant
548 * TRACE_EVENT_FN to perform any (un)registration work.548 * TRACE_EVENT_FN to perform any (un)registration work.
include/trace/bpf_probe.h+1−44
@@ -4,50 +4,7 @@ · 3 unmodified lines
4 4
5#ifdef CONFIG_BPF_EVENTS5#ifdef CONFIG_BPF_EVENTS
6 6
7#undef __entry7#include "stages/stage6_event_callback.h"
8#define __entry entry
9
10#undef __get_dynamic_array
11#define __get_dynamic_array(field) \
12 ((void *)__entry + (__entry->__data_loc_##field & 0xffff))
13
14#undef __get_dynamic_array_len
15#define __get_dynamic_array_len(field) \
16 ((__entry->__data_loc_##field >> 16) & 0xffff)
17
18#undef __get_str
19#define __get_str(field) ((char *)__get_dynamic_array(field))
20
21#undef __get_bitmask
22#define __get_bitmask(field) (char *)__get_dynamic_array(field)
23
24#undef __get_cpumask
25#define __get_cpumask(field) (char *)__get_dynamic_array(field)
26
27#undef __get_sockaddr
28#define __get_sockaddr(field) ((struct sockaddr *)__get_dynamic_array(field))
29
30#undef __get_rel_dynamic_array
31#define __get_rel_dynamic_array(field) \
32 ((void *)(&__entry->__rel_loc_##field) + \
33 sizeof(__entry->__rel_loc_##field) + \
34 (__entry->__rel_loc_##field & 0xffff))
35
36#undef __get_rel_dynamic_array_len
37#define __get_rel_dynamic_array_len(field) \
38 ((__entry->__rel_loc_##field >> 16) & 0xffff)
39
40#undef __get_rel_str
41#define __get_rel_str(field) ((char *)__get_rel_dynamic_array(field))
42
43#undef __get_rel_bitmask
44#define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field)
45
46#undef __get_rel_cpumask
47#define __get_rel_cpumask(field) (char *)__get_rel_dynamic_array(field)
48
49#undef __get_rel_sockaddr
50#define __get_rel_sockaddr(field) ((struct sockaddr *)__get_rel_dynamic_array(field))
51 8
52#undef __perf_count9#undef __perf_count
53#define __perf_count(c) (c)10#define __perf_count(c) (c)
include/trace/perf.h+1−45
@@ -4,51 +4,7 @@ · 3 unmodified lines
4 4
5#ifdef CONFIG_PERF_EVENTS5#ifdef CONFIG_PERF_EVENTS
6 6
7#undef __entry7#include "stages/stage6_event_callback.h"
8#define __entry entry
9
10#undef __get_dynamic_array
11#define __get_dynamic_array(field) \
12 ((void *)__entry + (__entry->__data_loc_##field & 0xffff))
13
14#undef __get_dynamic_array_len
15#define __get_dynamic_array_len(field) \
16 ((__entry->__data_loc_##field >> 16) & 0xffff)
17
18#undef __get_str
19#define __get_str(field) ((char *)__get_dynamic_array(field))
20
21#undef __get_bitmask
22#define __get_bitmask(field) (char *)__get_dynamic_array(field)
23
24#undef __get_cpumask
25#define __get_cpumask(field) (char *)__get_dynamic_array(field)
26
27#undef __get_sockaddr
28#define __get_sockaddr(field) ((struct sockaddr *)__get_dynamic_array(field))
29
30#undef __get_rel_dynamic_array
31#define __get_rel_dynamic_array(field) \
32 ((void *)__entry + \
33 offsetof(typeof(*__entry), __rel_loc_##field) + \
34 sizeof(__entry->__rel_loc_##field) + \
35 (__entry->__rel_loc_##field & 0xffff))
36
37#undef __get_rel_dynamic_array_len
38#define __get_rel_dynamic_array_len(field) \
39 ((__entry->__rel_loc_##field >> 16) & 0xffff)
40
41#undef __get_rel_str
42#define __get_rel_str(field) ((char *)__get_rel_dynamic_array(field))
43
44#undef __get_rel_bitmask
45#define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field)
46
47#undef __get_rel_cpumask
48#define __get_rel_cpumask(field) (char *)__get_rel_dynamic_array(field)
49
50#undef __get_rel_sockaddr
51#define __get_rel_sockaddr(field) ((struct sockaddr *)__get_rel_dynamic_array(field))
52 8
53#undef __perf_count9#undef __perf_count
54#define __perf_count(c) (__count = (c))10#define __perf_count(c) (__count = (c))
include/trace/stages/stage3_trace_output.h+3−0
@@ -139,3 +139,6 @@ · 138 unmodified lines
139 u64 ____val = (u64)(value); \139 u64 ____val = (u64)(value); \
140 (u32) do_div(____val, NSEC_PER_SEC); \140 (u32) do_div(____val, NSEC_PER_SEC); \
141 })141 })
142
143#undef __get_buf
144#define __get_buf(len) trace_seq_acquire(p, (len))
include/trace/stages/stage6_event_callback.h+3−0
@@ -2,6 +2,9 @@ · 1 unmodified line
2 2
3/* Stage 6 definitions for creating trace events */3/* Stage 6 definitions for creating trace events */
4 4
5/* Reuse some of the stage 3 macros */
6#include "stage3_trace_output.h"
7
5#undef __entry8#undef __entry
6#define __entry entry9#define __entry entry
7 10
include/trace/stages/stage7_class_define.h+1−0
@@ -23,6 +23,7 @@ · 22 unmodified lines
23#undef __get_rel_sockaddr23#undef __get_rel_sockaddr
24#undef __print_array24#undef __print_array
25#undef __print_hex_dump25#undef __print_hex_dump
26#undef __get_buf
26 27
27/*28/*
28 * The below is not executed in the kernel. It is only what is29 * The below is not executed in the kernel. It is only what is
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);
samples/Kconfig+7−0
@@ -46,6 +46,13 @@ config SAMPLE_FTRACE_DIRECT_MULTI · 45 unmodified lines
46 that hooks to wake_up_process and schedule, and prints46 that hooks to wake_up_process and schedule, and prints
47 the function addresses.47 the function addresses.
48 48
49config SAMPLE_FTRACE_OPS
50 tristate "Build custom ftrace ops example"
51 depends on FUNCTION_TRACER
52 help
53 This builds an ftrace ops example that hooks two functions and
54 measures the time taken to invoke one function a number of times.
55
49config SAMPLE_TRACE_ARRAY56config SAMPLE_TRACE_ARRAY
50 tristate "Build sample module for kernel access to Ftrace instancess"57 tristate "Build sample module for kernel access to Ftrace instancess"
51 depends on EVENT_TRACING && m58 depends on EVENT_TRACING && m
samples/Makefile+1−0
@@ -24,6 +24,7 @@ obj-$(CONFIG_SAMPLE_TRACE_CUSTOM_EVENTS) += trace_events/ · 23 unmodified lines
24obj-$(CONFIG_SAMPLE_TRACE_PRINTK) += trace_printk/24obj-$(CONFIG_SAMPLE_TRACE_PRINTK) += trace_printk/
25obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace/25obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace/
26obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace/26obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace/
27obj-$(CONFIG_SAMPLE_FTRACE_OPS) += ftrace/
27obj-$(CONFIG_SAMPLE_TRACE_ARRAY) += ftrace/28obj-$(CONFIG_SAMPLE_TRACE_ARRAY) += ftrace/
28subdir-$(CONFIG_SAMPLE_UHID) += uhid29subdir-$(CONFIG_SAMPLE_UHID) += uhid
29obj-$(CONFIG_VIDEO_PCI_SKELETON) += v4l/30obj-$(CONFIG_VIDEO_PCI_SKELETON) += v4l/
samples/ftrace/Makefile+1−0
@@ -5,6 +5,7 @@ obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-too.o · 4 unmodified lines
5obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-modify.o5obj-$(CONFIG_SAMPLE_FTRACE_DIRECT) += ftrace-direct-modify.o
6obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace-direct-multi.o6obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace-direct-multi.o
7obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace-direct-multi-modify.o7obj-$(CONFIG_SAMPLE_FTRACE_DIRECT_MULTI) += ftrace-direct-multi-modify.o
8obj-$(CONFIG_SAMPLE_FTRACE_OPS) += ftrace-ops.o
8 9
9CFLAGS_sample-trace-array.o := -I$(src)10CFLAGS_sample-trace-array.o := -I$(src)
10obj-$(CONFIG_SAMPLE_TRACE_ARRAY) += sample-trace-array.o11obj-$(CONFIG_SAMPLE_TRACE_ARRAY) += sample-trace-array.o
samples/ftrace/ftrace-direct-modify.c+1−1
@@ -3,7 +3,6 @@ · 2 unmodified lines
3#include <linux/kthread.h>3#include <linux/kthread.h>
4#include <linux/ftrace.h>4#include <linux/ftrace.h>
5#include <asm/asm-offsets.h>5#include <asm/asm-offsets.h>
6#include <asm/nospec-branch.h>
7 6
8extern void my_direct_func1(void);7extern void my_direct_func1(void);
9extern void my_direct_func2(void);8extern void my_direct_func2(void);
@@ -26,6 +25,7 @@ static unsigned long my_ip = (unsigned long)schedule; · 16 unmodified lines
26#ifdef CONFIG_X86_6425#ifdef CONFIG_X86_64
27 26
28#include <asm/ibt.h>27#include <asm/ibt.h>
28#include <asm/nospec-branch.h>
29 29
30asm (30asm (
31" .pushsection .text, \"ax\", @progbits\n"31" .pushsection .text, \"ax\", @progbits\n"
samples/ftrace/ftrace-direct-multi-modify.c+1−1
@@ -3,7 +3,6 @@ · 2 unmodified lines
3#include <linux/kthread.h>3#include <linux/kthread.h>
4#include <linux/ftrace.h>4#include <linux/ftrace.h>
5#include <asm/asm-offsets.h>5#include <asm/asm-offsets.h>
6#include <asm/nospec-branch.h>
7 6
8extern void my_direct_func1(unsigned long ip);7extern void my_direct_func1(unsigned long ip);
9extern void my_direct_func2(unsigned long ip);8extern void my_direct_func2(unsigned long ip);
@@ -24,6 +23,7 @@ extern void my_tramp2(void *); · 14 unmodified lines
24#ifdef CONFIG_X86_6423#ifdef CONFIG_X86_64
25 24
26#include <asm/ibt.h>25#include <asm/ibt.h>
26#include <asm/nospec-branch.h>
27 27
28asm (28asm (
29" .pushsection .text, \"ax\", @progbits\n"29" .pushsection .text, \"ax\", @progbits\n"
samples/ftrace/ftrace-direct-multi.c+1−1
@@ -5,7 +5,6 @@ · 4 unmodified lines
5#include <linux/ftrace.h>5#include <linux/ftrace.h>
6#include <linux/sched/stat.h>6#include <linux/sched/stat.h>
7#include <asm/asm-offsets.h>7#include <asm/asm-offsets.h>
8#include <asm/nospec-branch.h>
9 8
10extern void my_direct_func(unsigned long ip);9extern void my_direct_func(unsigned long ip);
11 10
@@ -19,6 +18,7 @@ extern void my_tramp(void *); · 7 unmodified lines
19#ifdef CONFIG_X86_6418#ifdef CONFIG_X86_64
20 19
21#include <asm/ibt.h>20#include <asm/ibt.h>
21#include <asm/nospec-branch.h>
22 22
23asm (23asm (
24" .pushsection .text, \"ax\", @progbits\n"24" .pushsection .text, \"ax\", @progbits\n"
samples/ftrace/ftrace-direct-too.c+1−1
@@ -4,7 +4,6 @@ · 3 unmodified lines
4#include <linux/mm.h> /* for handle_mm_fault() */4#include <linux/mm.h> /* for handle_mm_fault() */
5#include <linux/ftrace.h>5#include <linux/ftrace.h>
6#include <asm/asm-offsets.h>6#include <asm/asm-offsets.h>
7#include <asm/nospec-branch.h>
8 7
9extern void my_direct_func(struct vm_area_struct *vma,8extern void my_direct_func(struct vm_area_struct *vma,
10 unsigned long address, unsigned int flags);9 unsigned long address, unsigned int flags);
@@ -21,6 +20,7 @@ extern void my_tramp(void *); · 10 unmodified lines
21#ifdef CONFIG_X86_6420#ifdef CONFIG_X86_64
22 21
23#include <asm/ibt.h>22#include <asm/ibt.h>
23#include <asm/nospec-branch.h>
24 24
25asm (25asm (
26" .pushsection .text, \"ax\", @progbits\n"26" .pushsection .text, \"ax\", @progbits\n"
samples/ftrace/ftrace-direct.c+1−1
@@ -4,7 +4,6 @@ · 3 unmodified lines
4#include <linux/sched.h> /* for wake_up_process() */4#include <linux/sched.h> /* for wake_up_process() */
5#include <linux/ftrace.h>5#include <linux/ftrace.h>
6#include <asm/asm-offsets.h>6#include <asm/asm-offsets.h>
7#include <asm/nospec-branch.h>
8 7
9extern void my_direct_func(struct task_struct *p);8extern void my_direct_func(struct task_struct *p);
10 9
@@ -18,6 +17,7 @@ extern void my_tramp(void *); · 7 unmodified lines
18#ifdef CONFIG_X86_6417#ifdef CONFIG_X86_64
19 18
20#include <asm/ibt.h>19#include <asm/ibt.h>
20#include <asm/nospec-branch.h>
21 21
22asm (22asm (
23" .pushsection .text, \"ax\", @progbits\n"23" .pushsection .text, \"ax\", @progbits\n"
samples/ftrace/ftrace-ops.c+252−0
@@ -0,0 +1,252 @@
1// SPDX-License-Identifier: GPL-2.0-only
2
3#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
4
5#include <linux/ftrace.h>
6#include <linux/ktime.h>
7#include <linux/module.h>
8
9#include <asm/barrier.h>
10
11/*
12 * Arbitrary large value chosen to be sufficiently large to minimize noise but
13 * sufficiently small to complete quickly.
14 */
15static unsigned int nr_function_calls = 100000;
16module_param(nr_function_calls, uint, 0);
17MODULE_PARM_DESC(nr_function_calls, "How many times to call the relevant tracee");
18
19/*
20 * The number of ops associated with a call site affects whether a tracer can
21 * be called directly or whether it's necessary to go via the list func, which
22 * can be significantly more expensive.
23 */
24static unsigned int nr_ops_relevant = 1;
25module_param(nr_ops_relevant, uint, 0);
26MODULE_PARM_DESC(nr_ops_relevant, "How many ftrace_ops to associate with the relevant tracee");
27
28/*
29 * On architectures where all call sites share the same trampoline, having
30 * tracers enabled for distinct functions can force the use of the list func
31 * and incur overhead for all call sites.
32 */
33static unsigned int nr_ops_irrelevant;
34module_param(nr_ops_irrelevant, uint, 0);
35MODULE_PARM_DESC(nr_ops_irrelevant, "How many ftrace_ops to associate with the irrelevant tracee");
36
37/*
38 * On architectures with DYNAMIC_FTRACE_WITH_REGS, saving the full pt_regs can
39 * be more expensive than only saving the minimal necessary regs.
40 */
41static bool save_regs;
42module_param(save_regs, bool, 0);
43MODULE_PARM_DESC(save_regs, "Register ops with FTRACE_OPS_FL_SAVE_REGS (save all registers in the trampoline)");
44
45static bool assist_recursion;
46module_param(assist_recursion, bool, 0);
47MODULE_PARM_DESC(assist_reursion, "Register ops with FTRACE_OPS_FL_RECURSION");
48
49static bool assist_rcu;
50module_param(assist_rcu, bool, 0);
51MODULE_PARM_DESC(assist_reursion, "Register ops with FTRACE_OPS_FL_RCU");
52
53/*
54 * By default, a trivial tracer is used which immediately returns to mimimize
55 * overhead. Sometimes a consistency check using a more expensive tracer is
56 * desireable.
57 */
58static bool check_count;
59module_param(check_count, bool, 0);
60MODULE_PARM_DESC(check_count, "Check that tracers are called the expected number of times\n");
61
62/*
63 * Usually it's not interesting to leave the ops registered after the test
64 * runs, but sometimes it can be useful to leave them registered so that they
65 * can be inspected through the tracefs 'enabled_functions' file.
66 */
67static bool persist;
68module_param(persist, bool, 0);
69MODULE_PARM_DESC(persist, "Successfully load module and leave ftrace ops registered after test completes\n");
70
71/*
72 * Marked as noinline to ensure that an out-of-line traceable copy is
73 * generated by the compiler.
74 *
75 * The barrier() ensures the compiler won't elide calls by determining there
76 * are no side-effects.
77 */
78static noinline void tracee_relevant(void)
79{
80 barrier();
81}
82
83/*
84 * Marked as noinline to ensure that an out-of-line traceable copy is
85 * generated by the compiler.
86 *
87 * The barrier() ensures the compiler won't elide calls by determining there
88 * are no side-effects.
89 */
90static noinline void tracee_irrelevant(void)
91{
92 barrier();
93}
94
95struct sample_ops {
96 struct ftrace_ops ops;
97 unsigned int count;
98};
99
100static void ops_func_nop(unsigned long ip, unsigned long parent_ip,
101 struct ftrace_ops *op,
102 struct ftrace_regs *fregs)
103{
104 /* do nothing */
105}
106
107static void ops_func_count(unsigned long ip, unsigned long parent_ip,
108 struct ftrace_ops *op,
109 struct ftrace_regs *fregs)
110{
111 struct sample_ops *self;
112
113 self = container_of(op, struct sample_ops, ops);
114 self->count++;
115}
116
117static struct sample_ops *ops_relevant;
118static struct sample_ops *ops_irrelevant;
119
120static struct sample_ops *ops_alloc_init(void *tracee, ftrace_func_t func,
121 unsigned long flags, int nr)
122{
123 struct sample_ops *ops;
124
125 ops = kcalloc(nr, sizeof(*ops), GFP_KERNEL);
126 if (WARN_ON_ONCE(!ops))
127 return NULL;
128
129 for (unsigned int i = 0; i < nr; i++) {
130 ops[i].ops.func = func;
131 ops[i].ops.flags = flags;
132 WARN_ON_ONCE(ftrace_set_filter_ip(&ops[i].ops, (unsigned long)tracee, 0, 0));
133 WARN_ON_ONCE(register_ftrace_function(&ops[i].ops));
134 }
135
136 return ops;
137}
138
139static void ops_destroy(struct sample_ops *ops, int nr)
140{
141 if (!ops)
142 return;
143
144 for (unsigned int i = 0; i < nr; i++) {
145 WARN_ON_ONCE(unregister_ftrace_function(&ops[i].ops));
146 ftrace_free_filter(&ops[i].ops);
147 }
148
149 kfree(ops);
150}
151
152static void ops_check(struct sample_ops *ops, int nr,
153 unsigned int expected_count)
154{
155 if (!ops || !check_count)
156 return;
157
158 for (unsigned int i = 0; i < nr; i++) {
159 if (ops->count == expected_count)
160 continue;
161 pr_warn("Counter called %u times (expected %u)\n",
162 ops->count, expected_count);
163 }
164}
165
166static ftrace_func_t tracer_relevant = ops_func_nop;
167static ftrace_func_t tracer_irrelevant = ops_func_nop;
168
169static int __init ftrace_ops_sample_init(void)
170{
171 unsigned long flags = 0;
172 ktime_t start, end;
173 u64 period;
174
175 if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) && save_regs) {
176 pr_info("this kernel does not support saving registers\n");
177 save_regs = false;
178 } else if (save_regs) {
179 flags |= FTRACE_OPS_FL_SAVE_REGS;
180 }
181
182 if (assist_recursion)
183 flags |= FTRACE_OPS_FL_RECURSION;
184
185 if (assist_rcu)
186 flags |= FTRACE_OPS_FL_RCU;
187
188 if (check_count) {
189 tracer_relevant = ops_func_count;
190 tracer_irrelevant = ops_func_count;
191 }
192
193 pr_info("registering:\n"
194 " relevant ops: %u\n"
195 " tracee: %ps\n"
196 " tracer: %ps\n"
197 " irrelevant ops: %u\n"
198 " tracee: %ps\n"
199 " tracer: %ps\n"
200 " saving registers: %s\n"
201 " assist recursion: %s\n"
202 " assist RCU: %s\n",
203 nr_ops_relevant, tracee_relevant, tracer_relevant,
204 nr_ops_irrelevant, tracee_irrelevant, tracer_irrelevant,
205 save_regs ? "YES" : "NO",
206 assist_recursion ? "YES" : "NO",
207 assist_rcu ? "YES" : "NO");
208
209 ops_relevant = ops_alloc_init(tracee_relevant, tracer_relevant,
210 flags, nr_ops_relevant);
211 ops_irrelevant = ops_alloc_init(tracee_irrelevant, tracer_irrelevant,
212 flags, nr_ops_irrelevant);
213
214 start = ktime_get();
215 for (unsigned int i = 0; i < nr_function_calls; i++)
216 tracee_relevant();
217 end = ktime_get();
218
219 ops_check(ops_relevant, nr_ops_relevant, nr_function_calls);
220 ops_check(ops_irrelevant, nr_ops_irrelevant, 0);
221
222 period = ktime_to_ns(ktime_sub(end, start));
223
224 pr_info("Attempted %u calls to %ps in %lluns (%lluns / call)\n",
225 nr_function_calls, tracee_relevant,
226 period, div_u64(period, nr_function_calls));
227
228 if (persist)
229 return 0;
230
231 ops_destroy(ops_relevant, nr_ops_relevant);
232 ops_destroy(ops_irrelevant, nr_ops_irrelevant);
233
234 /*
235 * The benchmark completed sucessfully, but there's no reason to keep
236 * the module around. Return an error do the user doesn't have to
237 * manually unload the module.
238 */
239 return -EINVAL;
240}
241module_init(ftrace_ops_sample_init);
242
243static void __exit ftrace_ops_sample_exit(void)
244{
245 ops_destroy(ops_relevant, nr_ops_relevant);
246 ops_destroy(ops_irrelevant, nr_ops_irrelevant);
247}
248module_exit(ftrace_ops_sample_exit);
249
250MODULE_AUTHOR("Mark Rutland");
251MODULE_DESCRIPTION("Example of using custom ftrace_ops");
252MODULE_LICENSE("GPL");
samples/user_events/example.c+2−2
@@ -23,8 +23,8 @@ · 22 unmodified lines
23#endif23#endif
24 24
25/* Assumes debugfs is mounted */25/* Assumes debugfs is mounted */
26const char *data_file = "/sys/kernel/debug/tracing/user_events_data";26const char *data_file = "/sys/kernel/tracing/user_events_data";
27const char *status_file = "/sys/kernel/debug/tracing/user_events_status";27const char *status_file = "/sys/kernel/tracing/user_events_status";
28 28
29static int event_status(long **status)29static int event_status(long **status)
30{30{
scripts/tracing/draw_functrace.py+3−3
@@ -12,9 +12,9 @@ calls. Only the functions's names and the call time are provided. · 11 unmodified lines
12 12
13Usage:13Usage:
14 Be sure that you have CONFIG_FUNCTION_TRACER14 Be sure that you have CONFIG_FUNCTION_TRACER
15 # mount -t debugfs nodev /sys/kernel/debug15 # mount -t tracefs nodev /sys/kernel/tracing
16 # echo function > /sys/kernel/debug/tracing/current_tracer16 # echo function > /sys/kernel/tracing/current_tracer
17 $ cat /sys/kernel/debug/tracing/trace_pipe > ~/raw_trace_func17 $ cat /sys/kernel/tracing/trace_pipe > ~/raw_trace_func
18 Wait some times but not too much, the script is a bit slow.18 Wait some times but not too much, the script is a bit slow.
19 Break the pipe (Ctrl + Z)19 Break the pipe (Ctrl + Z)
20 $ scripts/tracing/draw_functrace.py < ~/raw_trace_func > draw_functrace20 $ scripts/tracing/draw_functrace.py < ~/raw_trace_func > draw_functrace
tools/lib/api/fs/tracing_path.c+2−2
@@ -14,8 +14,8 @@ · 13 unmodified lines
14#include "tracing_path.h"14#include "tracing_path.h"
15 15
16static char tracing_mnt[PATH_MAX] = "/sys/kernel/debug";16static char tracing_mnt[PATH_MAX] = "/sys/kernel/debug";
17static char tracing_path[PATH_MAX] = "/sys/kernel/debug/tracing";17static char tracing_path[PATH_MAX] = "/sys/kernel/tracing";
18static char tracing_events_path[PATH_MAX] = "/sys/kernel/debug/tracing/events";18static char tracing_events_path[PATH_MAX] = "/sys/kernel/tracing/events";
19 19
20static void __tracing_path_set(const char *tracing, const char *mountpoint)20static void __tracing_path_set(const char *tracing, const char *mountpoint)
21{21{
tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc+58−0
@@ -0,0 +1,58 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3# description: event filter function - test event filtering on functions
4# requires: set_event events/kmem/kmem_cache_free/filter
5# flags: instance
6
7fail() { #msg
8 echo $1
9 exit_fail
10}
11
12echo "Test event filter function name"
13echo 0 > tracing_on
14echo 0 > events/enable
15echo > trace
16echo 'call_site.function == exit_mmap' > events/kmem/kmem_cache_free/filter
17echo 1 > events/kmem/kmem_cache_free/enable
18echo 1 > tracing_on
19ls > /dev/null
20echo 0 > events/kmem/kmem_cache_free/enable
21
22hitcnt=`grep kmem_cache_free trace| grep exit_mmap | wc -l`
23misscnt=`grep kmem_cache_free trace| grep -v exit_mmap | wc -l`
24
25if [ $hitcnt -eq 0 ]; then
26 exit_fail
27fi
28
29if [ $misscnt -gt 0 ]; then
30 exit_fail
31fi
32
33address=`grep ' exit_mmap$' /proc/kallsyms | cut -d' ' -f1`
34
35echo "Test event filter function address"
36echo 0 > tracing_on
37echo 0 > events/enable
38echo > trace
39echo "call_site.function == 0x$address" > events/kmem/kmem_cache_free/filter
40echo 1 > events/kmem/kmem_cache_free/enable
41echo 1 > tracing_on
42sleep 1
43echo 0 > events/kmem/kmem_cache_free/enable
44
45hitcnt=`grep kmem_cache_free trace| grep exit_mmap | wc -l`
46misscnt=`grep kmem_cache_free trace| grep -v exit_mmap | wc -l`
47
48if [ $hitcnt -eq 0 ]; then
49 exit_fail
50fi
51
52if [ $misscnt -gt 0 ]; then
53 exit_fail
54fi
55
56reset_events_filter
57
58exit 0
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-stack.tc+24−0
@@ -0,0 +1,24 @@
1#!/bin/sh
2# SPDX-License-Identifier: GPL-2.0
3# description: event trigger - test inter-event histogram trigger trace action with dynamic string param
4# requires: set_event synthetic_events events/sched/sched_process_exec/hist "long[]' >> synthetic_events":README
5
6fail() { #msg
7 echo $1
8 exit_fail
9}
10
11echo "Test create synthetic event with stack"
12
13
14echo 's:wake_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events
15echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace if prev_state == 1||prev_state == 2' >> events/sched/sched_switch/trigger
16echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(wake_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger
17echo 1 > events/synthetic/wake_lat/enable
18sleep 1
19
20if ! grep -q "=>.*sched" trace; then
21 fail "Failed to create synthetic event with stack"
22fi
23
24exit 0
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc+6−0
@@ -70,6 +70,12 @@ grep "myevent[[:space:]]unsigned long var" synthetic_events · 69 unmodified lines
70echo "myevent char var[10]" > synthetic_events70echo "myevent char var[10]" > synthetic_events
71grep "myevent[[:space:]]char\[10\] var" synthetic_events71grep "myevent[[:space:]]char\[10\] var" synthetic_events
72 72
73if grep -q 'long\[\]' README; then
74 # test stacktrace type
75 echo "myevent unsigned long[] var" > synthetic_events
76 grep "myevent[[:space:]]unsigned long\[\] var" synthetic_events
77fi
78
73do_reset79do_reset
74 80
75exit 081exit 0
tools/tracing/latency/latency-collector.c+1−1
@@ -1584,7 +1584,7 @@ static void *do_printloop(void *arg) · 1583 unmodified lines
1584 /*1584 /*
1585 * Toss a coin to decide if we want to sleep before printing1585 * Toss a coin to decide if we want to sleep before printing
1586 * out the backtrace. The reason for this is that opening1586 * out the backtrace. The reason for this is that opening
1587 * /sys/kernel/debug/tracing/trace will cause a blackout of1587 * /sys/kernel/tracing/trace will cause a blackout of
1588 * hundreds of ms, where no latencies will be noted by the1588 * hundreds of ms, where no latencies will be noted by the
1589 * latency tracer. Thus by randomly sleeping we try to avoid1589 * latency tracer. Thus by randomly sleeping we try to avoid
1590 * missing traces systematically due to this. With this option1590 * missing traces systematically due to this. With this option