mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
Allow a stacktrace from one event to be displayed by the end event of a
synthetic event. This is very useful when looking for the longest latency
of a sleep or something blocked on I/O.
# cd /sys/kernel/tracing/
# echo 's:block_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events
# echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace if prev_state == 1||prev_state == 2' > events/sched/sched_switch/trigger
# 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
The above creates a "block_lat" synthetic event that take the stacktrace of
when a task schedules out in either the interruptible or uninterruptible
states, and on a new per process max $delta (the time it was scheduled
out), will print the process id and the stacktrace.
# echo 1 > events/synthetic/block_lat/enable
# cat trace
# TASK-PID CPU# ||||| TIMESTAMP FUNCTION
# | | | ||||| | |
kworker/u16:0-767 [006] d..4. 560.645045: block_lat: pid=767 delta=66 stack=STACK:
=> __schedule
=> schedule
=> pipe_read
=> vfs_read
=> ksys_read
=> do_syscall_64
=> 0x966000aa
<idle>-0 [003] d..4. 561.132117: block_lat: pid=0 delta=413787 stack=STACK:
=> __schedule
=> schedule
=> schedule_hrtimeout_range_clock
=> do_sys_poll
=> __x64_sys_poll
=> do_syscall_64
=> 0x966000aa
<...>-153 [006] d..4. 562.068407: block_lat: pid=153 delta=54 stack=STACK:
=> __schedule
=> schedule
=> io_schedule
=> rq_qos_wait
=> wbt_wait
=> __rq_qos_throttle
=> blk_mq_submit_bio
=> submit_bio_noacct_nocheck
=> ext4_bio_write_page
=> mpage_submit_page
=> mpage_process_page_bufs
=> mpage_prepare_extent_to_map
=> ext4_do_writepages
=> ext4_writepages
=> do_writepages
=> __writeback_single_inode
Link: https://lkml.kernel.org/r/20230117152236.010941267@goodmis.org
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Tom Zanussi <zanussi@kernel.org>
Cc: Ross Zwisler <zwisler@google.com>
Cc: Ching-lin Yu <chinglinyu@google.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
42 lines
892 B
C
42 lines
892 B
C
// SPDX-License-Identifier: GPL-2.0
|
|
#ifndef __TRACE_SYNTH_H
|
|
#define __TRACE_SYNTH_H
|
|
|
|
#include "trace_dynevent.h"
|
|
|
|
#define SYNTH_SYSTEM "synthetic"
|
|
#define SYNTH_FIELDS_MAX 64
|
|
|
|
#define STR_VAR_LEN_MAX MAX_FILTER_STR_VAL /* must be multiple of sizeof(u64) */
|
|
|
|
struct synth_field {
|
|
char *type;
|
|
char *name;
|
|
size_t size;
|
|
unsigned int offset;
|
|
unsigned int field_pos;
|
|
bool is_signed;
|
|
bool is_string;
|
|
bool is_dynamic;
|
|
bool is_stack;
|
|
};
|
|
|
|
struct synth_event {
|
|
struct dyn_event devent;
|
|
int ref;
|
|
char *name;
|
|
struct synth_field **fields;
|
|
unsigned int n_fields;
|
|
struct synth_field **dynamic_fields;
|
|
unsigned int n_dynamic_fields;
|
|
unsigned int n_u64;
|
|
struct trace_event_class class;
|
|
struct trace_event_call call;
|
|
struct tracepoint *tp;
|
|
struct module *mod;
|
|
};
|
|
|
|
extern struct synth_event *find_synth_event(const char *name);
|
|
|
|
#endif /* __TRACE_SYNTH_H */
|