From: Ian Rogers Date: Wed, 2 Apr 2025 20:15:47 +0000 (-0700) Subject: perf evlist: Refactor evlist__scnprintf_evsels() X-Git-Tag: v6.16-rc1~57^2~87 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=f0f245eaa2bca3595a0e775e9abdf7de909c0450;p=linux-block.git perf evlist: Refactor evlist__scnprintf_evsels() Switch output to using a strbuf so the storage can be resized. Add a maximum size argument to avoid too much output that may happen for uncore events. Rename as scnprintf is no longer used. Committer testing: With the patch applied: root@number:~# perf probe -x ~/bin/perf evlist__format_evsels Added new event: probe_perf:evlist_format_evsels (on evlist__format_evsels in /home/acme/bin/perf) You can now use it in all perf tools, such as: perf record -e probe_perf:evlist_format_evsels -aR sleep 1 root@number:~# perf probe -l probe_perf:evlist_format_evsels (on evlist__format_evsels@util/evlist.c in /home/acme/bin/perf) root@number:~# perf trace -e probe_perf:*/max-stack=10/ perf record -e cycles,instructions,cache-misses /tmp/bla Failed to collect 'cycles,instructions,cache-misses' for the '/tmp/bla' workload: Permission denied 0.000 perf/3893011 probe_perf:evlist_format_evsels(__probe_ip: 6183397) evlist__format_evsels (/home/acme/bin/perf) __cmd_record (/home/acme/bin/perf) cmd_record (/home/acme/bin/perf) run_builtin (/home/acme/bin/perf) handle_internal_command (/home/acme/bin/perf) run_argv (/home/acme/bin/perf) main (/home/acme/bin/perf) __libc_start_call_main (/usr/lib64/libc.so.6) __libc_start_main@@GLIBC_2.34 (/usr/lib64/libc.so.6) _start (/home/acme/bin/perf) root@number:~# Reviewed-by: Kan Liang Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Dominique Martinet Cc: Dr. David Alan Gilbert Cc: Howard Chu Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Levi Yun Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Weilin Wang Link: https://lore.kernel.org/r/20250402201549.4090305-4-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8898357325cf..52cebacc19a7 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -51,6 +51,7 @@ #include "util/clockid.h" #include "util/off_cpu.h" #include "util/bpf-filter.h" +#include "util/strbuf.h" #include "asm/bug.h" #include "perf.h" #include "cputopo.h" @@ -2791,13 +2792,15 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) record__auxtrace_snapshot_exit(rec); if (forks && workload_exec_errno) { - char msg[STRERR_BUFSIZE], strevsels[2048]; + char msg[STRERR_BUFSIZE]; const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); + struct strbuf sb = STRBUF_INIT; - evlist__scnprintf_evsels(rec->evlist, sizeof(strevsels), strevsels); + evlist__format_evsels(rec->evlist, &sb, 2048); pr_err("Failed to collect '%s' for the '%s' workload: %s\n", - strevsels, argv[0], emsg); + sb.buf, argv[0], emsg); + strbuf_release(&sb); err = -1; goto out_child; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 0a21da4f990f..140ac3ba8c11 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -35,6 +35,7 @@ #include "util/util.h" #include "util/env.h" #include "util/intel-tpebs.h" +#include "util/strbuf.h" #include #include #include @@ -2467,23 +2468,25 @@ struct evsel *evlist__find_evsel(struct evlist *evlist, int idx) return NULL; } -int evlist__scnprintf_evsels(struct evlist *evlist, size_t size, char *bf) +void evlist__format_evsels(struct evlist *evlist, struct strbuf *sb, size_t max_length) { struct evsel *evsel; - int printed = 0; + bool first = true; evlist__for_each_entry(evlist, evsel) { if (evsel__is_dummy_event(evsel)) continue; - if (size > (strlen(evsel__name(evsel)) + (printed ? 2 : 1))) { - printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "," : "", evsel__name(evsel)); - } else { - printed += scnprintf(bf + printed, size - printed, "%s...", printed ? "," : ""); - break; + + if (!first) + strbuf_addch(sb, ','); + + if (sb->len > max_length) { + strbuf_addstr(sb, "..."); + return; } + strbuf_addstr(sb, evsel__name(evsel)); + first = false; } - - return printed; } void evlist__check_mem_load_aux(struct evlist *evlist) diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index edcbf1c10e92..21f6bff319fd 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -20,6 +20,7 @@ struct pollfd; struct thread_map; struct perf_cpu_map; struct record_opts; +struct strbuf; struct target; /* @@ -430,7 +431,7 @@ int event_enable_timer__process(struct event_enable_timer *eet); struct evsel *evlist__find_evsel(struct evlist *evlist, int idx); -int evlist__scnprintf_evsels(struct evlist *evlist, size_t size, char *bf); +void evlist__format_evsels(struct evlist *evlist, struct strbuf *sb, size_t max_length); void evlist__check_mem_load_aux(struct evlist *evlist); void evlist__warn_user_requested_cpus(struct evlist *evlist, const char *cpu_list); void evlist__uniquify_name(struct evlist *evlist);