diff options
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r-- | tools/perf/builtin-trace.c | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 6ac51925ea42..2ab1b8e05ad3 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -55,6 +55,7 @@ #include "util/thread_map.h" #include "util/stat.h" #include "util/tool.h" +#include "util/trace.h" #include "util/util.h" #include "trace/beauty/beauty.h" #include "trace-event.h" @@ -141,12 +142,6 @@ struct syscall_fmt { bool hexret; }; -enum summary_mode { - SUMMARY__NONE = 0, - SUMMARY__BY_TOTAL, - SUMMARY__BY_THREAD, -}; - struct trace { struct perf_tool tool; struct { @@ -205,7 +200,7 @@ struct trace { } stats; unsigned int max_stack; unsigned int min_stack; - enum summary_mode summary_mode; + enum trace_summary_mode summary_mode; int raw_augmented_syscalls_args_size; bool raw_augmented_syscalls; bool fd_path_disabled; @@ -234,6 +229,7 @@ struct trace { bool force; bool vfs_getname; bool force_btf; + bool summary_bpf; int trace_pgfaults; char *perfconfig_events; struct { @@ -1352,7 +1348,7 @@ static const struct syscall_fmt syscall_fmts[] = { .arg = { [0] = { .scnprintf = SCA_FDAT, /* olddirfd */ }, [2] = { .scnprintf = SCA_FDAT, /* newdirfd */ }, [4] = { .scnprintf = SCA_RENAMEAT2_FLAGS, /* flags */ }, }, }, - { .name = "rseq", .errpid = true, + { .name = "rseq", .arg = { [0] = { .from_user = true /* rseq */, }, }, }, { .name = "rt_sigaction", .arg = { [0] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, @@ -1376,7 +1372,7 @@ static const struct syscall_fmt syscall_fmts[] = { { .name = "sendto", .arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, [4] = SCA_SOCKADDR_FROM_USER(addr), }, }, - { .name = "set_robust_list", .errpid = true, + { .name = "set_robust_list", .arg = { [0] = { .from_user = true /* head */, }, }, }, { .name = "set_tid_address", .errpid = true, }, { .name = "setitimer", @@ -1657,7 +1653,7 @@ static const size_t trace__entry_str_size = 2048; static void thread_trace__free_files(struct thread_trace *ttrace) { - for (int i = 0; i < ttrace->files.max; ++i) { + for (int i = 0; i <= ttrace->files.max; ++i) { struct file *file = ttrace->files.table + i; zfree(&file->pathname); } @@ -1703,6 +1699,7 @@ static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pat if (file != NULL) { struct stat st; + if (stat(pathname, &st) == 0) file->dev_maj = major(st.st_rdev); file->pathname = strdup(pathname); @@ -2614,6 +2611,9 @@ static void thread__update_stats(struct thread *thread, struct thread_trace *ttr struct syscall_stats *stats = NULL; u64 duration = 0; + if (trace->summary_bpf) + return; + if (trace->summary_mode == SUMMARY__BY_TOTAL) syscall_stats = trace->syscall_stats; @@ -2842,7 +2842,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel, e_machine = thread__e_machine(thread, trace->host); sc = trace__syscall_info(trace, evsel, e_machine, id); if (sc == NULL) - return -1; + goto out_put; ttrace = thread__trace(thread, trace); /* * We need to get ttrace just to make sure it is there when syscall__scnprintf_args() @@ -3005,8 +3005,8 @@ errno_print: { else if (sc->fmt->errpid) { struct thread *child = machine__find_thread(trace->host, ret, ret); + fprintf(trace->output, "%ld", ret); if (child != NULL) { - fprintf(trace->output, "%ld", ret); if (thread__comm_set(child)) fprintf(trace->output, " (%s)", thread__comm_str(child)); thread__put(child); @@ -4128,10 +4128,13 @@ static int trace__set_filter_loop_pids(struct trace *trace) if (!strcmp(thread__comm_str(parent), "sshd") || strstarts(thread__comm_str(parent), "gnome-terminal")) { pids[nr++] = thread__tid(parent); + thread__put(parent); break; } + thread__put(thread); thread = parent; } + thread__put(thread); err = evlist__append_tp_filter_pids(trace->evlist, nr, pids); if (!err && trace->filter_pids.map) @@ -4377,6 +4380,14 @@ static int trace__run(struct trace *trace, int argc, const char **argv) trace->live = true; + if (trace->summary_bpf) { + if (trace_prepare_bpf_summary(trace->summary_mode) < 0) + goto out_delete_evlist; + + if (trace->summary_only) + goto create_maps; + } + if (!trace->raw_augmented_syscalls) { if (trace->trace_syscalls && trace__add_syscall_newtp(trace)) goto out_error_raw_syscalls; @@ -4435,6 +4446,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) if (trace->cgroup) evlist__set_default_cgroup(trace->evlist, trace->cgroup); +create_maps: err = evlist__create_maps(evlist, &trace->opts.target); if (err < 0) { fprintf(trace->output, "Problems parsing the target to trace, check your options!\n"); @@ -4447,7 +4459,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_delete_evlist; } - if (trace->summary_mode == SUMMARY__BY_TOTAL) { + if (trace->summary_mode == SUMMARY__BY_TOTAL && !trace->summary_bpf) { trace->syscall_stats = alloc_syscall_stats(); if (trace->syscall_stats == NULL) goto out_delete_evlist; @@ -4535,9 +4547,11 @@ static int trace__run(struct trace *trace, int argc, const char **argv) if (err < 0) goto out_error_apply_filters; - err = evlist__mmap(evlist, trace->opts.mmap_pages); - if (err < 0) - goto out_error_mmap; + if (!trace->summary_only || !trace->summary_bpf) { + err = evlist__mmap(evlist, trace->opts.mmap_pages); + if (err < 0) + goto out_error_mmap; + } if (!target__none(&trace->opts.target) && !trace->opts.target.initial_delay) evlist__enable(evlist); @@ -4550,6 +4564,9 @@ static int trace__run(struct trace *trace, int argc, const char **argv) evlist__enable(evlist); } + if (trace->summary_bpf) + trace_start_bpf_summary(); + trace->multiple_threads = perf_thread_map__pid(evlist->core.threads, 0) == -1 || perf_thread_map__nr(evlist->core.threads) > 1 || evlist__first(evlist)->core.attr.inherit; @@ -4617,12 +4634,17 @@ out_disable: evlist__disable(evlist); + if (trace->summary_bpf) + trace_end_bpf_summary(); + if (trace->sort_events) ordered_events__flush(&trace->oe.data, OE_FLUSH__FINAL); if (!err) { if (trace->summary) { - if (trace->summary_mode == SUMMARY__BY_TOTAL) + if (trace->summary_bpf) + trace_print_bpf_summary(trace->output); + else if (trace->summary_mode == SUMMARY__BY_TOTAL) trace__fprintf_total_summary(trace, trace->output); else trace__fprintf_thread_summary(trace, trace->output); @@ -4638,6 +4660,7 @@ out_disable: } out_delete_evlist: + trace_cleanup_bpf_summary(); delete_syscall_stats(trace->syscall_stats); trace__symbols__exit(trace); evlist__free_syscall_tp_fields(evlist); @@ -5279,6 +5302,8 @@ static int trace__parse_summary_mode(const struct option *opt, const char *str, trace->summary_mode = SUMMARY__BY_THREAD; } else if (!strcmp(str, "total")) { trace->summary_mode = SUMMARY__BY_TOTAL; + } else if (!strcmp(str, "cgroup")) { + trace->summary_mode = SUMMARY__BY_CGROUP; } else { pr_err("Unknown summary mode: %s\n", str); return -1; @@ -5438,7 +5463,7 @@ int cmd_trace(int argc, const char **argv) OPT_BOOLEAN(0, "errno-summary", &trace.errno_summary, "Show errno stats per syscall, use with -s or -S"), OPT_CALLBACK(0, "summary-mode", &trace, "mode", - "How to show summary: select thread (default) or total", + "How to show summary: select thread (default), total or cgroup", trace__parse_summary_mode), OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min", "Trace pagefaults", parse_pagefaults, "maj"), @@ -5473,6 +5498,7 @@ int cmd_trace(int argc, const char **argv) "start"), OPT_BOOLEAN(0, "force-btf", &trace.force_btf, "Prefer btf_dump general pretty printer" "to customized ones"), + OPT_BOOLEAN(0, "bpf-summary", &trace.summary_bpf, "Summary syscall stats in BPF"), OPTS_EVSWITCH(&trace.evswitch), OPT_END() }; @@ -5564,6 +5590,16 @@ int cmd_trace(int argc, const char **argv) goto skip_augmentation; } + if (trace.summary_bpf) { + if (!trace.opts.target.system_wide) { + /* TODO: Add filters in the BPF to support other targets. */ + pr_err("Error: --bpf-summary only works for system-wide mode.\n"); + goto out; + } + if (trace.summary_only) + goto skip_augmentation; + } + trace.skel = augmented_raw_syscalls_bpf__open(); if (!trace.skel) { pr_debug("Failed to open augmented syscalls BPF skeleton"); @@ -5741,6 +5777,12 @@ init_augmented_syscall_tp: symbol_conf.keep_exited_threads = true; if (trace.summary_mode == SUMMARY__NONE) trace.summary_mode = SUMMARY__BY_THREAD; + + if (!trace.summary_bpf && trace.summary_mode == SUMMARY__BY_CGROUP) { + pr_err("Error: --summary-mode=cgroup only works with --bpf-summary\n"); + err = -EINVAL; + goto out; + } } if (output_name != NULL) { |