Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S936790AbdDZUbK (ORCPT ); Wed, 26 Apr 2017 16:31:10 -0400 Received: from mx.kolabnow.com ([95.128.36.1]:25794 "EHLO mx-out03.mykolab.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753325AbdDZUbG (ORCPT ); Wed, 26 Apr 2017 16:31:06 -0400 X-Spam-Flag: NO X-Spam-Score: -2.9 From: Federico Vaga To: Steven Rostedt Cc: LKML , Federico Vaga Subject: [PATCH 1/2] trace-cmd: uniform command implementation Date: Wed, 26 Apr 2017 22:30:27 +0200 Message-Id: <20170426203028.13900-2-federico.vaga@vaga.pv.it> In-Reply-To: <20170426203028.13900-1-federico.vaga@vaga.pv.it> References: <20170426203028.13900-1-federico.vaga@vaga.pv.it> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 33199 Lines: 1474 Most of the commands have the implementation in a dedicated file. Those commands without a dedicated file are implemented in the `main()` function. This patch uniform the code by moving the commands implemented in the `main()` function to dedicated files. Signed-off-by: Federico Vaga --- Makefile | 3 +- trace-check-events.c | 66 ++++++ trace-cmd.c | 631 +-------------------------------------------------- trace-list.c | 486 +++++++++++++++++++++++++++++++++++++++ trace-local.h | 7 + trace-show.c | 176 ++++++++++++++ 6 files changed, 741 insertions(+), 628 deletions(-) create mode 100644 trace-check-events.c create mode 100644 trace-list.c create mode 100644 trace-show.c diff --git a/Makefile b/Makefile index a3c6bfa..2be2754 100644 --- a/Makefile +++ b/Makefile @@ -341,7 +341,8 @@ TRACE_GUI_OBJS = trace-filter.o trace-compat.o trace-filter-hash.o trace-dialog. trace-xml.o TRACE_CMD_OBJS = trace-cmd.o trace-record.o trace-read.o trace-split.o trace-listen.o \ trace-stack.o trace-hist.o trace-mem.o trace-snapshot.o trace-stat.o \ - trace-hash.o trace-profile.o trace-stream.o trace-record.o trace-restore.o + trace-hash.o trace-profile.o trace-stream.o trace-record.o trace-restore.o \ + trace-check-events.o trace-show.o trace-list.o TRACE_VIEW_OBJS = trace-view.o trace-view-store.o TRACE_GRAPH_OBJS = trace-graph.o trace-plot.o trace-plot-cpu.o trace-plot-task.o TRACE_VIEW_MAIN_OBJS = trace-view-main.o $(TRACE_VIEW_OBJS) $(TRACE_GUI_OBJS) diff --git a/trace-check-events.c b/trace-check-events.c new file mode 100644 index 0000000..c5a0127 --- /dev/null +++ b/trace-check-events.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "trace-local.h" + +void trace_check_events(int argc, char **argv) +{ + const char *tracing; + int ret, c; + struct pevent *pevent = NULL; + struct plugin_list *list = NULL; + + while ((c = getopt(argc-1, argv+1, "+hN")) >= 0) { + switch (c) { + case 'h': + default: + usage(argv); + break; + case 'N': + tracecmd_disable_plugins = 1; + break; + } + } + tracing = tracecmd_get_tracing_dir(); + + if (!tracing) { + printf("Can not find or mount tracing directory!\n" + "Either tracing is not configured for this " + "kernel\n" + "or you do not have the proper permissions to " + "mount the directory"); + exit(EINVAL); + } + + pevent = pevent_alloc(); + if (!pevent) + exit(EINVAL); + list = tracecmd_load_plugins(pevent); + ret = tracecmd_fill_local_events(tracing, pevent); + if (ret || pevent->parsing_failures) + ret = EINVAL; + tracecmd_unload_plugins(list, pevent); + pevent_free(pevent); + + return; +} diff --git a/trace-cmd.c b/trace-cmd.c index 6a023e8..39bcc06 100644 --- a/trace-cmd.c +++ b/trace-cmd.c @@ -75,346 +75,9 @@ void *malloc_or_die(unsigned int size) return data; } -static void dump_file_content(const char *path) -{ - char buf[BUFSIZ]; - ssize_t n; - FILE *fp; - - fp = fopen(path, "r"); - if (!fp) - die("reading %s", path); - - do { - n = fread(buf, 1, BUFSIZ, fp); - if (n > 0) - fwrite(buf, 1, n, stdout); - } while (n > 0); - fclose(fp); -} - -void show_file(const char *name) -{ - char *path; - - path = tracecmd_get_tracing_file(name); - dump_file_content(path); - tracecmd_put_tracing_file(path); -} - -typedef int (*process_file_func)(char *buf, int len); - -static void process_file_re(process_file_func func, - const char *name, const char *re) -{ - regex_t reg; - char *path; - char *buf = NULL; - char *str; - FILE *fp; - ssize_t n; - size_t l = strlen(re); - - /* Just in case :-p */ - if (!re || l == 0) { - show_file(name); - return; - } - - /* Handle the newline at end of names for the user */ - str = malloc(l + 3); - if (!str) - die("Failed to allocate reg ex %s", re); - strcpy(str, re); - if (re[l-1] == '$') - strcpy(&str[l-1], "\n*$"); - - if (regcomp(®, str, REG_ICASE|REG_NOSUB)) - die("invalid function regex '%s'", re); - - free(str); - - path = tracecmd_get_tracing_file(name); - fp = fopen(path, "r"); - if (!fp) - die("reading %s", path); - tracecmd_put_tracing_file(path); - - do { - n = getline(&buf, &l, fp); - if (n > 0 && regexec(®, buf, 0, NULL, 0) == 0) - func(buf, n); - } while (n > 0); - free(buf); - fclose(fp); - - regfree(®); -} - -static int show_file_write(char *buf, int len) -{ - return fwrite(buf, 1, len, stdout); -} - -static void show_file_re(const char *name, const char *re) -{ - process_file_re(show_file_write, name, re); -} - -static char *get_event_file(const char *type, char *buf, int len) -{ - char *system; - char *event; - char *path; - char *file; - - if (buf[len-1] == '\n') - buf[len-1] = '\0'; - - system = strtok(buf, ":"); - if (!system) - die("no system found in %s", buf); - - event = strtok(NULL, ":"); - if (!event) - die("no event found in %s\n", buf); - - path = tracecmd_get_tracing_file("events"); - file = malloc(strlen(path) + strlen(system) + strlen(event) + - strlen(type) + strlen("///") + 1); - if (!file) - die("Failed to allocate event file %s %s", system, event); - sprintf(file, "%s/%s/%s/%s", path, system, event, type); - tracecmd_put_tracing_file(path); - - return file; -} - -static int event_filter_write(char *buf, int len) -{ - char *file; - - if (buf[len-1] == '\n') - buf[len-1] = '\0'; - - printf("%s\n", buf); - - file = get_event_file("filter", buf, len); - dump_file_content(file); - free(file); - printf("\n"); - - return 0; -} - -static int event_trigger_write(char *buf, int len) -{ - char *file; - - if (buf[len-1] == '\n') - buf[len-1] = '\0'; - - printf("%s\n", buf); - - file = get_event_file("trigger", buf, len); - dump_file_content(file); - free(file); - printf("\n"); - - return 0; -} - -static int event_format_write(char *fbuf, int len) -{ - char *file = get_event_file("format", fbuf, len); - char *buf = NULL; - size_t l; - FILE *fp; - int n; - - /* The get_event_file() crops system in fbuf */ - printf("system: %s\n", fbuf); - - /* Don't print the print fmt, it's ugly */ - - fp = fopen(file, "r"); - if (!fp) - die("reading %s", file); - - do { - n = getline(&buf, &l, fp); - if (n > 0) { - if (strncmp(buf, "print fmt", 9) == 0) - break; - fwrite(buf, 1, n, stdout); - } - } while (n > 0); - fclose(fp); - free(buf); - free(file); - - return 0; -} - -static void show_event_filter_re(const char *re) -{ - process_file_re(event_filter_write, "available_events", re); -} - -static void show_event_trigger_re(const char *re) -{ - process_file_re(event_trigger_write, "available_events", re); -} - -static void show_event_format_re(const char *re) -{ - process_file_re(event_format_write, "available_events", re); -} - -void show_instance_file(struct buffer_instance *instance, const char *name) -{ - char *path; - - path = get_instance_file(instance, name); - dump_file_content(path); - tracecmd_put_tracing_file(path); -} - -enum { - SHOW_EVENT_FORMAT = 1 << 0, - SHOW_EVENT_FILTER = 1 << 1, - SHOW_EVENT_TRIGGER = 1 << 2, -}; - -static void show_events(const char *eventre, int flags) -{ - if (flags && !eventre) - die("When specifying event files, an event must be named"); - - if (eventre) { - if (flags & SHOW_EVENT_FORMAT) - show_event_format_re(eventre); - - else if (flags & SHOW_EVENT_FILTER) - show_event_filter_re(eventre); - - else if (flags & SHOW_EVENT_TRIGGER) - show_event_trigger_re(eventre); - else - show_file_re("available_events", eventre); - } else - show_file("available_events"); -} - -static void show_tracers(void) -{ - show_file("available_tracers"); -} - -static void show_options(void) -{ - show_file("trace_options"); -} - -static void show_clocks(void) -{ - show_file("trace_clock"); -} - -static void show_functions(const char *funcre) -{ - if (funcre) - show_file_re("available_filter_functions", funcre); - else - show_file("available_filter_functions"); -} - -static void show_buffers(void) -{ - struct dirent *dent; - DIR *dir; - char *path; - int printed = 0; - - path = tracecmd_get_tracing_file("instances"); - dir = opendir(path); - tracecmd_put_tracing_file(path); - if (!dir) - die("Can not read instance directory"); - - while ((dent = readdir(dir))) { - const char *name = dent->d_name; - - if (strcmp(name, ".") == 0 || - strcmp(name, "..") == 0) - continue; - - printf("%s\n", name); - printed = 1; - } - closedir(dir); - - if (!printed) - printf("No buffer instances defined\n"); -} - -static void show_plugins(void) -{ - struct pevent *pevent; - struct plugin_list *list; - struct trace_seq s; - - pevent = pevent_alloc(); - if (!pevent) - die("Can not allocate pevent\n"); - - trace_seq_init(&s); - - list = tracecmd_load_plugins(pevent); - trace_util_print_plugins(&s, " ", "\n", list); - trace_seq_do_printf(&s); - tracecmd_unload_plugins(list, pevent); - pevent_free(pevent); -} - -static void show_plugin_options(void) -{ - struct pevent *pevent; - struct plugin_list *list; - struct trace_seq s; - - tracecmd_ftrace_load_options(); - - pevent = pevent_alloc(); - if (!pevent) - die("Can not allocate pevent\n"); - - trace_seq_init(&s); - - list = tracecmd_load_plugins(pevent); - trace_util_print_plugin_options(&s); - trace_seq_do_printf(&s); - tracecmd_unload_plugins(list, pevent); - pevent_free(pevent); -} - -enum { - OPT_tracing_on = 255, - OPT_current_tracer = 254, - OPT_buffer_size_kb = 253, - OPT_buffer_total_size_kb = 252, - OPT_ftrace_filter = 251, - OPT_ftrace_notrace = 250, - OPT_ftrace_pid = 249, - OPT_graph_function = 248, - OPT_graph_notrace = 247, - OPT_cpumask = 246, -}; int main (int argc, char **argv) { - int c; - errno = 0; if (argc < 2) @@ -445,44 +108,8 @@ int main (int argc, char **argv) trace_stack(argc, argv); exit(0); } else if (strcmp(argv[1], "check-events") == 0) { - const char *tracing; - int ret; - struct pevent *pevent = NULL; - struct plugin_list *list = NULL; - - while ((c = getopt(argc-1, argv+1, "+hN")) >= 0) { - switch (c) { - case 'h': - default: - usage(argv); - break; - case 'N': - tracecmd_disable_plugins = 1; - break; - } - } - tracing = tracecmd_get_tracing_dir(); - - if (!tracing) { - printf("Can not find or mount tracing directory!\n" - "Either tracing is not configured for this " - "kernel\n" - "or you do not have the proper permissions to " - "mount the directory"); - exit(EINVAL); - } - - pevent = pevent_alloc(); - if (!pevent) - exit(EINVAL); - list = tracecmd_load_plugins(pevent); - ret = tracecmd_fill_local_events(tracing, pevent); - if (ret || pevent->parsing_failures) - ret = EINVAL; - tracecmd_unload_plugins(list, pevent); - pevent_free(pevent); - exit(ret); - + trace_check_events(argc, argv); + exit(0); } else if (strcmp(argv[1], "record") == 0 || strcmp(argv[1], "start") == 0 || strcmp(argv[1], "extract") == 0 || @@ -502,261 +129,11 @@ int main (int argc, char **argv) show_plugin_options(); exit(0); } else if (strcmp(argv[1], "show") == 0) { - const char *buffer = NULL; - const char *file = "trace"; - const char *cpu = NULL; - struct buffer_instance *instance = &top_instance; - char cpu_path[128]; - char *path; - int snap = 0; - int pipe = 0; - int show_name = 0; - int option_index = 0; - int stop = 0; - static struct option long_options[] = { - {"tracing_on", no_argument, NULL, OPT_tracing_on}, - {"current_tracer", no_argument, NULL, OPT_current_tracer}, - {"buffer_size", no_argument, NULL, OPT_buffer_size_kb}, - {"buffer_total_size", no_argument, NULL, OPT_buffer_total_size_kb}, - {"ftrace_filter", no_argument, NULL, OPT_ftrace_filter}, - {"ftrace_notrace", no_argument, NULL, OPT_ftrace_notrace}, - {"ftrace_pid", no_argument, NULL, OPT_ftrace_pid}, - {"graph_function", no_argument, NULL, OPT_graph_function}, - {"graph_notrace", no_argument, NULL, OPT_graph_notrace}, - {"cpumask", no_argument, NULL, OPT_cpumask}, - {"help", no_argument, NULL, '?'}, - {NULL, 0, NULL, 0} - }; - - while ((c = getopt_long(argc-1, argv+1, "B:c:fsp", - long_options, &option_index)) >= 0) { - switch (c) { - case 'h': - usage(argv); - break; - case 'B': - if (buffer) - die("Can only show one buffer at a time"); - buffer = optarg; - instance = create_instance(optarg); - if (!instance) - die("Failed to create instance"); - break; - case 'c': - if (cpu) - die("Can only show one CPU at a time"); - cpu = optarg; - break; - case 'f': - show_name = 1; - break; - case 's': - snap = 1; - if (pipe) - die("Can not have -s and -p together"); - break; - case 'p': - pipe = 1; - if (snap) - die("Can not have -s and -p together"); - break; - case OPT_tracing_on: - show_instance_file(instance, "tracing_on"); - stop = 1; - break; - case OPT_current_tracer: - show_instance_file(instance, "current_tracer"); - stop = 1; - break; - case OPT_buffer_size_kb: - show_instance_file(instance, "buffer_size_kb"); - stop = 1; - break; - case OPT_buffer_total_size_kb: - show_instance_file(instance, "buffer_total_size_kb"); - stop = 1; - break; - case OPT_ftrace_filter: - show_instance_file(instance, "set_ftrace_filter"); - stop = 1; - break; - case OPT_ftrace_notrace: - show_instance_file(instance, "set_ftrace_notrace"); - stop = 1; - break; - case OPT_ftrace_pid: - show_instance_file(instance, "set_ftrace_pid"); - stop = 1; - break; - case OPT_graph_function: - show_instance_file(instance, "set_graph_function"); - stop = 1; - break; - case OPT_graph_notrace: - show_instance_file(instance, "set_graph_notrace"); - stop = 1; - break; - case OPT_cpumask: - show_instance_file(instance, "tracing_cpumask"); - stop = 1; - break; - default: - usage(argv); - } - } - if (stop) - exit(0); - if (pipe) - file = "trace_pipe"; - else if (snap) - file = "snapshot"; - - if (cpu) { - snprintf(cpu_path, 128, "per_cpu/cpu%d/%s", atoi(cpu), file); - file = cpu_path; - } - - if (buffer) { - path = malloc(strlen(buffer) + strlen("instances//") + - strlen(file) + 1); - if (!path) - die("Failed to allocate instance path %s", file); - sprintf(path, "instances/%s/%s", buffer, file); - file = path; - } - - if (show_name) { - char *name; - name = tracecmd_get_tracing_file(file); - printf("%s\n", name); - tracecmd_put_tracing_file(name); - } - show_file(file); - if (buffer) - free(path); - + trace_show(argc, argv); exit(0); } else if (strcmp(argv[1], "list") == 0) { - int events = 0; - int tracer = 0; - int options = 0; - int funcs = 0; - int buffers = 0; - int clocks = 0; - int plug = 0; - int plug_op = 0; - int flags = 0; - int show_all = 1; - int i; - const char *arg; - const char *funcre = NULL; - const char *eventre = NULL; - - for (i = 2; i < argc; i++) { - arg = NULL; - if (argv[i][0] == '-') { - if (i < argc - 1) { - if (argv[i+1][0] != '-') - arg = argv[i+1]; - } - switch (argv[i][1]) { - case 'h': - usage(argv); - break; - case 'e': - events = 1; - eventre = arg; - show_all = 0; - break; - case 'B': - buffers = 1; - show_all = 0; - break; - case 'C': - clocks = 1; - show_all = 0; - break; - case 'F': - flags |= SHOW_EVENT_FORMAT; - break; - case 'R': - flags |= SHOW_EVENT_TRIGGER; - break; - case 'l': - flags |= SHOW_EVENT_FILTER; - break; - case 'p': - case 't': - tracer = 1; - show_all = 0; - break; - case 'P': - plug = 1; - show_all = 0; - break; - case 'O': - plug_op = 1; - show_all = 0; - break; - case 'o': - options = 1; - show_all = 0; - break; - case 'f': - funcs = 1; - funcre = arg; - show_all = 0; - break; - case '-': - if (strcmp(argv[i], "--debug") == 0) { - debug = true; - break; - } - fprintf(stderr, "list: invalid option -- '%s'\n", - argv[i]); - default: - fprintf(stderr, "list: invalid option -- '%c'\n", - argv[i][1]); - usage(argv); - } - } - } - - if (events) - show_events(eventre, flags); - - if (tracer) - show_tracers(); - - if (options) - show_options(); - - if (plug) - show_plugins(); - - if (plug_op) - show_plugin_options(); - - if (funcs) - show_functions(funcre); - - if (buffers) - show_buffers(); - - if (clocks) - show_clocks(); - - if (show_all) { - printf("events:\n"); - show_events(NULL, 0); - printf("\ntracers:\n"); - show_tracers(); - printf("\noptions:\n"); - show_options(); - } - + trace_list(argc, argv); exit(0); - } else if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "help") == 0) { usage(argv); diff --git a/trace-list.c b/trace-list.c new file mode 100644 index 0000000..3fdca34 --- /dev/null +++ b/trace-list.c @@ -0,0 +1,486 @@ +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include + +#include "trace-local.h" + + +static void dump_file_content(const char *path) +{ + char buf[BUFSIZ]; + ssize_t n; + FILE *fp; + + fp = fopen(path, "r"); + if (!fp) + die("reading %s", path); + + do { + n = fread(buf, 1, BUFSIZ, fp); + if (n > 0) + fwrite(buf, 1, n, stdout); + } while (n > 0); + fclose(fp); +} + + + +void show_instance_file(struct buffer_instance *instance, const char *name) +{ + char *path; + + path = get_instance_file(instance, name); + dump_file_content(path); + tracecmd_put_tracing_file(path); +} + +enum { + SHOW_EVENT_FORMAT = 1 << 0, + SHOW_EVENT_FILTER = 1 << 1, + SHOW_EVENT_TRIGGER = 1 << 2, +}; + + +void show_file(const char *name) +{ + char *path; + + path = tracecmd_get_tracing_file(name); + dump_file_content(path); + tracecmd_put_tracing_file(path); +} + +typedef int (*process_file_func)(char *buf, int len); + +static void process_file_re(process_file_func func, + const char *name, const char *re) +{ + regex_t reg; + char *path; + char *buf = NULL; + char *str; + FILE *fp; + ssize_t n; + size_t l = strlen(re); + + /* Just in case :-p */ + if (!re || l == 0) { + show_file(name); + return; + } + + /* Handle the newline at end of names for the user */ + str = malloc(l + 3); + if (!str) + die("Failed to allocate reg ex %s", re); + strcpy(str, re); + if (re[l-1] == '$') + strcpy(&str[l-1], "\n*$"); + + if (regcomp(®, str, REG_ICASE|REG_NOSUB)) + die("invalid function regex '%s'", re); + + free(str); + + path = tracecmd_get_tracing_file(name); + fp = fopen(path, "r"); + if (!fp) + die("reading %s", path); + tracecmd_put_tracing_file(path); + + do { + n = getline(&buf, &l, fp); + if (n > 0 && regexec(®, buf, 0, NULL, 0) == 0) + func(buf, n); + } while (n > 0); + free(buf); + fclose(fp); + + regfree(®); +} + +static int show_file_write(char *buf, int len) +{ + return fwrite(buf, 1, len, stdout); +} + +static void show_file_re(const char *name, const char *re) +{ + process_file_re(show_file_write, name, re); +} + +static char *get_event_file(const char *type, char *buf, int len) +{ + char *system; + char *event; + char *path; + char *file; + + if (buf[len-1] == '\n') + buf[len-1] = '\0'; + + system = strtok(buf, ":"); + if (!system) + die("no system found in %s", buf); + + event = strtok(NULL, ":"); + if (!event) + die("no event found in %s\n", buf); + + path = tracecmd_get_tracing_file("events"); + file = malloc(strlen(path) + strlen(system) + strlen(event) + + strlen(type) + strlen("///") + 1); + if (!file) + die("Failed to allocate event file %s %s", system, event); + sprintf(file, "%s/%s/%s/%s", path, system, event, type); + tracecmd_put_tracing_file(path); + + return file; +} + +static int event_filter_write(char *buf, int len) +{ + char *file; + + if (buf[len-1] == '\n') + buf[len-1] = '\0'; + + printf("%s\n", buf); + + file = get_event_file("filter", buf, len); + dump_file_content(file); + free(file); + printf("\n"); + + return 0; +} + +static int event_trigger_write(char *buf, int len) +{ + char *file; + + if (buf[len-1] == '\n') + buf[len-1] = '\0'; + + printf("%s\n", buf); + + file = get_event_file("trigger", buf, len); + dump_file_content(file); + free(file); + printf("\n"); + + return 0; +} + +static int event_format_write(char *fbuf, int len) +{ + char *file = get_event_file("format", fbuf, len); + char *buf = NULL; + size_t l; + FILE *fp; + int n; + + /* The get_event_file() crops system in fbuf */ + printf("system: %s\n", fbuf); + + /* Don't print the print fmt, it's ugly */ + + fp = fopen(file, "r"); + if (!fp) + die("reading %s", file); + + do { + n = getline(&buf, &l, fp); + if (n > 0) { + if (strncmp(buf, "print fmt", 9) == 0) + break; + fwrite(buf, 1, n, stdout); + } + } while (n > 0); + fclose(fp); + free(buf); + free(file); + + return 0; +} + + +static void show_event_filter_re(const char *re) +{ + process_file_re(event_filter_write, "available_events", re); +} + + +static void show_event_trigger_re(const char *re) +{ + process_file_re(event_trigger_write, "available_events", re); +} + + +static void show_event_format_re(const char *re) +{ + process_file_re(event_format_write, "available_events", re); +} + + +static void show_events(const char *eventre, int flags) +{ + if (flags && !eventre) + die("When specifying event files, an event must be named"); + + if (eventre) { + if (flags & SHOW_EVENT_FORMAT) + show_event_format_re(eventre); + + else if (flags & SHOW_EVENT_FILTER) + show_event_filter_re(eventre); + + else if (flags & SHOW_EVENT_TRIGGER) + show_event_trigger_re(eventre); + else + show_file_re("available_events", eventre); + } else + show_file("available_events"); +} + + +static void show_tracers(void) +{ + show_file("available_tracers"); +} + + +static void show_options(void) +{ + show_file("trace_options"); +} + + +static void show_clocks(void) +{ + show_file("trace_clock"); +} + + +static void show_functions(const char *funcre) +{ + if (funcre) + show_file_re("available_filter_functions", funcre); + else + show_file("available_filter_functions"); +} + + +static void show_buffers(void) +{ + struct dirent *dent; + DIR *dir; + char *path; + int printed = 0; + + path = tracecmd_get_tracing_file("instances"); + dir = opendir(path); + tracecmd_put_tracing_file(path); + if (!dir) + die("Can not read instance directory"); + + while ((dent = readdir(dir))) { + const char *name = dent->d_name; + + if (strcmp(name, ".") == 0 || + strcmp(name, "..") == 0) + continue; + + printf("%s\n", name); + printed = 1; + } + closedir(dir); + + if (!printed) + printf("No buffer instances defined\n"); +} + + +void show_plugin_options(void) +{ + struct pevent *pevent; + struct plugin_list *list; + struct trace_seq s; + + tracecmd_ftrace_load_options(); + + pevent = pevent_alloc(); + if (!pevent) + die("Can not allocate pevent\n"); + + trace_seq_init(&s); + + list = tracecmd_load_plugins(pevent); + trace_util_print_plugin_options(&s); + trace_seq_do_printf(&s); + tracecmd_unload_plugins(list, pevent); + pevent_free(pevent); +} + + +static void show_plugins(void) +{ + struct pevent *pevent; + struct plugin_list *list; + struct trace_seq s; + + pevent = pevent_alloc(); + if (!pevent) + die("Can not allocate pevent\n"); + + trace_seq_init(&s); + + list = tracecmd_load_plugins(pevent); + trace_util_print_plugins(&s, " ", "\n", list); + trace_seq_do_printf(&s); + tracecmd_unload_plugins(list, pevent); + pevent_free(pevent); +} + + +void trace_list(int argc, char **argv) +{ + int events = 0; + int tracer = 0; + int options = 0; + int funcs = 0; + int buffers = 0; + int clocks = 0; + int plug = 0; + int plug_op = 0; + int flags = 0; + int show_all = 1; + int i; + const char *arg; + const char *funcre = NULL; + const char *eventre = NULL; + + for (i = 2; i < argc; i++) { + arg = NULL; + if (argv[i][0] == '-') { + if (i < argc - 1) { + if (argv[i+1][0] != '-') + arg = argv[i+1]; + } + switch (argv[i][1]) { + case 'h': + usage(argv); + break; + case 'e': + events = 1; + eventre = arg; + show_all = 0; + break; + case 'B': + buffers = 1; + show_all = 0; + break; + case 'C': + clocks = 1; + show_all = 0; + break; + case 'F': + flags |= SHOW_EVENT_FORMAT; + break; + case 'R': + flags |= SHOW_EVENT_TRIGGER; + break; + case 'l': + flags |= SHOW_EVENT_FILTER; + break; + case 'p': + case 't': + tracer = 1; + show_all = 0; + break; + case 'P': + plug = 1; + show_all = 0; + break; + case 'O': + plug_op = 1; + show_all = 0; + break; + case 'o': + options = 1; + show_all = 0; + break; + case 'f': + funcs = 1; + funcre = arg; + show_all = 0; + break; + case '-': + if (strcmp(argv[i], "--debug") == 0) { + debug = true; + break; + } + fprintf(stderr, "list: invalid option -- '%s'\n", + argv[i]); + default: + fprintf(stderr, "list: invalid option -- '%c'\n", + argv[i][1]); + usage(argv); + } + } + } + + if (events) + show_events(eventre, flags); + + if (tracer) + show_tracers(); + + if (options) + show_options(); + + if (plug) + show_plugins(); + + if (plug_op) + show_plugin_options(); + + if (funcs) + show_functions(funcre); + + if (buffers) + show_buffers(); + + if (clocks) + show_clocks(); + + if (show_all) { + printf("events:\n"); + show_events(NULL, 0); + printf("\ntracers:\n"); + show_tracers(); + printf("\noptions:\n"); + show_options(); + } + + return; + +} diff --git a/trace-local.h b/trace-local.h index 46aa979..ee518fb 100644 --- a/trace-local.h +++ b/trace-local.h @@ -65,6 +65,8 @@ void trace_listen(int argc, char **argv); void trace_restore(int argc, char **argv); +void trace_check_events(int argc, char **argv); + void trace_stack(int argc, char **argv); void trace_option(int argc, char **argv); @@ -77,6 +79,10 @@ void trace_mem(int argc, char **argv); void trace_stat(int argc, char **argv); +void trace_show(int argc, char **argv); + +void trace_list(int argc, char **argv); + struct hook_list; void trace_init_profile(struct tracecmd_input *handle, struct hook_list *hooks, @@ -183,6 +189,7 @@ char *get_instance_file(struct buffer_instance *instance, const char *file); void update_first_instance(struct buffer_instance *instance, int topt); void show_instance_file(struct buffer_instance *instance, const char *name); +void show_plugin_options(void); int count_cpus(void); /* No longer in event-utils.h */ diff --git a/trace-show.c b/trace-show.c new file mode 100644 index 0000000..14b786c --- /dev/null +++ b/trace-show.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License (not later!) + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "trace-local.h" + +enum { + OPT_tracing_on = 255, + OPT_current_tracer = 254, + OPT_buffer_size_kb = 253, + OPT_buffer_total_size_kb = 252, + OPT_ftrace_filter = 251, + OPT_ftrace_notrace = 250, + OPT_ftrace_pid = 249, + OPT_graph_function = 248, + OPT_graph_notrace = 247, + OPT_cpumask = 246, +}; + +void trace_show(int argc, char **argv) +{ + const char *buffer = NULL; + const char *file = "trace"; + const char *cpu = NULL; + struct buffer_instance *instance = &top_instance; + char cpu_path[128]; + char *path; + int snap = 0; + int pipe = 0; + int show_name = 0; + int option_index = 0; + int stop = 0; + int c; + static struct option long_options[] = { + {"tracing_on", no_argument, NULL, OPT_tracing_on}, + {"current_tracer", no_argument, NULL, OPT_current_tracer}, + {"buffer_size", no_argument, NULL, OPT_buffer_size_kb}, + {"buffer_total_size", no_argument, NULL, OPT_buffer_total_size_kb}, + {"ftrace_filter", no_argument, NULL, OPT_ftrace_filter}, + {"ftrace_notrace", no_argument, NULL, OPT_ftrace_notrace}, + {"ftrace_pid", no_argument, NULL, OPT_ftrace_pid}, + {"graph_function", no_argument, NULL, OPT_graph_function}, + {"graph_notrace", no_argument, NULL, OPT_graph_notrace}, + {"cpumask", no_argument, NULL, OPT_cpumask}, + {"help", no_argument, NULL, '?'}, + {NULL, 0, NULL, 0} + }; + + while ((c = getopt_long(argc-1, argv+1, "B:c:fsp", + long_options, &option_index)) >= 0) { + switch (c) { + case 'h': + usage(argv); + break; + case 'B': + if (buffer) + die("Can only show one buffer at a time"); + buffer = optarg; + instance = create_instance(optarg); + if (!instance) + die("Failed to create instance"); + break; + case 'c': + if (cpu) + die("Can only show one CPU at a time"); + cpu = optarg; + break; + case 'f': + show_name = 1; + break; + case 's': + snap = 1; + if (pipe) + die("Can not have -s and -p together"); + break; + case 'p': + pipe = 1; + if (snap) + die("Can not have -s and -p together"); + break; + case OPT_tracing_on: + show_instance_file(instance, "tracing_on"); + stop = 1; + break; + case OPT_current_tracer: + show_instance_file(instance, "current_tracer"); + stop = 1; + break; + case OPT_buffer_size_kb: + show_instance_file(instance, "buffer_size_kb"); + stop = 1; + break; + case OPT_buffer_total_size_kb: + show_instance_file(instance, "buffer_total_size_kb"); + stop = 1; + break; + case OPT_ftrace_filter: + show_instance_file(instance, "set_ftrace_filter"); + stop = 1; + break; + case OPT_ftrace_notrace: + show_instance_file(instance, "set_ftrace_notrace"); + stop = 1; + break; + case OPT_ftrace_pid: + show_instance_file(instance, "set_ftrace_pid"); + stop = 1; + break; + case OPT_graph_function: + show_instance_file(instance, "set_graph_function"); + stop = 1; + break; + case OPT_graph_notrace: + show_instance_file(instance, "set_graph_notrace"); + stop = 1; + break; + case OPT_cpumask: + show_instance_file(instance, "tracing_cpumask"); + stop = 1; + break; + default: + usage(argv); + } + } + if (stop) + exit(0); + if (pipe) + file = "trace_pipe"; + else if (snap) + file = "snapshot"; + + if (cpu) { + snprintf(cpu_path, 128, "per_cpu/cpu%d/%s", atoi(cpu), file); + file = cpu_path; + } + + if (buffer) { + path = malloc(strlen(buffer) + strlen("instances//") + + strlen(file) + 1); + if (!path) + die("Failed to allocate instance path %s", file); + sprintf(path, "instances/%s/%s", buffer, file); + file = path; + } + + if (show_name) { + char *name; + name = tracecmd_get_tracing_file(file); + printf("%s\n", name); + tracecmd_put_tracing_file(name); + } + show_file(file); + if (buffer) + free(path); + + return; +} -- 2.9.3