19 #include <subcmd/parse-options.h> 20 #include <api/fs/tracing_path.h> 28 #define DEFAULT_TRACER "function_graph" 42 struct list_head list;
61 siginfo_t *info __maybe_unused,
62 void *ucontext __maybe_unused)
72 ssize_t
size = strlen(val);
77 file = get_tracing_file(name);
79 pr_debug(
"cannot get tracing file: %s\n", name);
88 fd = open(file, flags);
90 pr_debug(
"cannot open tracing file: %s: %s\n",
91 name, str_error_r(errno, errbuf,
sizeof(errbuf)));
99 val_copy = strdup(val);
102 val_copy[
size] =
'\n';
104 if (write(fd, val_copy, size + 1) == size + 1)
107 pr_debug(
"write '%s' to tracing/%s failed: %s\n",
108 val, name, str_error_r(errno, errbuf,
sizeof(errbuf)));
114 put_tracing_file(file);
161 scnprintf(buf,
sizeof(buf),
"%d",
177 mask_size = (last_cpu + 3) / 4 + 1;
178 mask_size += last_cpu / 32;
180 cpumask =
malloc(mask_size);
181 if (cpumask == NULL) {
182 pr_debug(
"failed to allocate cpu mask\n");
218 list_for_each_entry(pos, funcs,
list) {
268 snprintf(buf,
sizeof(buf),
"%d", ftrace->
graph_depth);
281 struct pollfd pollfd = {
285 if (geteuid() != 0) {
286 pr_err(
"ftrace only works for root!\n");
296 pr_err(
"failed to reset ftrace\n");
305 &ftrace->
target, argv,
false,
311 pr_err(
"failed to set ftrace pid\n");
316 pr_err(
"failed to set tracing cpumask\n");
321 pr_err(
"failed to set tracing filters\n");
326 pr_err(
"failed to set graph depth\n");
331 pr_err(
"failed to set current_tracer to %s\n", ftrace->
tracer);
337 trace_file = get_tracing_file(
"trace_pipe");
339 pr_err(
"failed to open trace_pipe\n");
343 trace_fd = open(trace_file, O_RDONLY);
345 put_tracing_file(trace_file);
348 pr_err(
"failed to open trace_pipe\n");
352 fcntl(trace_fd, F_SETFL, O_NONBLOCK);
353 pollfd.fd = trace_fd;
356 pr_err(
"can't enable tracing\n");
363 if (poll(&pollfd, 1, -1) < 0)
366 if (pollfd.revents & POLLIN) {
367 int n = read(trace_fd, buf,
sizeof(buf));
370 if (fwrite(buf, n, 1, stdout) != 1)
379 int n = read(trace_fd, buf,
sizeof(buf));
382 if (fwrite(buf, n, 1, stdout) != 1)
391 return done ? 0 : -1;
398 if (!strstarts(var,
"ftrace."))
401 if (strcmp(var,
"ftrace.tracer"))
404 if (!strcmp(value,
"function_graph") ||
405 !strcmp(value,
"function")) {
410 pr_err(
"Please select \"function_graph\" (default) or \"function\"\n");
415 int unset __maybe_unused)
417 struct list_head *head = opt->value;
420 entry =
malloc(
sizeof(*entry) + strlen(str) + 1);
424 strcpy(entry->
name, str);
425 list_add_tail(&entry->
list, head);
434 list_for_each_entry_safe(pos, tmp, head,
list) {
435 list_del(&pos->
list);
445 .target = { .uid = UINT_MAX, },
447 const char *
const ftrace_usage[] = {
448 "perf ftrace [<options>] [<command>]",
449 "perf ftrace [<options>] -- <command> [<options>]",
452 const struct option ftrace_options[] = {
453 OPT_STRING(
't',
"tracer", &ftrace.
tracer,
"tracer",
454 "tracer to use: function_graph(default) or function"),
455 OPT_STRING(
'p',
"pid", &ftrace.
target.
pid,
"pid",
456 "trace on existing process id"),
457 OPT_INCR(
'v',
"verbose", &
verbose,
460 "system-wide collection from all CPUs"),
462 "list of cpus to monitor"),
463 OPT_CALLBACK(
'T',
"trace-funcs", &ftrace.
filters,
"func",
465 OPT_CALLBACK(
'N',
"notrace-funcs", &ftrace.
notrace,
"func",
467 OPT_CALLBACK(
'G',
"graph-funcs", &ftrace.
graph_funcs,
"func",
469 OPT_CALLBACK(
'g',
"nograph-funcs", &ftrace.
nograph_funcs,
"func",
471 OPT_INTEGER(
'D',
"graph-depth", &ftrace.
graph_depth,
472 "Max depth for function graph tracer"),
476 INIT_LIST_HEAD(&ftrace.
filters);
477 INIT_LIST_HEAD(&ftrace.
notrace);
485 argc = parse_options(argc, argv, ftrace_options, ftrace_usage,
486 PARSE_OPT_STOP_AT_NON_OPTION);
488 usage_with_options(ftrace_usage, ftrace_options);
496 goto out_delete_filters;
500 if (ftrace.
evlist == NULL) {
502 goto out_delete_filters;
507 goto out_delete_evlist;
static int parse_filter_func(const struct option *opt, const char *str, int unset __maybe_unused)
int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, const char *argv[], bool pipe_output, void(*exec_error)(int signo, siginfo_t *info, void *ucontext))
int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
enum target_errno target__validate(struct target *target)
static int set_tracing_cpu(struct perf_ftrace *ftrace)
static void ftrace__workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info __maybe_unused, void *ucontext __maybe_unused)
int cmd_ftrace(int argc, const char **argv)
void perf_evlist__delete(struct perf_evlist *evlist)
struct list_head graph_funcs
size_t cpu_map__snprint_mask(struct cpu_map *map, char *buf, size_t size)
static int set_tracing_depth(struct perf_ftrace *ftrace)
int perf_evlist__start_workload(struct perf_evlist *evlist)
struct thread_map * threads
static bool target__none(struct target *target)
static int perf_ftrace_config(const char *var, const char *value, void *cb)
int target__strerror(struct target *target, int errnum, char *buf, size_t buflen)
void cpu_map__put(struct cpu_map *map)
static size_t mask_size(struct cpu_map *map, int *max)
#define pr_debug(fmt,...)
static int write_tracing_file(const char *name, const char *val)
static int __write_tracing_file(const char *name, const char *val, bool append)
static bool target__has_cpu(struct target *target)
static int entry(u64 ip, struct unwind_info *ui)
int cpu_map__cpu(struct cpu_map *cpus, int idx)
static int str(yyscan_t scanner, int token)
struct list_head nograph_funcs
static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
struct thread_map_data map[]
static int set_tracing_pid(struct perf_ftrace *ftrace)
static void reset_tracing_filters(void)
static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
static int set_tracing_filters(struct perf_ftrace *ftrace)
static int set_tracing_cpumask(struct cpu_map *cpumap)
static int thread_map__nr(struct thread_map *threads)
static int reset_tracing_cpu(void)
struct perf_evlist * evlist
static int append_tracing_file(const char *name, const char *val)
int perf_config(config_fn_t fn, void *data)
static void delete_filter_func(struct list_head *head)
static int __set_tracing_filter(const char *filter_file, struct list_head *funcs)
static void sig_handler(int sig __maybe_unused)
struct cpu_map * cpu_map__new(const char *cpu_list)
struct perf_evlist * perf_evlist__new(void)