From 12e55569a244996a23cb401e8116e5a060b664f0 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 19 Nov 2013 18:29:37 -0500 Subject: tools lib traceevent: Use helper trace-seq in print functions like kernel does Jiri Olsa reported that his plugin for scsi was chopping off part of the output. Investigating this, I found that Jiri used the same functions as what is in the kernel, which adds the following: trace_seq_putc(p, 0); This adds a '\0' to the output string. The reason this works in the kernel is that the "p" that is passed to the function helper is a temporary trace_seq. But in the libtraceevent library, it's the pointer to the trace_seq used to output. By adding the '\0', it truncates the line and nothing added after that will be printed. We can solve this in two ways. One is to have the helper functions for the library not add the unnecessary '\0'. The other is to change the library to also use a helper trace_seq structure that gets copied to the main trace_seq just like the kernel does. The latter allows the helper functions in the plugins to be the same as the kernel, which is the better solution. Signed-off-by: Steven Rostedt Reported-by: Jiri Olsa Tested-by: Jiri Olsa Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20131119182937.401668e3@gandalf.local.home Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 217c82ee3665..900fca01bdd3 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -4099,6 +4099,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event unsigned long long val; struct func_map *func; const char *saveptr; + struct trace_seq p; char *bprint_fmt = NULL; char format[32]; int show_func; @@ -4306,8 +4307,12 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event format[len] = 0; if (!len_as_arg) len_arg = -1; - print_str_arg(s, data, size, event, + /* Use helper trace_seq */ + trace_seq_init(&p); + print_str_arg(&p, data, size, event, format, len_arg, arg); + trace_seq_terminate(&p); + trace_seq_puts(s, p.buffer); arg = arg->next; break; default: -- cgit v1.2.3 From c877bbd8eceb14c5eac6779cc804fa8b34044736 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:16 +0100 Subject: tools lib traceevent: Add plugin support Backporting plugin support for traceevent lib. Backported from Steven Rostedt's trace-cmd repo (HEAD 0f2c2fb): git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git It's now possible to use following interface to load plugins (shared objects) to enhance pevent object functionality. The plugin interface/hooks are as follows: (taken from event-parse.h comments) - 'pevent_plugin_loader' (required) The function name to initialized the plugin. int pevent_plugin_loader(struct pevent *pevent) - 'pevent_plugin_unloader' (optional) The function called just before unloading int pevent_plugin_unloader(void) - 'pevent_plugin_options' (optional) Plugin options that can be set before loading struct plugin_option pevent_plugin_options[] = { { .name = "option-name", .plugin_alias = "overide-file-name", (optional) .description = "description of option to show users", }, { .name = NULL, }, }; Array must end with .name = NULL; The plugin_alias (below) can be used to give a shorter name to access the variable. Useful if a plugin handles more than one event. NOTE options support is not backported yet. - 'pevent_plugin_alias' (optional) The name to use for finding options (uses filename if not defined) New traceevent functions are added to search and load available plugins: struct plugin_list* traceevent_load_plugins(struct pevent *pevent) - loads plusing for 'struct pevent' object and returns loaded plugins list void traceevent_unload_plugins(struct plugin_list *plugin_list); - unload plugin list Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-3-git-send-email-jolsa@redhat.com Signed-off-by: Steven Rostedt Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 6 +- tools/lib/traceevent/event-parse.h | 5 + tools/lib/traceevent/event-plugin.c | 202 ++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 tools/lib/traceevent/event-plugin.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index fc1502098595..2ccb5bc800e8 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -180,7 +180,11 @@ $(obj)/%.o: $(src)/%.c %.o: $(src)/%.c $(Q)$(call do_compile) -PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o +PEVENT_LIB_OBJS = event-parse.o +PEVENT_LIB_OBJS += event-plugin.o +PEVENT_LIB_OBJS += trace-seq.o +PEVENT_LIB_OBJS += parse-filter.o +PEVENT_LIB_OBJS += parse-utils.o PEVENT_LIB_OBJS += kbuffer-parse.o ALL_OBJS = $(PEVENT_LIB_OBJS) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 8d73d2594f65..a28886066bcc 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -377,6 +377,11 @@ enum pevent_errno { }; #undef _PE +struct plugin_list; + +struct plugin_list *traceevent_load_plugins(struct pevent *pevent); +void traceevent_unload_plugins(struct plugin_list *plugin_list); + struct cmdline; struct cmdline_list; struct func_map; diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c new file mode 100644 index 000000000000..d272d87aa7d4 --- /dev/null +++ b/tools/lib/traceevent/event-plugin.c @@ -0,0 +1,202 @@ +/* + * 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 Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include +#include +#include +#include +#include +#include +#include +#include "event-parse.h" +#include "event-utils.h" + +#define LOCAL_PLUGIN_DIR ".traceevent/plugins" + +struct plugin_list { + struct plugin_list *next; + char *name; + void *handle; +}; + +static void +load_plugin(struct pevent *pevent, const char *path, + const char *file, void *data) +{ + struct plugin_list **plugin_list = data; + pevent_plugin_load_func func; + struct plugin_list *list; + const char *alias; + char *plugin; + void *handle; + + plugin = malloc_or_die(strlen(path) + strlen(file) + 2); + + strcpy(plugin, path); + strcat(plugin, "/"); + strcat(plugin, file); + + handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL); + if (!handle) { + warning("could not load plugin '%s'\n%s\n", + plugin, dlerror()); + goto out_free; + } + + alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME); + if (!alias) + alias = file; + + func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME); + if (!func) { + warning("could not find func '%s' in plugin '%s'\n%s\n", + PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror()); + goto out_free; + } + + list = malloc_or_die(sizeof(*list)); + list->next = *plugin_list; + list->handle = handle; + list->name = plugin; + *plugin_list = list; + + pr_stat("registering plugin: %s", plugin); + func(pevent); + return; + + out_free: + free(plugin); +} + +static void +load_plugins_dir(struct pevent *pevent, const char *suffix, + const char *path, + void (*load_plugin)(struct pevent *pevent, + const char *path, + const char *name, + void *data), + void *data) +{ + struct dirent *dent; + struct stat st; + DIR *dir; + int ret; + + ret = stat(path, &st); + if (ret < 0) + return; + + if (!S_ISDIR(st.st_mode)) + return; + + dir = opendir(path); + if (!dir) + return; + + while ((dent = readdir(dir))) { + const char *name = dent->d_name; + + if (strcmp(name, ".") == 0 || + strcmp(name, "..") == 0) + continue; + + /* Only load plugins that end in suffix */ + if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0) + continue; + + load_plugin(pevent, path, name, data); + } + + closedir(dir); +} + +static void +load_plugins(struct pevent *pevent, const char *suffix, + void (*load_plugin)(struct pevent *pevent, + const char *path, + const char *name, + void *data), + void *data) +{ + char *home; + char *path; + char *envdir; + + /* + * If a system plugin directory was defined, + * check that first. + */ +#ifdef PLUGIN_DIR + load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data); +#endif + + /* + * Next let the environment-set plugin directory + * override the system defaults. + */ + envdir = getenv("TRACEEVENT_PLUGIN_DIR"); + if (envdir) + load_plugins_dir(pevent, suffix, envdir, load_plugin, data); + + /* + * Now let the home directory override the environment + * or system defaults. + */ + home = getenv("HOME"); + if (!home) + return; + + path = malloc_or_die(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2); + + strcpy(path, home); + strcat(path, "/"); + strcat(path, LOCAL_PLUGIN_DIR); + + load_plugins_dir(pevent, suffix, path, load_plugin, data); + + free(path); +} + +struct plugin_list* +traceevent_load_plugins(struct pevent *pevent) +{ + struct plugin_list *list = NULL; + + load_plugins(pevent, ".so", load_plugin, &list); + return list; +} + +void +traceevent_unload_plugins(struct plugin_list *plugin_list) +{ + pevent_plugin_unload_func func; + struct plugin_list *list; + + while (plugin_list) { + list = plugin_list; + plugin_list = list->next; + func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME); + if (func) + func(); + dlclose(list->handle); + free(list->name); + free(list); + } +} -- cgit v1.2.3 From e0e96d03f004e8953a731053b61e275f276fff01 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:17 +0100 Subject: tools lib traceevent: Add plugin build support Backporting missing pieces of plugin building infrastructure: - Adding Makefile 'plugins' target to build all defined plugins - Adding Makefile 'install_plugins' target as 'install_lib' target dependency - Link plugin objects with shared object building Backported from Steven Rostedt's trace-cmd repo (HEAD 0f2c2fb): git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git Plugins are by default installed into following locations: '$(HOME)/.traceevent/plugins' - If we are installing under $(HOME) '$(prefix)/lib/traceevent/plugins' - Otherwise This path is propagated to the plugin object as a plugins search path. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-4-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 52 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 2ccb5bc800e8..15267988f6b6 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -43,6 +43,30 @@ man_dir_SQ = '$(subst ','\'',$(man_dir))' export man_dir man_dir_SQ INSTALL export DESTDIR DESTDIR_SQ +set_plugin_dir := 1 + +# Set plugin_dir to preffered global plugin location +# If we install under $HOME directory we go under +# $(HOME)/.traceevent/plugins +# +# We dont set PLUGIN_DIR in case we install under $HOME +# directory, because by default the code looks under: +# $(HOME)/.traceevent/plugins by default. +# +ifeq ($(plugin_dir),) +ifeq ($(prefix),$(HOME)) +override plugin_dir = $(HOME)/.traceevent/plugins +set_plugin_dir := 0 +else +override plugin_dir = $(prefix)/lib/traceevent/plugins +endif +endif + +ifeq ($(set_plugin_dir),1) +PLUGIN_DIR = -DPLUGIN_DIR="$(DESTDIR)/$(plugin_dir)" +PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' +endif + # copy a bit from Linux kbuild ifeq ("$(origin V)", "command line") @@ -96,6 +120,7 @@ export prefix bindir src obj # Shell quotes bindir_SQ = $(subst ','\'',$(bindir)) bindir_relative_SQ = $(subst ','\'',$(bindir_relative)) +plugin_dir_SQ = $(subst ','\'',$(plugin_dir)) LIB_FILE = libtraceevent.a libtraceevent.so @@ -138,8 +163,8 @@ else print_app_build = echo ' BUILD '$(OBJ); print_fpic_compile = echo ' CC FPIC '$(OBJ); print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); - print_plugin_obj_compile = echo ' BUILD PLUGIN OBJ '$(OBJ); - print_plugin_build = echo ' BUILD PLUGIN '$(OBJ); + print_plugin_obj_compile = echo ' CC FPIC '$(OBJ); + print_plugin_build = echo ' BUILD PLUGIN '$(OBJ); print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; endif @@ -187,9 +212,11 @@ PEVENT_LIB_OBJS += parse-filter.o PEVENT_LIB_OBJS += parse-utils.o PEVENT_LIB_OBJS += kbuffer-parse.o -ALL_OBJS = $(PEVENT_LIB_OBJS) +PLUGINS := $(PLUGIN_OBJS:.o=.so) + +ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS) -CMD_TARGETS = $(LIB_FILE) +CMD_TARGETS = $(LIB_FILE) $(PLUGINS) TARGETS = $(CMD_TARGETS) @@ -204,9 +231,17 @@ libtraceevent.so: $(PEVENT_LIB_OBJS) libtraceevent.a: $(PEVENT_LIB_OBJS) $(Q)$(do_build_static_lib) +plugins: $(PLUGINS) + $(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS $(Q)$(do_fpic_compile) +$(PLUGIN_OBJS): %.o : $(src)/%.c + $(Q)$(do_compile_plugin_obj) + +$(PLUGINS): %.so: %.o + $(Q)$(do_plugin_build) + define make_version.h (echo '/* This file is automatically generated. Do not modify. */'; \ echo \#define VERSION_CODE $(shell \ @@ -294,9 +329,16 @@ define do_install $(INSTALL) $1 '$(DESTDIR_SQ)$2' endef -install_lib: all_cmd +install_lib: all_cmd install_plugins $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ)) +PLUGINS_INSTALL = $(subst .so,.install,$(PLUGINS)) + +$(PLUGINS_INSTALL): %.install : %.so force + $(Q)$(call do_install,$<,$(plugin_dir_SQ)) + +install_plugins: $(PLUGINS_INSTALL) + install: install_lib clean: -- cgit v1.2.3 From 91a058ad3856b0a37cb21250eb4c478d0297a1a3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:18 +0100 Subject: tools lib traceevent: Add traceevent_host_bigendian function Adding traceevent_host_bigendian function to get host endianity. It's used in following patches. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-5-git-send-email-jolsa@redhat.com Signed-off-by: Steven Rostedt Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index a28886066bcc..54273c0ec544 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -23,6 +23,7 @@ #include #include #include +#include #ifndef __maybe_unused #define __maybe_unused __attribute__((unused)) @@ -527,6 +528,15 @@ __data2host8(struct pevent *pevent, unsigned long long data) __data2host8(pevent, __val); \ }) +static inline int traceevent_host_bigendian(void) +{ + unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 }; + unsigned int val; + + memcpy(&val, str, 4); + return val == 0x01020304; +} + /* taken from kernel/trace/trace.h */ enum trace_flag_type { TRACE_FLAG_IRQS_OFF = 0x01, -- cgit v1.2.3 From 71ad9583ff15d2e95cb8c67a5c963321d9d1877b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:19 +0100 Subject: tools lib traceevent: Change pevent_parse_format to include pevent handle Changing the pevent_parse_format interface to include the pevent handle. The goal is to always use pevent object when dealing with traceevent library. The reason is that we might need additional processing (like plugins), which is not possible otherwise. Patches follow to make this happen completely. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-6-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 56 ++++++++++++++++++++++++-------------- tools/lib/traceevent/event-parse.h | 4 ++- 2 files changed, 38 insertions(+), 22 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 900fca01bdd3..9849873265d4 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -5121,8 +5121,38 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp, return ret; } +static enum pevent_errno +__pevent_parse_event(struct pevent *pevent, + struct event_format **eventp, + const char *buf, unsigned long size, + const char *sys) +{ + int ret = __pevent_parse_format(eventp, pevent, buf, size, sys); + struct event_format *event = *eventp; + + if (event == NULL) + return ret; + + if (pevent && add_event(pevent, event)) { + ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; + goto event_add_failed; + } + +#define PRINT_ARGS 0 + if (PRINT_ARGS && event->print_fmt.args) + print_args(event->print_fmt.args); + + return 0; + +event_add_failed: + pevent_free_format(event); + return ret; +} + /** * pevent_parse_format - parse the event format + * @pevent: the handle to the pevent + * @eventp: returned format * @buf: the buffer storing the event format string * @size: the size of @buf * @sys: the system the event belongs to @@ -5134,10 +5164,12 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp, * * /sys/kernel/debug/tracing/events/.../.../format */ -enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, +enum pevent_errno pevent_parse_format(struct pevent *pevent, + struct event_format **eventp, + const char *buf, unsigned long size, const char *sys) { - return __pevent_parse_format(eventp, NULL, buf, size, sys); + return __pevent_parse_event(pevent, eventp, buf, size, sys); } /** @@ -5158,25 +5190,7 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, unsigned long size, const char *sys) { struct event_format *event = NULL; - int ret = __pevent_parse_format(&event, pevent, buf, size, sys); - - if (event == NULL) - return ret; - - if (add_event(pevent, event)) { - ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; - goto event_add_failed; - } - -#define PRINT_ARGS 0 - if (PRINT_ARGS && event->print_fmt.args) - print_args(event->print_fmt.args); - - return 0; - -event_add_failed: - pevent_free_format(event); - return ret; + return __pevent_parse_event(pevent, &event, buf, size, sys); } #undef _PE diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 54273c0ec544..620c27a72960 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -562,7 +562,9 @@ int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long siz enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, unsigned long size, const char *sys); -enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, +enum pevent_errno pevent_parse_format(struct pevent *pevent, + struct event_format **eventp, + const char *buf, unsigned long size, const char *sys); void pevent_free_format(struct event_format *event); -- cgit v1.2.3 From f33c5cd73172c4fb81daa83a4f6d322210172fa0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:20 +0100 Subject: tools lib traceevent: Harmonize the install messages in lib-traceevent Removing the 'to ...' part out of the install message, because it does not fit to the rest of the build messages we use. Before: INSTALL plugin_hrtimer.so to /home/jolsa/libexec/perf-core/traceevent/plugins INSTALL plugin_jbd2.so to /home/jolsa/libexec/perf-core/traceevent/plugins INSTALL plugin_kmem.so to /home/jolsa/libexec/perf-core/traceevent/plugins INSTALL plugin_kvm.so to /home/jolsa/libexec/perf-core/traceevent/plugins INSTALL plugin_mac80211.so to /home/jolsa/libexec/perf-core/traceevent/plugins INSTALL plugin_sched_switch.so to /home/jolsa/libexec/perf-core/traceevent/plugins INSTALL plugin_function.so to /home/jolsa/libexec/perf-core/traceevent/plugins INSTALL plugin_xen.so to /home/jolsa/libexec/perf-core/traceevent/plugins INSTALL plugin_scsi.so to /home/jolsa/libexec/perf-core/traceevent/plugins Now: INSTALL plugin_jbd2.so INSTALL plugin_hrtimer.so INSTALL plugin_kmem.so INSTALL plugin_kvm.so INSTALL plugin_mac80211.so INSTALL plugin_sched_switch.so INSTALL plugin_function.so INSTALL plugin_xen.so INSTALL plugin_scsi.so Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-7-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 15267988f6b6..f9468519d5f7 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -166,7 +166,7 @@ else print_plugin_obj_compile = echo ' CC FPIC '$(OBJ); print_plugin_build = echo ' BUILD PLUGIN '$(OBJ); print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); - print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; + print_install = echo ' INSTALL '$1; endif do_fpic_compile = \ -- cgit v1.2.3 From e0549f11e8d57c1a606773342b3b71c74f9986eb Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:26 +0100 Subject: tools lib traceevent: Add jbd2 plugin Backporting jbd2 plugin. Backported from Steven Rostedt's trace-cmd repo (HEAD 0f2c2fb): git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git This plugin adds field resolving functions for following tracepoint events: jbd2:jbd2_checkpoint_stats jbd2:jbd2_run_stats The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e 'jbd2:jbd2_run_stats,jbd2:jbd2_checkpoint_stats' -a') --- script.jbd2.old +++ script.jbd2.new - jbd2/dm-3-8 576 [000] 2983.748423: jbd2:jbd2_checkpoint_stats: [FAILED TO PARSE] dev=265289731 tid=0x3f2bbb chp_time=0x0 forced_to_close=0 written=0 dropped=2 + jbd2/dm-3-8 576 [000] 2983.748423: jbd2:jbd2_checkpoint_stats: dev 253,3 tid 4139963 chp_time 0 forced_to_close 0 written 0 dropped 2 - jbd2/dm-3-8 576 [000] 2983.852789: jbd2:jbd2_run_stats: [FAILED TO PARSE] dev=265289731 tid=0x3f2bc0 wait=0x0 request_delay=0x0 running=0x138d locked=0x0 flushing=0x0 logging=0x68 handle_count=2995 blocks=17 blocks_logged=18 + jbd2/dm-3-8 576 [000] 2983.852789: jbd2:jbd2_run_stats: dev 253,3 tid 4139968 wait 0 request_delay 0 running 5005 locked 0 flushing 0 logging 104 handle_count 2995 blocks 17 blocks_logged 18 This plugin also adds jbd2_dev_to_name function, which was removed from jdb2 tracepoints recently. Keeping it in for backward compatibility reasons. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-13-git-send-email-jolsa@redhat.com Signed-off-by: Steven Rostedt Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 2 ++ tools/lib/traceevent/plugin_jbd2.c | 66 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tools/lib/traceevent/plugin_jbd2.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index f9468519d5f7..6c6540075a67 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -212,6 +212,8 @@ PEVENT_LIB_OBJS += parse-filter.o PEVENT_LIB_OBJS += parse-utils.o PEVENT_LIB_OBJS += kbuffer-parse.o +PLUGIN_OBJS = plugin_jbd2.o + PLUGINS := $(PLUGIN_OBJS:.o=.so) ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS) diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugin_jbd2.c new file mode 100644 index 000000000000..5d85de741b52 --- /dev/null +++ b/tools/lib/traceevent/plugin_jbd2.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 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 Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" + +#define MINORBITS 20 +#define MINORMASK ((1U << MINORBITS) - 1) + +#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) +#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) + +unsigned long long process_jbd2_dev_to_name(struct trace_seq *s, + unsigned long long *args) +{ + unsigned int dev = args[0]; + + trace_seq_printf(s, "%d:%d", MAJOR(dev), MINOR(dev)); + return 0; +} + +unsigned long long process_jiffies_to_msecs(struct trace_seq *s, + unsigned long long *args) +{ + unsigned long long jiffies = args[0]; + + trace_seq_printf(s, "%lld", jiffies); + return jiffies; +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + pevent_register_print_function(pevent, + process_jbd2_dev_to_name, + PEVENT_FUNC_ARG_STRING, + "jbd2_dev_to_name", + PEVENT_FUNC_ARG_INT, + PEVENT_FUNC_ARG_VOID); + + pevent_register_print_function(pevent, + process_jiffies_to_msecs, + PEVENT_FUNC_ARG_LONG, + "jiffies_to_msecs", + PEVENT_FUNC_ARG_LONG, + PEVENT_FUNC_ARG_VOID); + return 0; +} -- cgit v1.2.3 From d9d13f8be6237950753e093683e9f415f31eccbc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:27 +0100 Subject: tools lib traceevent: Add hrtimer plugin Backporting hrtimer plugin. Backported from Steven Rostedt's trace-cmd repo (HEAD 0f2c2fb): git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git This plugin adds function field resolving for following tracepoint events: timer:hrtimer_expire_entry timer:hrtimer_start The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e 'timer:hrtimer*' -a') --- script.hrtimer.old +++ script.hrtimer.new - swapper 0 [000] 27405.519092: timer:hrtimer_start: [FAILED TO PARSE] hrtimer=0xffff88021e20e800 function=0xffffffff810c0e10 expires=27398383000000 softexpires=27398383000000 + swapper 0 [000] 27405.519103: timer:hrtimer_start: hrtimer=0xffff88021e20e800 function=tick_sched_timer expires=27398383000000 softexpires=27398383000000 - swapper 0 [001] 27405.519544: timer:hrtimer_expire_entry: [FAILED TO PARSE] hrtimer=0xffff880211334058 now=27398294182491 function=0xffffffff81086f20 + swapper 0 [001] 27405.519544: timer:hrtimer_expire_entry: hrtimer=0xffff880211334058 now=27398294182491 function=posix_timer_fn/0x0 Check the 'function' field is translated into the function name. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-14-git-send-email-jolsa@redhat.com Signed-off-by: Steven Rostedt Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 3 +- tools/lib/traceevent/plugin_hrtimer.c | 93 +++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 tools/lib/traceevent/plugin_hrtimer.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 6c6540075a67..9ff2e2596614 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -212,7 +212,8 @@ PEVENT_LIB_OBJS += parse-filter.o PEVENT_LIB_OBJS += parse-utils.o PEVENT_LIB_OBJS += kbuffer-parse.o -PLUGIN_OBJS = plugin_jbd2.o +PLUGIN_OBJS = plugin_jbd2.o +PLUGIN_OBJS += plugin_hrtimer.o PLUGINS := $(PLUGIN_OBJS:.o=.so) diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c new file mode 100644 index 000000000000..e41d4cf9344f --- /dev/null +++ b/tools/lib/traceevent/plugin_hrtimer.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2009 Red Hat Inc, Steven Rostedt + * Copyright (C) 2009 Johannes Berg + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" + +static int timer_expire_handler(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context) +{ + trace_seq_printf(s, "hrtimer="); + + if (pevent_print_num_field(s, "0x%llx", event, "timer", + record, 0) == -1) + pevent_print_num_field(s, "0x%llx", event, "hrtimer", + record, 1); + + trace_seq_printf(s, " now="); + + pevent_print_num_field(s, "%llu", event, "now", record, 1); + + pevent_print_func_field(s, " function=%s", event, "function", + record, 0); + return 0; +} + +static int timer_start_handler(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context) +{ + struct pevent *pevent = event->pevent; + struct format_field *fn = pevent_find_field(event, "function"); + void *data = record->data; + + trace_seq_printf(s, "hrtimer="); + + if (pevent_print_num_field(s, "0x%llx", event, "timer", + record, 0) == -1) + pevent_print_num_field(s, "0x%llx", event, "hrtimer", + record, 1); + + if (!fn) { + trace_seq_printf(s, " function=MISSING"); + } else { + unsigned long long function; + const char *func; + + if (pevent_read_number_field(fn, data, &function)) + trace_seq_printf(s, " function=INVALID"); + + func = pevent_find_function(pevent, function); + + trace_seq_printf(s, " function=%s", func); + } + + trace_seq_printf(s, " expires="); + pevent_print_num_field(s, "%llu", event, "expires", record, 1); + + trace_seq_printf(s, " softexpires="); + pevent_print_num_field(s, "%llu", event, "softexpires", record, 1); + return 0; +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + pevent_register_event_handler(pevent, -1, + "timer", "hrtimer_expire_entry", + timer_expire_handler, NULL); + + pevent_register_event_handler(pevent, -1, "timer", "hrtimer_start", + timer_start_handler, NULL); + return 0; +} -- cgit v1.2.3 From f825628840e581f92f1c2e79dfa943f29c054e67 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:28 +0100 Subject: tools lib traceevent: Add kmem plugin Backporting kmem plugin. Backported from Steven Rostedt's trace-cmd repo (HEAD 0f2c2fb): git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git This plugin adds call_site field resolving for following tracepoint events: kmem:kfree kmem:kmalloc kmem:kmalloc_node kmem:kmem_cache_alloc kmem:kmem_cache_alloc_node kmem:kmem_cache_free The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e 'kmem:*' -a') --- script.kmem.old +++ script.kmem.new - perf 27846 [001] 29643.403319: kmem:kfree: call_site=ffffffff810e64f6 ptr=(nil) + perf 27846 [001] 29643.403238: kmem:kfree: (__audit_syscall_exit+0x1f6) call_site=ffffffff810e64f6 ptr=(nil) - perf 27846 [001] 29643.403337: kmem:kmem_cache_alloc: call_site=ffffffff812ff0c5 ptr=0xffff88020e155630 bytes_req=560 bytes_alloc=568 gfp_flags=GFP_KERNEL + perf 27846 [001] 29643.403337: kmem:kmem_cache_alloc: (radix_tree_preload+0x35) call_site=ffffffff812ff0c5 ptr=0xffff88020e155630 bytes_req=560 bytes_alloc=568 gfp_flags=GFP_KERNEL - perf 27846 [001] 29643.403342: kmem:kmem_cache_free: call_site=ffffffff8126ec61 ptr=0xffff88020dffe750 + perf 27846 [001] 29643.403342: kmem:kmem_cache_free: (jbd2_journal_stop+0x221) call_site=ffffffff8126ec61 ptr=0xffff88020dffe750 - firefox 954 [000] 29643.445477: kmem:kmem_cache_alloc_node: call_site=ffffffff8153c64e ptr=0xffff8801cecb4000 bytes_req=256 bytes_alloc=256 gfp_flags=GFP_KERNEL|GFP_REPEAT node=-1 + firefox 954 [000] 29643.445477: kmem:kmem_cache_alloc_node: (__alloc_skb+0x4e) call_site=ffffffff8153c64e ptr=0xffff8801cecb4000 bytes_req=256 bytes_alloc=256 gfp_flags=GFP_KERNEL|GFP_REPEAT node=-1 - perf 27846 [001] 29643.445510: kmem:kmalloc: call_site=ffffffff81250642 ptr=0xffff88020fd6c300 bytes_req=96 bytes_alloc=96 gfp_flags=GFP_NOFS|GFP_ZERO + perf 27846 [001] 29643.445510: kmem:kmalloc: (ext4_ext_find_extent+0x362) call_site=ffffffff81250642 ptr=0xffff88020fd6c300 bytes_req=96 bytes_alloc=96 gfp_flags=GFP_NOFS|GFP_ZERO - X 888 [002] 29643.445546: kmem:kmalloc_node: call_site=ffffffff8153c67e ptr=0xffff880103828e00 bytes_req=384 bytes_alloc=512 gfp_flags=GFP_KERNEL|GFP_NOWARN|GFP_REPEAT|GFP_NOMEMALLOC node=-1 + X 888 [002] 29643.445546: kmem:kmalloc_node: (__alloc_skb+0x7e) call_site=ffffffff8153c67e ptr=0xffff880103828e00 bytes_req=384 bytes_alloc=512 gfp_flags=GFP_KERNEL|GFP_NOWARN|GFP_REPEAT|GFP_NOMEMALLOC node=-1 Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-15-git-send-email-jolsa@redhat.com Signed-off-by: Steven Rostedt Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 1 + tools/lib/traceevent/plugin_kmem.c | 72 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tools/lib/traceevent/plugin_kmem.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 9ff2e2596614..245d6b4f0aed 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -214,6 +214,7 @@ PEVENT_LIB_OBJS += kbuffer-parse.o PLUGIN_OBJS = plugin_jbd2.o PLUGIN_OBJS += plugin_hrtimer.o +PLUGIN_OBJS += plugin_kmem.o PLUGINS := $(PLUGIN_OBJS:.o=.so) diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c new file mode 100644 index 000000000000..7115c8037ea8 --- /dev/null +++ b/tools/lib/traceevent/plugin_kmem.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" + +static int call_site_handler(struct trace_seq *s, struct pevent_record *record, + struct event_format *event, void *context) +{ + struct format_field *field; + unsigned long long val, addr; + void *data = record->data; + const char *func; + + field = pevent_find_field(event, "call_site"); + if (!field) + return 1; + + if (pevent_read_number_field(field, data, &val)) + return 1; + + func = pevent_find_function(event->pevent, val); + if (!func) + return 1; + + addr = pevent_find_function_address(event->pevent, val); + + trace_seq_printf(s, "(%s+0x%x) ", func, (int)(val - addr)); + return 1; +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + pevent_register_event_handler(pevent, -1, "kmem", "kfree", + call_site_handler, NULL); + + pevent_register_event_handler(pevent, -1, "kmem", "kmalloc", + call_site_handler, NULL); + + pevent_register_event_handler(pevent, -1, "kmem", "kmalloc_node", + call_site_handler, NULL); + + pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_alloc", + call_site_handler, NULL); + + pevent_register_event_handler(pevent, -1, "kmem", + "kmem_cache_alloc_node", + call_site_handler, NULL); + + pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_free", + call_site_handler, NULL); + return 0; +} -- cgit v1.2.3 From 35d79f9ff88765af3fba6981db8d071872dcc5a8 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:29 +0100 Subject: tools lib traceevent: Add kvm plugin Backporting kvm plugin. Backported from Steven Rostedt's trace-cmd repo (HEAD 0f2c2fb): git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git This plugin adds field resolving functions for following tracepoint events: kvm:kvm_exit kvm:kvm_emulate_insn kvm:kvm_nested_vmexit kvm:kvm_nested_vmexit_inject kvmmmu:kvm_mmu_get_page kvmmmu:kvm_mmu_sync_page kvmmmu:kvm_mmu_unsync_page kvmmmu:kvm_mmu_zap_page kvmmmu:kvm_mmu_prepare_zap_page The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e 'kvm:*,kvmmmu:*' -a') --- script.kvm.old +++ script.kvm.new qemu-system-x86 17414 [000] 6868.995053: kvm:kvm_exit: reason EPT_VIOLATION rip 0xfff0 info 184 0 qemu-system-x86 17414 [000] 6868.995109: kvm:kvm_emulate_insn: f0000:c46b:e4 71 (real) - qemu-system-x86 3006 [002] 10562.079422: kvmmmu:kvm_mmu_get_page: [FAILED TO PARSE] mmu_valid_gen=0x2 gfn=0 role=122884 root_count=0 unsync=0 created=1 + qemu-system-x86 3006 [002] 10562.079422: kvmmmu:kvm_mmu_get_page: new sp gfn 0 0/4 q0 direct --- !pge !nxe root 0 sync - qemu-system-x86 3006 [002] 10562.080502: kvmmmu:kvm_mmu_prepare_zap_page: [FAILED TO PARSE] mmu_valid_gen=0x2 gfn=0 role=122884 root_count=1 unsync=0 + qemu-system-x86 3006 [002] 10562.080502: kvmmmu:kvm_mmu_prepare_zap_page: 0/4 q0 direct --- !pge !nxe root 1 sync qemu-system-x86 3290 [002] 10708.755312: kvmmmu:fast_page_fault: [FAILED TO PARSE] vcpu_id=0 gva=4094486080 error_code=3 sptep=0xffff88019f1e3670 old_spte=336391285 new_spte=336391287 retry=1 - insmod 2576 [001] 781.731666: kvmmmu:kvm_mmu_sync_page: [FAILED TO PARSE] mmu_valid_gen=0x1 gfn=2 role=24624 root_count=10 unsync=1 + insmod 2576 [001] 781.731666: kvmmmu:kvm_mmu_sync_page: 3/0 q0 --- !pge !nxe root 10 unsync - insmod 2576 [001] 781.731668: kvmmmu:kvm_mmu_unsync_page: [FAILED TO PARSE] mmu_valid_gen=0x1 gfn=2 role=24624 root_count=10 unsync=1 + insmod 2576 [001] 781.731668: kvmmmu:kvm_mmu_unsync_page: 3/0 q0 --- !pge !nxe root 10 unsync Note: - kvm_mmu_zap_page is replaced by kvm_mmu_prepare_zap_page in current kernel, keeping it for backward compatibility - some of the tracepoints keep the same output even with the plugin handling: kvm:kvm_exit, kvm:kvm_emulate_insn - the 'kvmmmu:fast_page_fault' is still broken because of missing is_writable_pte function and is fixed in another patch - ommited following tracepoints from backport because the output was buggy kvm:kvm_nested_vmexit kvm:kvm_nested_vmexit_inject Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-16-git-send-email-jolsa@redhat.com Signed-off-by: Jiri Olsa Signed-off-by: Steven Rostedt Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 1 + tools/lib/traceevent/plugin_kvm.c | 419 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 420 insertions(+) create mode 100644 tools/lib/traceevent/plugin_kvm.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 245d6b4f0aed..226a8f9fb177 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -215,6 +215,7 @@ PEVENT_LIB_OBJS += kbuffer-parse.o PLUGIN_OBJS = plugin_jbd2.o PLUGIN_OBJS += plugin_hrtimer.o PLUGIN_OBJS += plugin_kmem.o +PLUGIN_OBJS += plugin_kvm.o PLUGINS := $(PLUGIN_OBJS:.o=.so) diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c new file mode 100644 index 000000000000..be9d9c6a49e6 --- /dev/null +++ b/tools/lib/traceevent/plugin_kvm.c @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2009 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include +#include + +#include "event-parse.h" + +#ifdef HAVE_UDIS86 + +#include + +static ud_t ud; + +static void init_disassembler(void) +{ + ud_init(&ud); + ud_set_syntax(&ud, UD_SYN_ATT); +} + +static const char *disassemble(unsigned char *insn, int len, uint64_t rip, + int cr0_pe, int eflags_vm, + int cs_d, int cs_l) +{ + int mode; + + if (!cr0_pe) + mode = 16; + else if (eflags_vm) + mode = 16; + else if (cs_l) + mode = 64; + else if (cs_d) + mode = 32; + else + mode = 16; + + ud_set_pc(&ud, rip); + ud_set_mode(&ud, mode); + ud_set_input_buffer(&ud, insn, len); + ud_disassemble(&ud); + return ud_insn_asm(&ud); +} + +#else + +static void init_disassembler(void) +{ +} + +static const char *disassemble(unsigned char *insn, int len, uint64_t rip, + int cr0_pe, int eflags_vm, + int cs_d, int cs_l) +{ + static char out[15*3+1]; + int i; + + for (i = 0; i < len; ++i) + sprintf(out + i * 3, "%02x ", insn[i]); + out[len*3-1] = '\0'; + return out; +} + +#endif + + +#define VMX_EXIT_REASONS \ + _ER(EXCEPTION_NMI, 0) \ + _ER(EXTERNAL_INTERRUPT, 1) \ + _ER(TRIPLE_FAULT, 2) \ + _ER(PENDING_INTERRUPT, 7) \ + _ER(NMI_WINDOW, 8) \ + _ER(TASK_SWITCH, 9) \ + _ER(CPUID, 10) \ + _ER(HLT, 12) \ + _ER(INVD, 13) \ + _ER(INVLPG, 14) \ + _ER(RDPMC, 15) \ + _ER(RDTSC, 16) \ + _ER(VMCALL, 18) \ + _ER(VMCLEAR, 19) \ + _ER(VMLAUNCH, 20) \ + _ER(VMPTRLD, 21) \ + _ER(VMPTRST, 22) \ + _ER(VMREAD, 23) \ + _ER(VMRESUME, 24) \ + _ER(VMWRITE, 25) \ + _ER(VMOFF, 26) \ + _ER(VMON, 27) \ + _ER(CR_ACCESS, 28) \ + _ER(DR_ACCESS, 29) \ + _ER(IO_INSTRUCTION, 30) \ + _ER(MSR_READ, 31) \ + _ER(MSR_WRITE, 32) \ + _ER(MWAIT_INSTRUCTION, 36) \ + _ER(MONITOR_INSTRUCTION, 39) \ + _ER(PAUSE_INSTRUCTION, 40) \ + _ER(MCE_DURING_VMENTRY, 41) \ + _ER(TPR_BELOW_THRESHOLD, 43) \ + _ER(APIC_ACCESS, 44) \ + _ER(EOI_INDUCED, 45) \ + _ER(EPT_VIOLATION, 48) \ + _ER(EPT_MISCONFIG, 49) \ + _ER(INVEPT, 50) \ + _ER(PREEMPTION_TIMER, 52) \ + _ER(WBINVD, 54) \ + _ER(XSETBV, 55) \ + _ER(APIC_WRITE, 56) \ + _ER(INVPCID, 58) + +#define SVM_EXIT_REASONS \ + _ER(EXIT_READ_CR0, 0x000) \ + _ER(EXIT_READ_CR3, 0x003) \ + _ER(EXIT_READ_CR4, 0x004) \ + _ER(EXIT_READ_CR8, 0x008) \ + _ER(EXIT_WRITE_CR0, 0x010) \ + _ER(EXIT_WRITE_CR3, 0x013) \ + _ER(EXIT_WRITE_CR4, 0x014) \ + _ER(EXIT_WRITE_CR8, 0x018) \ + _ER(EXIT_READ_DR0, 0x020) \ + _ER(EXIT_READ_DR1, 0x021) \ + _ER(EXIT_READ_DR2, 0x022) \ + _ER(EXIT_READ_DR3, 0x023) \ + _ER(EXIT_READ_DR4, 0x024) \ + _ER(EXIT_READ_DR5, 0x025) \ + _ER(EXIT_READ_DR6, 0x026) \ + _ER(EXIT_READ_DR7, 0x027) \ + _ER(EXIT_WRITE_DR0, 0x030) \ + _ER(EXIT_WRITE_DR1, 0x031) \ + _ER(EXIT_WRITE_DR2, 0x032) \ + _ER(EXIT_WRITE_DR3, 0x033) \ + _ER(EXIT_WRITE_DR4, 0x034) \ + _ER(EXIT_WRITE_DR5, 0x035) \ + _ER(EXIT_WRITE_DR6, 0x036) \ + _ER(EXIT_WRITE_DR7, 0x037) \ + _ER(EXIT_EXCP_BASE, 0x040) \ + _ER(EXIT_INTR, 0x060) \ + _ER(EXIT_NMI, 0x061) \ + _ER(EXIT_SMI, 0x062) \ + _ER(EXIT_INIT, 0x063) \ + _ER(EXIT_VINTR, 0x064) \ + _ER(EXIT_CR0_SEL_WRITE, 0x065) \ + _ER(EXIT_IDTR_READ, 0x066) \ + _ER(EXIT_GDTR_READ, 0x067) \ + _ER(EXIT_LDTR_READ, 0x068) \ + _ER(EXIT_TR_READ, 0x069) \ + _ER(EXIT_IDTR_WRITE, 0x06a) \ + _ER(EXIT_GDTR_WRITE, 0x06b) \ + _ER(EXIT_LDTR_WRITE, 0x06c) \ + _ER(EXIT_TR_WRITE, 0x06d) \ + _ER(EXIT_RDTSC, 0x06e) \ + _ER(EXIT_RDPMC, 0x06f) \ + _ER(EXIT_PUSHF, 0x070) \ + _ER(EXIT_POPF, 0x071) \ + _ER(EXIT_CPUID, 0x072) \ + _ER(EXIT_RSM, 0x073) \ + _ER(EXIT_IRET, 0x074) \ + _ER(EXIT_SWINT, 0x075) \ + _ER(EXIT_INVD, 0x076) \ + _ER(EXIT_PAUSE, 0x077) \ + _ER(EXIT_HLT, 0x078) \ + _ER(EXIT_INVLPG, 0x079) \ + _ER(EXIT_INVLPGA, 0x07a) \ + _ER(EXIT_IOIO, 0x07b) \ + _ER(EXIT_MSR, 0x07c) \ + _ER(EXIT_TASK_SWITCH, 0x07d) \ + _ER(EXIT_FERR_FREEZE, 0x07e) \ + _ER(EXIT_SHUTDOWN, 0x07f) \ + _ER(EXIT_VMRUN, 0x080) \ + _ER(EXIT_VMMCALL, 0x081) \ + _ER(EXIT_VMLOAD, 0x082) \ + _ER(EXIT_VMSAVE, 0x083) \ + _ER(EXIT_STGI, 0x084) \ + _ER(EXIT_CLGI, 0x085) \ + _ER(EXIT_SKINIT, 0x086) \ + _ER(EXIT_RDTSCP, 0x087) \ + _ER(EXIT_ICEBP, 0x088) \ + _ER(EXIT_WBINVD, 0x089) \ + _ER(EXIT_MONITOR, 0x08a) \ + _ER(EXIT_MWAIT, 0x08b) \ + _ER(EXIT_MWAIT_COND, 0x08c) \ + _ER(EXIT_NPF, 0x400) \ + _ER(EXIT_ERR, -1) + +#define _ER(reason, val) { #reason, val }, +struct str_values { + const char *str; + int val; +}; + +static struct str_values vmx_exit_reasons[] = { + VMX_EXIT_REASONS + { NULL, -1} +}; + +static struct str_values svm_exit_reasons[] = { + SVM_EXIT_REASONS + { NULL, -1} +}; + +static struct isa_exit_reasons { + unsigned isa; + struct str_values *strings; +} isa_exit_reasons[] = { + { .isa = 1, .strings = vmx_exit_reasons }, + { .isa = 2, .strings = svm_exit_reasons }, + { } +}; + +static const char *find_exit_reason(unsigned isa, int val) +{ + struct str_values *strings = NULL; + int i; + + for (i = 0; isa_exit_reasons[i].strings; ++i) + if (isa_exit_reasons[i].isa == isa) { + strings = isa_exit_reasons[i].strings; + break; + } + if (!strings) + return "UNKNOWN-ISA"; + for (i = 0; strings[i].val >= 0; i++) + if (strings[i].val == val) + break; + if (strings[i].str) + return strings[i].str; + return "UNKNOWN"; +} + +static int kvm_exit_handler(struct trace_seq *s, struct pevent_record *record, + struct event_format *event, void *context) +{ + unsigned long long isa; + unsigned long long val; + unsigned long long info1 = 0, info2 = 0; + + if (pevent_get_field_val(s, event, "exit_reason", record, &val, 1) < 0) + return -1; + + if (pevent_get_field_val(s, event, "isa", record, &isa, 0) < 0) + isa = 1; + + trace_seq_printf(s, "reason %s", find_exit_reason(isa, val)); + + pevent_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1); + + if (pevent_get_field_val(s, event, "info1", record, &info1, 0) >= 0 + && pevent_get_field_val(s, event, "info2", record, &info2, 0) >= 0) + trace_seq_printf(s, " info %llx %llx", info1, info2); + + return 0; +} + +#define KVM_EMUL_INSN_F_CR0_PE (1 << 0) +#define KVM_EMUL_INSN_F_EFL_VM (1 << 1) +#define KVM_EMUL_INSN_F_CS_D (1 << 2) +#define KVM_EMUL_INSN_F_CS_L (1 << 3) + +static int kvm_emulate_insn_handler(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context) +{ + unsigned long long rip, csbase, len, flags, failed; + int llen; + uint8_t *insn; + const char *disasm; + + if (pevent_get_field_val(s, event, "rip", record, &rip, 1) < 0) + return -1; + + if (pevent_get_field_val(s, event, "csbase", record, &csbase, 1) < 0) + return -1; + + if (pevent_get_field_val(s, event, "len", record, &len, 1) < 0) + return -1; + + if (pevent_get_field_val(s, event, "flags", record, &flags, 1) < 0) + return -1; + + if (pevent_get_field_val(s, event, "failed", record, &failed, 1) < 0) + return -1; + + insn = pevent_get_field_raw(s, event, "insn", record, &llen, 1); + if (!insn) + return -1; + + disasm = disassemble(insn, len, rip, + flags & KVM_EMUL_INSN_F_CR0_PE, + flags & KVM_EMUL_INSN_F_EFL_VM, + flags & KVM_EMUL_INSN_F_CS_D, + flags & KVM_EMUL_INSN_F_CS_L); + + trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm, + failed ? " FAIL" : ""); + return 0; +} + +union kvm_mmu_page_role { + unsigned word; + struct { + unsigned glevels:4; + unsigned level:4; + unsigned quadrant:2; + unsigned pad_for_nice_hex_output:6; + unsigned direct:1; + unsigned access:3; + unsigned invalid:1; + unsigned cr4_pge:1; + unsigned nxe:1; + }; +}; + +static int kvm_mmu_print_role(struct trace_seq *s, struct pevent_record *record, + struct event_format *event, void *context) +{ + unsigned long long val; + static const char *access_str[] = { + "---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux" + }; + union kvm_mmu_page_role role; + + if (pevent_get_field_val(s, event, "role", record, &val, 1) < 0) + return -1; + + role.word = (int)val; + + /* + * We can only use the structure if file is of the same + * endianess. + */ + if (pevent_is_file_bigendian(event->pevent) == + pevent_is_host_bigendian(event->pevent)) { + + trace_seq_printf(s, "%u/%u q%u%s %s%s %spge %snxe", + role.level, + role.glevels, + role.quadrant, + role.direct ? " direct" : "", + access_str[role.access], + role.invalid ? " invalid" : "", + role.cr4_pge ? "" : "!", + role.nxe ? "" : "!"); + } else + trace_seq_printf(s, "WORD: %08x", role.word); + + pevent_print_num_field(s, " root %u ", event, + "root_count", record, 1); + + if (pevent_get_field_val(s, event, "unsync", record, &val, 1) < 0) + return -1; + + trace_seq_printf(s, "%s%c", val ? "unsync" : "sync", 0); + return 0; +} + +static int kvm_mmu_get_page_handler(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context) +{ + unsigned long long val; + + if (pevent_get_field_val(s, event, "created", record, &val, 1) < 0) + return -1; + + trace_seq_printf(s, "%s ", val ? "new" : "existing"); + + if (pevent_get_field_val(s, event, "gfn", record, &val, 1) < 0) + return -1; + + trace_seq_printf(s, "sp gfn %llx ", val); + return kvm_mmu_print_role(s, record, event, context); +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + init_disassembler(); + + pevent_register_event_handler(pevent, -1, "kvm", "kvm_exit", + kvm_exit_handler, NULL); + + pevent_register_event_handler(pevent, -1, "kvm", "kvm_emulate_insn", + kvm_emulate_insn_handler, NULL); + + pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page", + kvm_mmu_get_page_handler, NULL); + + pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page", + kvm_mmu_print_role, NULL); + + pevent_register_event_handler(pevent, -1, + "kvmmmu", "kvm_mmu_unsync_page", + kvm_mmu_print_role, NULL); + + pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page", + kvm_mmu_print_role, NULL); + + pevent_register_event_handler(pevent, -1, "kvmmmu", + "kvm_mmu_prepare_zap_page", kvm_mmu_print_role, + NULL); + return 0; +} -- cgit v1.2.3 From de705e2e88442c0c5dc6ec8c1f3fb1931def102e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:30 +0100 Subject: tools lib traceevent: Add mac80211 plugin Backporting mac80211 plugin. Backported from Steven Rostedt's trace-cmd repo (HEAD 0f2c2fb): git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git This plugin adds changed field resolving for mac80211:drv_bss_info_changed tracepoint event. The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e 'mac80211:drv_bss_info_changed' -a') --- script.mac80211.old +++ script.mac80211.new - ifconfig 3711 [000] 1290.446492: mac80211:drv_bss_info_changed: phy0 vif:wlan0(2) changed:0x309f + ifconfig 3711 [000] 1290.446492: mac80211:drv_bss_info_changed: phy0 vif:wlan0(2) + assoc:0 aid:2 cts:0 shortpre:0 shortslot:0 dtimper:1 + bcnint:102 assoc_cap:0x431 basic_rates:0xf enable_beacon:0 + ht_operation_mode:0 Omitting the mac80211:drv_config tracepoint handling because the kernel tracepoint changed its prototype and the plugin handler is no longer working. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-17-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 1 + tools/lib/traceevent/plugin_mac80211.c | 95 ++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 tools/lib/traceevent/plugin_mac80211.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 226a8f9fb177..d0e0ca12aa10 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -216,6 +216,7 @@ PLUGIN_OBJS = plugin_jbd2.o PLUGIN_OBJS += plugin_hrtimer.o PLUGIN_OBJS += plugin_kmem.o PLUGIN_OBJS += plugin_kvm.o +PLUGIN_OBJS += plugin_mac80211.o PLUGINS := $(PLUGIN_OBJS:.o=.so) diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c new file mode 100644 index 000000000000..558a3b91c046 --- /dev/null +++ b/tools/lib/traceevent/plugin_mac80211.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2009 Johannes Berg + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" + +#define INDENT 65 + +static void print_string(struct trace_seq *s, struct event_format *event, + const char *name, const void *data) +{ + struct format_field *f = pevent_find_field(event, name); + int offset; + int length; + + if (!f) { + trace_seq_printf(s, "NOTFOUND:%s", name); + return; + } + + offset = f->offset; + length = f->size; + + if (!strncmp(f->type, "__data_loc", 10)) { + unsigned long long v; + if (pevent_read_number_field(f, data, &v)) { + trace_seq_printf(s, "invalid_data_loc"); + return; + } + offset = v & 0xffff; + length = v >> 16; + } + + trace_seq_printf(s, "%.*s", length, (char *)data + offset); +} + +#define SF(fn) pevent_print_num_field(s, fn ":%d", event, fn, record, 0) +#define SFX(fn) pevent_print_num_field(s, fn ":%#x", event, fn, record, 0) +#define SP() trace_seq_putc(s, ' ') + +static int drv_bss_info_changed(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context) +{ + void *data = record->data; + + print_string(s, event, "wiphy_name", data); + trace_seq_printf(s, " vif:"); + print_string(s, event, "vif_name", data); + pevent_print_num_field(s, "(%d)", event, "vif_type", record, 1); + + trace_seq_printf(s, "\n%*s", INDENT, ""); + SF("assoc"); SP(); + SF("aid"); SP(); + SF("cts"); SP(); + SF("shortpre"); SP(); + SF("shortslot"); SP(); + SF("dtimper"); SP(); + trace_seq_printf(s, "\n%*s", INDENT, ""); + SF("bcnint"); SP(); + SFX("assoc_cap"); SP(); + SFX("basic_rates"); SP(); + SF("enable_beacon"); + trace_seq_printf(s, "\n%*s", INDENT, ""); + SF("ht_operation_mode"); + + return 0; +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + pevent_register_event_handler(pevent, -1, "mac80211", + "drv_bss_info_changed", + drv_bss_info_changed, NULL); + return 0; +} -- cgit v1.2.3 From 83e815ee1c6b5fdb570374404ab44b24c1325ccb Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:31 +0100 Subject: tools lib traceevent: Add sched_switch plugin Backporting sched_switch plugin. Backported from Steven Rostedt's trace-cmd repo (HEAD 0f2c2fb): git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git This plugin adds fields resolving for sched:sched_switch tracepoint event. The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e sched:sched_switch -a') --- script.sched_switch.old +++ script.sched_switch.new - perf 577 [002] 30965.311852: sched:sched_switch: prev_comm=perf prev_pid=577 prev_prio=120 prev_state=S ==> next_comm=swapper/2 next_pid=0 next_prio=120 + perf 577 [002] 30965.311852: sched:sched_switch: perf:577 [120] S ==> swapper/2:0 [120] Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-18-git-send-email-jolsa@redhat.com Signed-off-by: Steven Rostedt Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 1 + tools/lib/traceevent/plugin_sched_switch.c | 148 +++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 tools/lib/traceevent/plugin_sched_switch.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index d0e0ca12aa10..1c319a8cf1b0 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -217,6 +217,7 @@ PLUGIN_OBJS += plugin_hrtimer.o PLUGIN_OBJS += plugin_kmem.o PLUGIN_OBJS += plugin_kvm.o PLUGIN_OBJS += plugin_mac80211.o +PLUGIN_OBJS += plugin_sched_switch.o PLUGINS := $(PLUGIN_OBJS:.o=.so) diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c new file mode 100644 index 000000000000..fea3724aa24f --- /dev/null +++ b/tools/lib/traceevent/plugin_sched_switch.c @@ -0,0 +1,148 @@ +/* + * 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 Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" + +static void write_state(struct trace_seq *s, int val) +{ + const char states[] = "SDTtZXxW"; + int found = 0; + int i; + + for (i = 0; i < (sizeof(states) - 1); i++) { + if (!(val & (1 << i))) + continue; + + if (found) + trace_seq_putc(s, '|'); + + found = 1; + trace_seq_putc(s, states[i]); + } + + if (!found) + trace_seq_putc(s, 'R'); +} + +static void write_and_save_comm(struct format_field *field, + struct pevent_record *record, + struct trace_seq *s, int pid) +{ + const char *comm; + int len; + + comm = (char *)(record->data + field->offset); + len = s->len; + trace_seq_printf(s, "%.*s", + field->size, comm); + + /* make sure the comm has a \0 at the end. */ + trace_seq_terminate(s); + comm = &s->buffer[len]; + + /* Help out the comm to ids. This will handle dups */ + pevent_register_comm(field->event->pevent, comm, pid); +} + +static int sched_wakeup_handler(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context) +{ + struct format_field *field; + unsigned long long val; + + if (pevent_get_field_val(s, event, "pid", record, &val, 1)) + return trace_seq_putc(s, '!'); + + field = pevent_find_any_field(event, "comm"); + if (field) { + write_and_save_comm(field, record, s, val); + trace_seq_putc(s, ':'); + } + trace_seq_printf(s, "%lld", val); + + if (pevent_get_field_val(s, event, "prio", record, &val, 0) == 0) + trace_seq_printf(s, " [%lld]", val); + + if (pevent_get_field_val(s, event, "success", record, &val, 1) == 0) + trace_seq_printf(s, " success=%lld", val); + + if (pevent_get_field_val(s, event, "target_cpu", record, &val, 0) == 0) + trace_seq_printf(s, " CPU:%03llu", val); + + return 0; +} + +static int sched_switch_handler(struct trace_seq *s, + struct pevent_record *record, + struct event_format *event, void *context) +{ + struct format_field *field; + unsigned long long val; + + if (pevent_get_field_val(s, event, "prev_pid", record, &val, 1)) + return trace_seq_putc(s, '!'); + + field = pevent_find_any_field(event, "prev_comm"); + if (field) { + write_and_save_comm(field, record, s, val); + trace_seq_putc(s, ':'); + } + trace_seq_printf(s, "%lld ", val); + + if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) + trace_seq_printf(s, "[%lld] ", val); + + if (pevent_get_field_val(s, event, "prev_state", record, &val, 0) == 0) + write_state(s, val); + + trace_seq_puts(s, " ==> "); + + if (pevent_get_field_val(s, event, "next_pid", record, &val, 1)) + return trace_seq_putc(s, '!'); + + field = pevent_find_any_field(event, "next_comm"); + if (field) { + write_and_save_comm(field, record, s, val); + trace_seq_putc(s, ':'); + } + trace_seq_printf(s, "%lld", val); + + if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0) + trace_seq_printf(s, " [%lld]", val); + + return 0; +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + pevent_register_event_handler(pevent, -1, "sched", "sched_switch", + sched_switch_handler, NULL); + + pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup", + sched_wakeup_handler, NULL); + + pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup_new", + sched_wakeup_handler, NULL); + return 0; +} -- cgit v1.2.3 From 07a180a0bfea7029b8cf84a7d8e856539e5c69f5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:32 +0100 Subject: tools lib traceevent: Add function plugin Backporting function plugin. Backported from Steven Rostedt's trace-cmd repo (HEAD 0f2c2fb): git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git This plugin adds function and parent function fields resolving for ftrace:function tracepoint event. The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e ftrace:function ls') --- script.function.old +++ script.function.new - ls 10781 [001] 32667.291379: ftrace:function: ffffffff811adb80 <-- ffffffff811afc48 - ls 10781 [001] 32667.291379: ftrace:function: ffffffff811b35d0 <-- ffffffff811adb9b - ls 10781 [001] 32667.291380: ftrace:function: ffffffff811b3520 <-- ffffffff811b35e8 - ls 10781 [001] 32667.291380: ftrace:function: ffffffff811b2720 <-- ffffffff811b3549 - ls 10781 [001] 32667.291381: ftrace:function: ffffffff81297e10 <-- ffffffff811b356c - ls 10781 [001] 32667.291381: ftrace:function: ffffffff81298f40 <-- ffffffff81297e2c - ls 10781 [001] 32667.291382: ftrace:function: ffffffff81076160 <-- ffffffff811afbf0 - ls 10781 [001] 32667.291383: ftrace:function: ffffffff811c3eb0 <-- ffffffff811afbfc - ls 10781 [001] 32667.291383: ftrace:function: ffffffff8164e100 <-- ffffffff811c3ed8 - ls 10781 [001] 32667.291384: ftrace:function: ffffffff811a5d10 <-- ffffffff811c3f53 - ls 10781 [001] 32667.291384: ftrace:function: ffffffff811e8e70 <-- ffffffff811a5d58 - ls 10781 [001] 32667.291385: ftrace:function: ffffffff811f38e0 <-- ffffffff811a5d63 - ls 10781 [001] 32667.291385: ftrace:function: ffffffff811a9ff0 <-- ffffffff811a5d6b - ls 10781 [001] 32667.291386: ftrace:function: ffffffff811a9fa0 <-- ffffffff811aa015 - ls 10781 [001] 32667.291387: ftrace:function: ffffffff810851c0 <-- ffffffff811aa053 - ls 10781 [001] 32667.291387: ftrace:function: ffffffff81090e00 <-- ffffffff81085211 + ls 10781 [001] 32667.291379: ftrace:function: would_dump <-- setup_new_exec + ls 10781 [001] 32667.291379: ftrace:function: inode_permission <-- would_dump + ls 10781 [001] 32667.291380: ftrace:function: __inode_permission <-- inode_permission + ls 10781 [001] 32667.291380: ftrace:function: generic_permission <-- __inode_permission + ls 10781 [001] 32667.291381: ftrace:function: security_inode_permission <-- __inode_permission + ls 10781 [001] 32667.291381: ftrace:function: cap_inode_permission <-- security_inode_permission + ls 10781 [001] 32667.291382: ftrace:function: flush_signal_handlers <-- setup_new_exec + ls 10781 [001] 32667.291383: ftrace:function: do_close_on_exec <-- setup_new_exec + ls 10781 [001] 32667.291383: ftrace:function: _raw_spin_lock <-- do_close_on_exec + ls 10781 [001] 32667.291384: ftrace:function: filp_close <-- do_close_on_exec + ls 10781 [001] 32667.291384: ftrace:function: dnotify_flush <-- filp_close + ls 10781 [001] 32667.291385: ftrace:function: locks_remove_posix <-- filp_close + ls 10781 [001] 32667.291385: ftrace:function: fput <-- filp_close + ls 10781 [001] 32667.291386: ftrace:function: file_sb_list_del <-- fput + ls 10781 [001] 32667.291387: ftrace:function: task_work_add <-- fput + ls 10781 [001] 32667.291387: ftrace:function: kick_process <-- task_work_add Removing options support as it's not backported yet. Currently this plugin supports 2 options: 'parent' to display parent function 'indent' to show function call indents Enabling both of them by default. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-19-git-send-email-jolsa@redhat.com Signed-off-by: Steven Rostedt Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 1 + tools/lib/traceevent/plugin_function.c | 151 +++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 tools/lib/traceevent/plugin_function.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 1c319a8cf1b0..21f9b8fa5e43 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -218,6 +218,7 @@ PLUGIN_OBJS += plugin_kmem.o PLUGIN_OBJS += plugin_kvm.o PLUGIN_OBJS += plugin_mac80211.o PLUGIN_OBJS += plugin_sched_switch.o +PLUGIN_OBJS += plugin_function.o PLUGINS := $(PLUGIN_OBJS:.o=.so) diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c new file mode 100644 index 000000000000..8deb22e69361 --- /dev/null +++ b/tools/lib/traceevent/plugin_function.c @@ -0,0 +1,151 @@ +/* + * 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 Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "event-parse.h" +#include "event-utils.h" + +static struct func_stack { + int index; + int size; + char **stack; +} *fstack; + +static int cpus = -1; + +#define STK_BLK 10 + +static void add_child(struct func_stack *stack, const char *child, int pos) +{ + int i; + + if (!child) + return; + + if (pos < stack->size) + free(stack->stack[pos]); + else { + if (!stack->stack) + stack->stack = malloc_or_die(sizeof(char *) * STK_BLK); + else + stack->stack = realloc(stack->stack, sizeof(char *) * + (stack->size + STK_BLK)); + for (i = stack->size; i < stack->size + STK_BLK; i++) + stack->stack[i] = NULL; + stack->size += STK_BLK; + } + + stack->stack[pos] = strdup(child); +} + +static int get_index(const char *parent, const char *child, int cpu) +{ + int i; + + if (cpu < 0) + return 0; + + if (cpu > cpus) { + if (fstack) + fstack = realloc(fstack, sizeof(*fstack) * (cpu + 1)); + else + fstack = malloc_or_die(sizeof(*fstack) * (cpu + 1)); + + /* Account for holes in the cpu count */ + for (i = cpus + 1; i <= cpu; i++) + memset(&fstack[i], 0, sizeof(fstack[i])); + cpus = cpu; + } + + for (i = 0; i < fstack[cpu].size && fstack[cpu].stack[i]; i++) { + if (strcmp(parent, fstack[cpu].stack[i]) == 0) { + add_child(&fstack[cpu], child, i+1); + return i; + } + } + + /* Not found */ + add_child(&fstack[cpu], parent, 0); + add_child(&fstack[cpu], child, 1); + return 0; +} + +static int function_handler(struct trace_seq *s, struct pevent_record *record, + struct event_format *event, void *context) +{ + struct pevent *pevent = event->pevent; + unsigned long long function; + unsigned long long pfunction; + const char *func; + const char *parent; + int i, index; + + if (pevent_get_field_val(s, event, "ip", record, &function, 1)) + return trace_seq_putc(s, '!'); + + func = pevent_find_function(pevent, function); + + if (pevent_get_field_val(s, event, "parent_ip", record, &pfunction, 1)) + return trace_seq_putc(s, '!'); + + parent = pevent_find_function(pevent, pfunction); + + index = get_index(parent, func, record->cpu); + + for (i = 0; i < index; i++) + trace_seq_printf(s, " "); + + if (func) + trace_seq_printf(s, "%s", func); + else + trace_seq_printf(s, "0x%llx", function); + + trace_seq_printf(s, " <-- "); + if (parent) + trace_seq_printf(s, "%s", parent); + else + trace_seq_printf(s, "0x%llx", pfunction); + + return 0; +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + pevent_register_event_handler(pevent, -1, "ftrace", "function", + function_handler, NULL); + return 0; +} + +void PEVENT_PLUGIN_UNLOADER(void) +{ + int i, x; + + for (i = 0; i <= cpus; i++) { + for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++) + free(fstack[i].stack[x]); + free(fstack[i].stack); + } + + free(fstack); + fstack = NULL; + cpus = -1; +} -- cgit v1.2.3 From 40c03ad5925855e47e4b6294323107b2b180ae3d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:33 +0100 Subject: tools lib traceevent: Add xen plugin Adding xen plugin. This plugin adds fields resolving for following tracepoint events: xen:xen_mc_entry xen:xen_mc_extend_args The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e 'xen:*' ls') --- script.xen.old +++ script.xen.new - swapper 0 [002] 136.267492: xen:xen_mc_entry: [FAILED TO PARSE] op=3 nargs=2 args=ARRAY[18, 00, 00, 00, 00, 00, 00, 00, 00, e0, d4, 4b, 04, 88, ff, ff, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + swapper 0 [002] 136.267492: xen:xen_mc_entry: op 3(stack_switch) args [18, 0, 0, 0, 0, 0] - perf 1970 [008] 136.273319: xen:xen_mc_extend_args: [FAILED TO PARSE] op=1 args=16 res=1 + perf 1970 [008] 136.273319: xen:xen_mc_extend_args: extending op 1(mmu_update) by 16 bytes res ??? NOTE We still do not handle the 'sizeof' and fail to parse following xen tracepoints: xen:xen_mmu_set_pte xen:xen_mmu_set_pte_atomic xen:xen_mmu_set_domain_pte xen:xen_mmu_set_pte_at xen:xen_mmu_set_pmd xen:xen_mmu_set_pud xen:xen_mmu_set_pgd xen:xen_mmu_ptep_modify_prot_start xen:xen_mmu_ptep_modify_prot_commit Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jeremy Fitzhardinge Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-20-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 1 + tools/lib/traceevent/plugin_xen.c | 130 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 tools/lib/traceevent/plugin_xen.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 21f9b8fa5e43..54af60aff3b4 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -219,6 +219,7 @@ PLUGIN_OBJS += plugin_kvm.o PLUGIN_OBJS += plugin_mac80211.o PLUGIN_OBJS += plugin_sched_switch.o PLUGIN_OBJS += plugin_function.o +PLUGIN_OBJS += plugin_xen.o PLUGINS := $(PLUGIN_OBJS:.o=.so) diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugin_xen.c new file mode 100644 index 000000000000..e7794298f3a9 --- /dev/null +++ b/tools/lib/traceevent/plugin_xen.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include "event-parse.h" + +#define __HYPERVISOR_set_trap_table 0 +#define __HYPERVISOR_mmu_update 1 +#define __HYPERVISOR_set_gdt 2 +#define __HYPERVISOR_stack_switch 3 +#define __HYPERVISOR_set_callbacks 4 +#define __HYPERVISOR_fpu_taskswitch 5 +#define __HYPERVISOR_sched_op_compat 6 +#define __HYPERVISOR_dom0_op 7 +#define __HYPERVISOR_set_debugreg 8 +#define __HYPERVISOR_get_debugreg 9 +#define __HYPERVISOR_update_descriptor 10 +#define __HYPERVISOR_memory_op 12 +#define __HYPERVISOR_multicall 13 +#define __HYPERVISOR_update_va_mapping 14 +#define __HYPERVISOR_set_timer_op 15 +#define __HYPERVISOR_event_channel_op_compat 16 +#define __HYPERVISOR_xen_version 17 +#define __HYPERVISOR_console_io 18 +#define __HYPERVISOR_physdev_op_compat 19 +#define __HYPERVISOR_grant_table_op 20 +#define __HYPERVISOR_vm_assist 21 +#define __HYPERVISOR_update_va_mapping_otherdomain 22 +#define __HYPERVISOR_iret 23 /* x86 only */ +#define __HYPERVISOR_vcpu_op 24 +#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */ +#define __HYPERVISOR_mmuext_op 26 +#define __HYPERVISOR_acm_op 27 +#define __HYPERVISOR_nmi_op 28 +#define __HYPERVISOR_sched_op 29 +#define __HYPERVISOR_callback_op 30 +#define __HYPERVISOR_xenoprof_op 31 +#define __HYPERVISOR_event_channel_op 32 +#define __HYPERVISOR_physdev_op 33 +#define __HYPERVISOR_hvm_op 34 +#define __HYPERVISOR_tmem_op 38 + +/* Architecture-specific hypercall definitions. */ +#define __HYPERVISOR_arch_0 48 +#define __HYPERVISOR_arch_1 49 +#define __HYPERVISOR_arch_2 50 +#define __HYPERVISOR_arch_3 51 +#define __HYPERVISOR_arch_4 52 +#define __HYPERVISOR_arch_5 53 +#define __HYPERVISOR_arch_6 54 +#define __HYPERVISOR_arch_7 55 + +#define N(x) [__HYPERVISOR_##x] = "("#x")" +static const char *xen_hypercall_names[] = { + N(set_trap_table), + N(mmu_update), + N(set_gdt), + N(stack_switch), + N(set_callbacks), + N(fpu_taskswitch), + N(sched_op_compat), + N(dom0_op), + N(set_debugreg), + N(get_debugreg), + N(update_descriptor), + N(memory_op), + N(multicall), + N(update_va_mapping), + N(set_timer_op), + N(event_channel_op_compat), + N(xen_version), + N(console_io), + N(physdev_op_compat), + N(grant_table_op), + N(vm_assist), + N(update_va_mapping_otherdomain), + N(iret), + N(vcpu_op), + N(set_segment_base), + N(mmuext_op), + N(acm_op), + N(nmi_op), + N(sched_op), + N(callback_op), + N(xenoprof_op), + N(event_channel_op), + N(physdev_op), + N(hvm_op), + +/* Architecture-specific hypercall definitions. */ + N(arch_0), + N(arch_1), + N(arch_2), + N(arch_3), + N(arch_4), + N(arch_5), + N(arch_6), + N(arch_7), +}; +#undef N + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +static const char *xen_hypercall_name(unsigned op) +{ + if (op < ARRAY_SIZE(xen_hypercall_names) && + xen_hypercall_names[op] != NULL) + return xen_hypercall_names[op]; + + return ""; +} + +unsigned long long process_xen_hypercall_name(struct trace_seq *s, + unsigned long long *args) +{ + unsigned int op = args[0]; + + trace_seq_printf(s, "%s", xen_hypercall_name(op)); + return 0; +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + pevent_register_print_function(pevent, + process_xen_hypercall_name, + PEVENT_FUNC_ARG_STRING, + "xen_hypercall_name", + PEVENT_FUNC_ARG_INT, + PEVENT_FUNC_ARG_VOID); + return 0; +} -- cgit v1.2.3 From 04010929fa33ad3a446b9fd50b82321c1c3cf239 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:34 +0100 Subject: tools lib traceevent: Add scsi plugin Adding scsi plugin. This plugin adds fields resolving functions for following tracepoint events: scsi:scsi_dispatch_cmd_start scsi:scsi_dispatch_cmd_error scsi:scsi_dispatch_cmd_done scsi:scsi_dispatch_cmd_timeout The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e 'scsi:scsi_dispatch_cmd*' -a) - swapper 0 [000] 6620.491019: scsi:scsi_dispatch_cmd_done: [FAILED TO PARSE] host_no=0 channel=0 id=0 lun=0 result=0 opcode=53 cmd_len=10 data_sglen=0 prot_sglen=0 prot_op=0 cmnd=5 + swapper 0 [000] 6620.491019: scsi:scsi_dispatch_cmd_done: host_no=0 channel=0 id=0 lun=0 data_sgl=0 prot_sgl=0 prot_op=SCSI_PROT_NORMAL cmnd=(SYNCHRONIZE_CACHE - raw=35 00 00 00 00 00 00 00 00 00) result=(driver=DRIVER_OK host=DID_OK message=COMMAND_COMPLETE status=SAM_STAT_GOOD) - kworker/0:0 21554 [000] 6620.491126: scsi:scsi_dispatch_cmd_start: [FAILED TO PARSE] host_no=0 channel=0 id=0 lun=0 opcode=42 cmd_len=10 data_sglen=1 prot_sglen=0 prot_op=0 cmnd=* + kworker/0:0 21554 [000] 6620.491126: scsi:scsi_dispatch_cmd_start: host_no=0 channel=0 id=0 lun=0 data_sgl=1 prot_sgl=0 prot_op=SCSI_PROT_NORMAL cmnd=(WRITE_10 lba=570899168 txlen=8 protect=0 raw=2a 00 22 07 3a e0 00 00 08 00) - jbd2/dm-3-8 593 [002] 6621.607992: scsi:scsi_dispatch_cmd_error: [FAILED TO PARSE] host_no=0 channel=0 id=0 lun=0 rtn=4182 opcode=53 cmd_len=10 data_sglen=0 prot_sglen=0 prot_op=0 cmnd=5 + jbd2/dm-3-8 593 [002] 6621.607992: scsi:scsi_dispatch_cmd_error: host_no=0 channel=0 id=0 lun=0 data_sgl=0 prot_sgl=0 prot_op=SCSI_PROT_NORMAL cmnd=(SYNCHRONIZE_CACHE - raw=35 00 00 00 00 00 00 00 00 00) rtn=4182 NOTE I couldn't generate scsi_dispatch_cmd_timeout tracepoint, but it's similar to the rest, so I believe it's ok. Signed-off-by: Jiri Olsa Cc: "Martin K. Petersen" Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Martin K. Petersen Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-21-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 1 + tools/lib/traceevent/plugin_scsi.c | 423 +++++++++++++++++++++++++++++++++++++ 2 files changed, 424 insertions(+) create mode 100644 tools/lib/traceevent/plugin_scsi.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 54af60aff3b4..671f969922bc 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -220,6 +220,7 @@ PLUGIN_OBJS += plugin_mac80211.o PLUGIN_OBJS += plugin_sched_switch.o PLUGIN_OBJS += plugin_function.o PLUGIN_OBJS += plugin_xen.o +PLUGIN_OBJS += plugin_scsi.o PLUGINS := $(PLUGIN_OBJS:.o=.so) diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c new file mode 100644 index 000000000000..6fb8e3e3fcad --- /dev/null +++ b/tools/lib/traceevent/plugin_scsi.c @@ -0,0 +1,423 @@ +#include +#include +#include +#include "event-parse.h" + +typedef unsigned long sector_t; +typedef uint64_t u64; +typedef unsigned int u32; + +/* + * SCSI opcodes + */ +#define TEST_UNIT_READY 0x00 +#define REZERO_UNIT 0x01 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define READ_BLOCK_LIMITS 0x05 +#define REASSIGN_BLOCKS 0x07 +#define INITIALIZE_ELEMENT_STATUS 0x07 +#define READ_6 0x08 +#define WRITE_6 0x0a +#define SEEK_6 0x0b +#define READ_REVERSE 0x0f +#define WRITE_FILEMARKS 0x10 +#define SPACE 0x11 +#define INQUIRY 0x12 +#define RECOVER_BUFFERED_DATA 0x14 +#define MODE_SELECT 0x15 +#define RESERVE 0x16 +#define RELEASE 0x17 +#define COPY 0x18 +#define ERASE 0x19 +#define MODE_SENSE 0x1a +#define START_STOP 0x1b +#define RECEIVE_DIAGNOSTIC 0x1c +#define SEND_DIAGNOSTIC 0x1d +#define ALLOW_MEDIUM_REMOVAL 0x1e + +#define READ_FORMAT_CAPACITIES 0x23 +#define SET_WINDOW 0x24 +#define READ_CAPACITY 0x25 +#define READ_10 0x28 +#define WRITE_10 0x2a +#define SEEK_10 0x2b +#define POSITION_TO_ELEMENT 0x2b +#define WRITE_VERIFY 0x2e +#define VERIFY 0x2f +#define SEARCH_HIGH 0x30 +#define SEARCH_EQUAL 0x31 +#define SEARCH_LOW 0x32 +#define SET_LIMITS 0x33 +#define PRE_FETCH 0x34 +#define READ_POSITION 0x34 +#define SYNCHRONIZE_CACHE 0x35 +#define LOCK_UNLOCK_CACHE 0x36 +#define READ_DEFECT_DATA 0x37 +#define MEDIUM_SCAN 0x38 +#define COMPARE 0x39 +#define COPY_VERIFY 0x3a +#define WRITE_BUFFER 0x3b +#define READ_BUFFER 0x3c +#define UPDATE_BLOCK 0x3d +#define READ_LONG 0x3e +#define WRITE_LONG 0x3f +#define CHANGE_DEFINITION 0x40 +#define WRITE_SAME 0x41 +#define UNMAP 0x42 +#define READ_TOC 0x43 +#define READ_HEADER 0x44 +#define GET_EVENT_STATUS_NOTIFICATION 0x4a +#define LOG_SELECT 0x4c +#define LOG_SENSE 0x4d +#define XDWRITEREAD_10 0x53 +#define MODE_SELECT_10 0x55 +#define RESERVE_10 0x56 +#define RELEASE_10 0x57 +#define MODE_SENSE_10 0x5a +#define PERSISTENT_RESERVE_IN 0x5e +#define PERSISTENT_RESERVE_OUT 0x5f +#define VARIABLE_LENGTH_CMD 0x7f +#define REPORT_LUNS 0xa0 +#define SECURITY_PROTOCOL_IN 0xa2 +#define MAINTENANCE_IN 0xa3 +#define MAINTENANCE_OUT 0xa4 +#define MOVE_MEDIUM 0xa5 +#define EXCHANGE_MEDIUM 0xa6 +#define READ_12 0xa8 +#define WRITE_12 0xaa +#define READ_MEDIA_SERIAL_NUMBER 0xab +#define WRITE_VERIFY_12 0xae +#define VERIFY_12 0xaf +#define SEARCH_HIGH_12 0xb0 +#define SEARCH_EQUAL_12 0xb1 +#define SEARCH_LOW_12 0xb2 +#define SECURITY_PROTOCOL_OUT 0xb5 +#define READ_ELEMENT_STATUS 0xb8 +#define SEND_VOLUME_TAG 0xb6 +#define WRITE_LONG_2 0xea +#define EXTENDED_COPY 0x83 +#define RECEIVE_COPY_RESULTS 0x84 +#define ACCESS_CONTROL_IN 0x86 +#define ACCESS_CONTROL_OUT 0x87 +#define READ_16 0x88 +#define WRITE_16 0x8a +#define READ_ATTRIBUTE 0x8c +#define WRITE_ATTRIBUTE 0x8d +#define VERIFY_16 0x8f +#define SYNCHRONIZE_CACHE_16 0x91 +#define WRITE_SAME_16 0x93 +#define SERVICE_ACTION_IN 0x9e +/* values for service action in */ +#define SAI_READ_CAPACITY_16 0x10 +#define SAI_GET_LBA_STATUS 0x12 +/* values for VARIABLE_LENGTH_CMD service action codes + * see spc4r17 Section D.3.5, table D.7 and D.8 */ +#define VLC_SA_RECEIVE_CREDENTIAL 0x1800 +/* values for maintenance in */ +#define MI_REPORT_IDENTIFYING_INFORMATION 0x05 +#define MI_REPORT_TARGET_PGS 0x0a +#define MI_REPORT_ALIASES 0x0b +#define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c +#define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d +#define MI_REPORT_PRIORITY 0x0e +#define MI_REPORT_TIMESTAMP 0x0f +#define MI_MANAGEMENT_PROTOCOL_IN 0x10 +/* value for MI_REPORT_TARGET_PGS ext header */ +#define MI_EXT_HDR_PARAM_FMT 0x20 +/* values for maintenance out */ +#define MO_SET_IDENTIFYING_INFORMATION 0x06 +#define MO_SET_TARGET_PGS 0x0a +#define MO_CHANGE_ALIASES 0x0b +#define MO_SET_PRIORITY 0x0e +#define MO_SET_TIMESTAMP 0x0f +#define MO_MANAGEMENT_PROTOCOL_OUT 0x10 +/* values for variable length command */ +#define XDREAD_32 0x03 +#define XDWRITE_32 0x04 +#define XPWRITE_32 0x06 +#define XDWRITEREAD_32 0x07 +#define READ_32 0x09 +#define VERIFY_32 0x0a +#define WRITE_32 0x0b +#define WRITE_SAME_32 0x0d + +#define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f) +#define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9]) + +static const char * +scsi_trace_misc(struct trace_seq *, unsigned char *, int); + +static const char * +scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + sector_t lba = 0, txlen = 0; + + lba |= ((cdb[1] & 0x1F) << 16); + lba |= (cdb[2] << 8); + lba |= cdb[3]; + txlen = cdb[4]; + + trace_seq_printf(p, "lba=%llu txlen=%llu", + (unsigned long long)lba, (unsigned long long)txlen); + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + sector_t lba = 0, txlen = 0; + + lba |= (cdb[2] << 24); + lba |= (cdb[3] << 16); + lba |= (cdb[4] << 8); + lba |= cdb[5]; + txlen |= (cdb[7] << 8); + txlen |= cdb[8]; + + trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", + (unsigned long long)lba, (unsigned long long)txlen, + cdb[1] >> 5); + + if (cdb[0] == WRITE_SAME) + trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); + + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + sector_t lba = 0, txlen = 0; + + lba |= (cdb[2] << 24); + lba |= (cdb[3] << 16); + lba |= (cdb[4] << 8); + lba |= cdb[5]; + txlen |= (cdb[6] << 24); + txlen |= (cdb[7] << 16); + txlen |= (cdb[8] << 8); + txlen |= cdb[9]; + + trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", + (unsigned long long)lba, (unsigned long long)txlen, + cdb[1] >> 5); + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + sector_t lba = 0, txlen = 0; + + lba |= ((u64)cdb[2] << 56); + lba |= ((u64)cdb[3] << 48); + lba |= ((u64)cdb[4] << 40); + lba |= ((u64)cdb[5] << 32); + lba |= (cdb[6] << 24); + lba |= (cdb[7] << 16); + lba |= (cdb[8] << 8); + lba |= cdb[9]; + txlen |= (cdb[10] << 24); + txlen |= (cdb[11] << 16); + txlen |= (cdb[12] << 8); + txlen |= cdb[13]; + + trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u", + (unsigned long long)lba, (unsigned long long)txlen, + cdb[1] >> 5); + + if (cdb[0] == WRITE_SAME_16) + trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1); + + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len, *cmd; + sector_t lba = 0, txlen = 0; + u32 ei_lbrt = 0; + + switch (SERVICE_ACTION32(cdb)) { + case READ_32: + cmd = "READ"; + break; + case VERIFY_32: + cmd = "VERIFY"; + break; + case WRITE_32: + cmd = "WRITE"; + break; + case WRITE_SAME_32: + cmd = "WRITE_SAME"; + break; + default: + trace_seq_printf(p, "UNKNOWN"); + goto out; + } + + lba |= ((u64)cdb[12] << 56); + lba |= ((u64)cdb[13] << 48); + lba |= ((u64)cdb[14] << 40); + lba |= ((u64)cdb[15] << 32); + lba |= (cdb[16] << 24); + lba |= (cdb[17] << 16); + lba |= (cdb[18] << 8); + lba |= cdb[19]; + ei_lbrt |= (cdb[20] << 24); + ei_lbrt |= (cdb[21] << 16); + ei_lbrt |= (cdb[22] << 8); + ei_lbrt |= cdb[23]; + txlen |= (cdb[28] << 24); + txlen |= (cdb[29] << 16); + txlen |= (cdb[30] << 8); + txlen |= cdb[31]; + + trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u", + cmd, (unsigned long long)lba, + (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt); + + if (SERVICE_ACTION32(cdb) == WRITE_SAME_32) + trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1); + +out: + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + unsigned int regions = cdb[7] << 8 | cdb[8]; + + trace_seq_printf(p, "regions=%u", (regions - 8) / 16); + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len, *cmd; + sector_t lba = 0; + u32 alloc_len = 0; + + switch (SERVICE_ACTION16(cdb)) { + case SAI_READ_CAPACITY_16: + cmd = "READ_CAPACITY_16"; + break; + case SAI_GET_LBA_STATUS: + cmd = "GET_LBA_STATUS"; + break; + default: + trace_seq_printf(p, "UNKNOWN"); + goto out; + } + + lba |= ((u64)cdb[2] << 56); + lba |= ((u64)cdb[3] << 48); + lba |= ((u64)cdb[4] << 40); + lba |= ((u64)cdb[5] << 32); + lba |= (cdb[6] << 24); + lba |= (cdb[7] << 16); + lba |= (cdb[8] << 8); + lba |= cdb[9]; + alloc_len |= (cdb[10] << 24); + alloc_len |= (cdb[11] << 16); + alloc_len |= (cdb[12] << 8); + alloc_len |= cdb[13]; + + trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, + (unsigned long long)lba, alloc_len); + +out: + trace_seq_putc(p, 0); + return ret; +} + +static const char * +scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len) +{ + switch (SERVICE_ACTION32(cdb)) { + case READ_32: + case VERIFY_32: + case WRITE_32: + case WRITE_SAME_32: + return scsi_trace_rw32(p, cdb, len); + default: + return scsi_trace_misc(p, cdb, len); + } +} + +static const char * +scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len) +{ + const char *ret = p->buffer + p->len; + + trace_seq_printf(p, "-"); + trace_seq_putc(p, 0); + return ret; +} + +const char * +scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) +{ + switch (cdb[0]) { + case READ_6: + case WRITE_6: + return scsi_trace_rw6(p, cdb, len); + case READ_10: + case VERIFY: + case WRITE_10: + case WRITE_SAME: + return scsi_trace_rw10(p, cdb, len); + case READ_12: + case VERIFY_12: + case WRITE_12: + return scsi_trace_rw12(p, cdb, len); + case READ_16: + case VERIFY_16: + case WRITE_16: + case WRITE_SAME_16: + return scsi_trace_rw16(p, cdb, len); + case UNMAP: + return scsi_trace_unmap(p, cdb, len); + case SERVICE_ACTION_IN: + return scsi_trace_service_action_in(p, cdb, len); + case VARIABLE_LENGTH_CMD: + return scsi_trace_varlen(p, cdb, len); + default: + return scsi_trace_misc(p, cdb, len); + } +} + +unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s, + unsigned long long *args) +{ + scsi_trace_parse_cdb(s, (unsigned char *) args[1], args[2]); + return 0; +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + pevent_register_print_function(pevent, + process_scsi_trace_parse_cdb, + PEVENT_FUNC_ARG_STRING, + "scsi_trace_parse_cdb", + PEVENT_FUNC_ARG_PTR, + PEVENT_FUNC_ARG_PTR, + PEVENT_FUNC_ARG_INT, + PEVENT_FUNC_ARG_VOID); + return 0; +} -- cgit v1.2.3 From 943714737374635a134dc3de59a7f062cea53fb3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:35 +0100 Subject: tools lib traceevent: Add cfg80211 plugin Adding cfg80211 plugin. This plugin adds handler for __le16_to_cpup function t properly parse following tracepoint events: cfg80211:cfg80211_tx_mlme_mgmt cfg80211:cfg80211_rx_mlme_mgmt cfg80211:cfg80211_rx_unprot_mlme_mgmt The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e 'cfg80211:*' -a') --- script.cfg80211.old +++ script.cfg80211.new - ifconfig 2705 [003] 662.896560: cfg80211:cfg80211_tx_mlme_mgmt: [FAILED TO PARSE] name=wlan0 ifindex=3 frame=ARRAY[c0, 00, 00, 00, 00, 3a, 98, a0, 30, 51, 10, 0b, a9, c6, f4, 74, 00, 3a, 98, a0, 30, 51, 00, 00, 03, 00] + ifconfig 2705 [003] 662.896560: cfg80211:cfg80211_tx_mlme_mgmt: netdev:wlan0(3), ftype:0xc0 - kworker/u16:0 1697 [002] 664.808210: cfg80211:cfg80211_rx_mlme_mgmt: [FAILED TO PARSE] name=wlan0 ifindex=3 frame=ARRAY[b0, 00, da, 00, 10, 0b, a9, c6, f4, 74, d8, 24, bd, a1, 26, 31, d8, 24, bd, a1, 26, 31, 10, b7, 00, 00, 02, 00, 00, 00] + kworker/u16:0 1697 [002] 664.808210: cfg80211:cfg80211_rx_mlme_mgmt: netdev:wlan0(3), ftype:0xb0 Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-22-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 1 + tools/lib/traceevent/plugin_cfg80211.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tools/lib/traceevent/plugin_cfg80211.c (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 671f969922bc..0d9cbb426b44 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -221,6 +221,7 @@ PLUGIN_OBJS += plugin_sched_switch.o PLUGIN_OBJS += plugin_function.o PLUGIN_OBJS += plugin_xen.o PLUGIN_OBJS += plugin_scsi.o +PLUGIN_OBJS += plugin_cfg80211.o PLUGINS := $(PLUGIN_OBJS:.o=.so) diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c new file mode 100644 index 000000000000..dcab8e873c21 --- /dev/null +++ b/tools/lib/traceevent/plugin_cfg80211.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include "event-parse.h" + +static unsigned long long +process___le16_to_cpup(struct trace_seq *s, + unsigned long long *args) +{ + uint16_t *val = (uint16_t *) args[0]; + return val ? (long long) le16toh(*val) : 0; +} + +int PEVENT_PLUGIN_LOADER(struct pevent *pevent) +{ + pevent_register_print_function(pevent, + process___le16_to_cpup, + PEVENT_FUNC_ARG_INT, + "__le16_to_cpup", + PEVENT_FUNC_ARG_PTR, + PEVENT_FUNC_ARG_VOID); + return 0; +} -- cgit v1.2.3 From f9bb36afb25d3bfda1c9276a55985b710c8a91ae Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:36 +0100 Subject: tools lib traceevent: Remove malloc_or_die from event-plugin.c Removing malloc_or_die calls from event-plugin.c, replacing them with standard malloc and error path. Suggested-by: Namhyung Kim Signed-off-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-23-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-plugin.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index d272d87aa7d4..125f5676bcb5 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -47,7 +47,11 @@ load_plugin(struct pevent *pevent, const char *path, char *plugin; void *handle; - plugin = malloc_or_die(strlen(path) + strlen(file) + 2); + plugin = malloc(strlen(path) + strlen(file) + 2); + if (!plugin) { + warning("could not allocate plugin memory\n"); + return; + } strcpy(plugin, path); strcat(plugin, "/"); @@ -71,7 +75,12 @@ load_plugin(struct pevent *pevent, const char *path, goto out_free; } - list = malloc_or_die(sizeof(*list)); + list = malloc(sizeof(*list)); + if (!list) { + warning("could not allocate plugin memory\n"); + goto out_free; + } + list->next = *plugin_list; list->handle = handle; list->name = plugin; @@ -163,7 +172,11 @@ load_plugins(struct pevent *pevent, const char *suffix, if (!home) return; - path = malloc_or_die(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2); + path = malloc(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2); + if (!path) { + warning("could not allocate plugin memory\n"); + return; + } strcpy(path, home); strcat(path, "/"); -- cgit v1.2.3 From f04015ecb5eb0bf25260de585f0c5f60e84f073a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:37 +0100 Subject: tools lib traceevent: Use static functions in jbd2 plugin There's no need for following functions to be global: process_jbd2_dev_to_name process_jiffies_to_msecs Make them static. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-24-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_jbd2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugin_jbd2.c index 5d85de741b52..2f93f81f0bac 100644 --- a/tools/lib/traceevent/plugin_jbd2.c +++ b/tools/lib/traceevent/plugin_jbd2.c @@ -29,8 +29,9 @@ #define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS)) #define MINOR(dev) ((unsigned int) ((dev) & MINORMASK)) -unsigned long long process_jbd2_dev_to_name(struct trace_seq *s, - unsigned long long *args) +static unsigned long long +process_jbd2_dev_to_name(struct trace_seq *s, + unsigned long long *args) { unsigned int dev = args[0]; @@ -38,8 +39,9 @@ unsigned long long process_jbd2_dev_to_name(struct trace_seq *s, return 0; } -unsigned long long process_jiffies_to_msecs(struct trace_seq *s, - unsigned long long *args) +static unsigned long long +process_jiffies_to_msecs(struct trace_seq *s, + unsigned long long *args) { unsigned long long jiffies = args[0]; -- cgit v1.2.3 From b32cea650a16092a654baa2095c78fa917bad4da Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:38 +0100 Subject: tools lib traceevent: Use pevent_print_func_field in hrtimer_start handler The pevent_print_func_field function encompasses all the functionality used in the hrtimer_start handler. Change the handler to use this function. This also unifies the function field output with the hrtimer_expire_entry handler. Suggested-by: Steven Rostedt Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-25-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_hrtimer.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c index e41d4cf9344f..0b0ebf30aa44 100644 --- a/tools/lib/traceevent/plugin_hrtimer.c +++ b/tools/lib/traceevent/plugin_hrtimer.c @@ -48,10 +48,6 @@ static int timer_start_handler(struct trace_seq *s, struct pevent_record *record, struct event_format *event, void *context) { - struct pevent *pevent = event->pevent; - struct format_field *fn = pevent_find_field(event, "function"); - void *data = record->data; - trace_seq_printf(s, "hrtimer="); if (pevent_print_num_field(s, "0x%llx", event, "timer", @@ -59,19 +55,8 @@ static int timer_start_handler(struct trace_seq *s, pevent_print_num_field(s, "0x%llx", event, "hrtimer", record, 1); - if (!fn) { - trace_seq_printf(s, " function=MISSING"); - } else { - unsigned long long function; - const char *func; - - if (pevent_read_number_field(fn, data, &function)) - trace_seq_printf(s, " function=INVALID"); - - func = pevent_find_function(pevent, function); - - trace_seq_printf(s, " function=%s", func); - } + pevent_print_func_field(s, " function=%s", event, "function", + record, 0); trace_seq_printf(s, " expires="); pevent_print_num_field(s, "%llu", event, "expires", record, 1); -- cgit v1.2.3 From 39956e78010645ee9d121e6a6eb6d9892e3fc92e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:39 +0100 Subject: tools lib traceevent: Several cleanups for function plugin Several cleanups suggested by Namhyung: * Remove index field from struct func_stack as it's not needed. * Rename get_index into add_and_get_index. * Use '%*X' format string capability instead of the loop Suggested-by: Namhyung Kim Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-26-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_function.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c index 8deb22e69361..87acf9c77948 100644 --- a/tools/lib/traceevent/plugin_function.c +++ b/tools/lib/traceevent/plugin_function.c @@ -25,7 +25,6 @@ #include "event-utils.h" static struct func_stack { - int index; int size; char **stack; } *fstack; @@ -57,7 +56,7 @@ static void add_child(struct func_stack *stack, const char *child, int pos) stack->stack[pos] = strdup(child); } -static int get_index(const char *parent, const char *child, int cpu) +static int add_and_get_index(const char *parent, const char *child, int cpu) { int i; @@ -97,7 +96,7 @@ static int function_handler(struct trace_seq *s, struct pevent_record *record, unsigned long long pfunction; const char *func; const char *parent; - int i, index; + int index; if (pevent_get_field_val(s, event, "ip", record, &function, 1)) return trace_seq_putc(s, '!'); @@ -109,10 +108,9 @@ static int function_handler(struct trace_seq *s, struct pevent_record *record, parent = pevent_find_function(pevent, pfunction); - index = get_index(parent, func, record->cpu); + index = add_and_get_index(parent, func, record->cpu); - for (i = 0; i < index; i++) - trace_seq_printf(s, " "); + trace_seq_printf(s, "%*s", index*3, ""); if (func) trace_seq_printf(s, "%s", func); -- cgit v1.2.3 From d8e56c98b7ef96a31a64c69df24ab5d80f90e055 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:40 +0100 Subject: tools lib traceevent: Remove malloc_or_die from plugin_function.c Removing malloc_or_die calls from plugin_function.c, replacing them and factoring the code with standard realloc and error path. Suggested-by: Namhyung Kim Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-27-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_function.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c index 87acf9c77948..aad92ad5e96f 100644 --- a/tools/lib/traceevent/plugin_function.c +++ b/tools/lib/traceevent/plugin_function.c @@ -43,11 +43,17 @@ static void add_child(struct func_stack *stack, const char *child, int pos) if (pos < stack->size) free(stack->stack[pos]); else { - if (!stack->stack) - stack->stack = malloc_or_die(sizeof(char *) * STK_BLK); - else - stack->stack = realloc(stack->stack, sizeof(char *) * - (stack->size + STK_BLK)); + char **ptr; + + ptr = realloc(stack->stack, sizeof(char *) * + (stack->size + STK_BLK)); + if (!ptr) { + warning("could not allocate plugin memory\n"); + return; + } + + stack->stack = ptr; + for (i = stack->size; i < stack->size + STK_BLK; i++) stack->stack[i] = NULL; stack->size += STK_BLK; @@ -64,10 +70,15 @@ static int add_and_get_index(const char *parent, const char *child, int cpu) return 0; if (cpu > cpus) { - if (fstack) - fstack = realloc(fstack, sizeof(*fstack) * (cpu + 1)); - else - fstack = malloc_or_die(sizeof(*fstack) * (cpu + 1)); + struct func_stack *ptr; + + ptr = realloc(fstack, sizeof(*fstack) * (cpu + 1)); + if (!ptr) { + warning("could not allocate plugin memory\n"); + return 0; + } + + fstack = ptr; /* Account for holes in the cpu count */ for (i = cpus + 1; i <= cpu; i++) -- cgit v1.2.3 From 6d65894bc028d0342829ea1e64c9e9efad571124 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 3 Dec 2013 14:09:41 +0100 Subject: tools lib traceevent: Update kvm plugin with is_writable_pte helper Adding is_writable_pte print helper function, so the kvmmmu:fast_page_fault print format gets resolved properly. The diff of 'perf script' output generated by old and new code: (data was generated by 'perf record -e 'kvm:*,kvmmmu:*' -a') --- script.kvm.old +++ script.kvm.new - qemu-system-x86 3290 [002] 10708.755312: kvmmmu:fast_page_fault: [FAILED TO PARSE] vcpu_id=0 gva=4094486080 error_code=3 sptep=0xffff88019f1e3670 old_spte=336391285 new_spte=336391287 retry=1 + qemu-system-x86 3290 [002] 10708.755312: kvmmmu:fast_page_fault: vcpu 0 gva f40ce640 error_code P|W sptep 0xffff88019f1e3670 old 0x140cec75 new 140cec77 spurious 0 fixed 1 Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386076182-14484-28-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_kvm.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c index be9d9c6a49e6..a0e282c6b967 100644 --- a/tools/lib/traceevent/plugin_kvm.c +++ b/tools/lib/traceevent/plugin_kvm.c @@ -389,6 +389,16 @@ static int kvm_mmu_get_page_handler(struct trace_seq *s, return kvm_mmu_print_role(s, record, event, context); } +#define PT_WRITABLE_SHIFT 1 +#define PT_WRITABLE_MASK (1ULL << PT_WRITABLE_SHIFT) + +static unsigned long long +process_is_writable_pte(struct trace_seq *s, unsigned long long *args) +{ + unsigned long pte = args[0]; + return pte & PT_WRITABLE_MASK; +} + int PEVENT_PLUGIN_LOADER(struct pevent *pevent) { init_disassembler(); @@ -415,5 +425,12 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_prepare_zap_page", kvm_mmu_print_role, NULL); + + pevent_register_print_function(pevent, + process_is_writable_pte, + PEVENT_FUNC_ARG_INT, + "is_writable_pte", + PEVENT_FUNC_ARG_LONG, + PEVENT_FUNC_ARG_VOID); return 0; } -- cgit v1.2.3 From 3a3ffa2e82205921d1189f1055c22dae4c72819a Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 18 Nov 2013 21:38:20 -0500 Subject: tools lib traceevent: Report better error message on bad function args When Jiri Olsa was writing a function callback for scsi_trace_parse_cdb(), he thought that the traceevent library had a bug in it because he was getting this error: Error: expected ')' but read ',' Error: expected ')' but read ',' Error: expected ')' but read ',' Error: expected ')' but read ',' But in truth, he didn't have the write number of arguments for the function callback, and the error was the library detecting the discrepancy. A better error message would have prevented the confusion: Error: function 'scsi_trace_parse_cdb()' only expects 2 arguments but event scsi_dispatch_cmd_timeout has more Error: function 'scsi_trace_parse_cdb()' only expects 2 arguments but event scsi_dispatch_cmd_start has more Error: function 'scsi_trace_parse_cdb()' only expects 2 arguments but event scsi_dispatch_cmd_error has more Error: function 'scsi_trace_parse_cdb()' only expects 2 arguments but event scsi_dispatch_cmd_done has more Or Error: function 'scsi_trace_parse_cdb()' expects 4 arguments but event scsi_dispatch_cmd_timeout only uses 3 Error: function 'scsi_trace_parse_cdb()' expects 4 arguments but event scsi_dispatch_cmd_start only uses 3 Error: function 'scsi_trace_parse_cdb()' expects 4 arguments but event scsi_dispatch_cmd_error only uses 3 Error: function 'scsi_trace_parse_cdb()' expects 4 arguments but event scsi_dispatch_cmd_done only uses 3 Signed-off-by: Steven Rostedt Link: http://lkml.kernel.org/n/tip-a4c34w62vl0diitvxb7bt3er@git.kernel.org Signed-off-by: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 9849873265d4..22566c271275 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -2710,7 +2710,6 @@ process_func_handler(struct event_format *event, struct pevent_function_handler struct print_arg *farg; enum event_type type; char *token; - const char *test; int i; arg->type = PRINT_FUNC; @@ -2727,15 +2726,19 @@ process_func_handler(struct event_format *event, struct pevent_function_handler } type = process_arg(event, farg, &token); - if (i < (func->nr_args - 1)) - test = ","; - else - test = ")"; - - if (test_type_token(type, token, EVENT_DELIM, test)) { - free_arg(farg); - free_token(token); - return EVENT_ERROR; + if (i < (func->nr_args - 1)) { + if (type != EVENT_DELIM || strcmp(token, ",") != 0) { + warning("Error: function '%s()' expects %d arguments but event %s only uses %d", + func->name, func->nr_args, + event->name, i + 1); + goto err; + } + } else { + if (type != EVENT_DELIM || strcmp(token, ")") != 0) { + warning("Error: function '%s()' only expects %d arguments but event %s has more", + func->name, func->nr_args, event->name); + goto err; + } } *next_arg = farg; @@ -2747,6 +2750,11 @@ process_func_handler(struct event_format *event, struct pevent_function_handler *tok = token; return type; + +err: + free_arg(farg); + free_token(token); + return EVENT_ERROR; } static enum event_type -- cgit v1.2.3 From 4f24416331e9a507e953e90d4534e9a9802cbc12 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 9 Dec 2013 14:34:00 +0900 Subject: tools lib traceevent: Get rid of malloc_or_die() in pevent_filter_alloc() It returns NULL when allocation fails so the users should check the return value from now on. Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386567251-22751-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 2500e75583fc..b3a61d4fe38e 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -182,7 +182,10 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent) { struct event_filter *filter; - filter = malloc_or_die(sizeof(*filter)); + filter = malloc(sizeof(*filter)); + if (filter == NULL) + return NULL; + memset(filter, 0, sizeof(*filter)); filter->pevent = pevent; pevent_ref(pevent); -- cgit v1.2.3 From 234520d3fbe43ef72268c4959f85ae326459378c Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 9 Dec 2013 14:34:04 +0900 Subject: tools lib traceevent: Get rid of malloc_or_die() in add_event() Make it return error value since its only caller find_event() now can handle allocation error properly. Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386567251-22751-8-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index b3a61d4fe38e..2b73abfb0c9f 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -245,15 +245,19 @@ static void free_arg(struct filter_arg *arg) free(arg); } -static void add_event(struct event_list **events, +static int add_event(struct event_list **events, struct event_format *event) { struct event_list *list; - list = malloc_or_die(sizeof(*list)); + list = malloc(sizeof(*list)); + if (list == NULL) + return -1; + list->next = *events; *events = list; list->event = event; + return 0; } static int event_match(struct event_format *event, @@ -276,6 +280,7 @@ find_event(struct pevent *pevent, struct event_list **events, regex_t ereg; regex_t sreg; int match = 0; + int fail = 0; char *reg; int ret; int i; @@ -310,7 +315,10 @@ find_event(struct pevent *pevent, struct event_list **events, event = pevent->events[i]; if (event_match(event, sys_name ? &sreg : NULL, &ereg)) { match = 1; - add_event(events, event); + if (add_event(events, event) < 0) { + fail = 1; + break; + } } } @@ -320,6 +328,8 @@ find_event(struct pevent *pevent, struct event_list **events, if (!match) return -1; + if (fail) + return -2; return 0; } -- cgit v1.2.3 From 2036fcd1c7ce455424c11bdb1c8a2ac906430e2f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 9 Dec 2013 14:34:05 +0900 Subject: tools lib traceevent: Get rid of die() in create_arg_item() Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386567251-22751-9-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 2b73abfb0c9f..53e48eb112c3 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -362,8 +362,11 @@ create_arg_item(struct event_format *event, const char *token, arg->value.type = type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR; arg->value.str = strdup(token); - if (!arg->value.str) - die("malloc string"); + if (!arg->value.str) { + free_arg(arg); + show_error(error_str, "failed to allocate string filter arg"); + return NULL; + } break; case EVENT_ITEM: /* if it is a number, then convert it */ -- cgit v1.2.3 From 28942c87e5e907f591d77547203e86ad1089b499 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 9 Dec 2013 14:34:08 +0900 Subject: tools lib traceevent: Get rid of malloc_or_die() in pevent_filter_add_filter_str() Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386567251-22751-12-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 53e48eb112c3..a4d5bb23a110 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -1226,7 +1226,13 @@ int pevent_filter_add_filter_str(struct event_filter *filter, else len = strlen(filter_str); - this_event = malloc_or_die(len + 1); + this_event = malloc(len + 1); + if (this_event == NULL) { + show_error(error_str, "Memory allocation failure"); + /* This can only happen when events is NULL, but still */ + free_events(events); + return -1; + } memcpy(this_event, filter_str, len); this_event[len] = 0; -- cgit v1.2.3 From 7ef2e813476273ac9c9138f002d8f4cb28e5adad Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 9 Dec 2013 14:34:09 +0900 Subject: tools lib traceevent: Get rid of die() in pevent_filter_clear_trivial() Change the function signature to return error code and not call die() anymore. Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386567251-22751-13-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 2 +- tools/lib/traceevent/parse-filter.c | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 620c27a72960..6e23f197175f 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -860,7 +860,7 @@ int pevent_event_filtered(struct event_filter *filter, void pevent_filter_reset(struct event_filter *filter); -void pevent_filter_clear_trivial(struct event_filter *filter, +int pevent_filter_clear_trivial(struct event_filter *filter, enum filter_trivial_type type); void pevent_filter_free(struct event_filter *filter); diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index a4d5bb23a110..ab402fb2dcf7 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -1504,8 +1504,10 @@ int pevent_update_trivial(struct event_filter *dest, struct event_filter *source * @type: remove only true, false, or both * * Removes filters that only contain a TRUE or FALES boolean arg. + * + * Returns 0 on success and -1 if there was a problem. */ -void pevent_filter_clear_trivial(struct event_filter *filter, +int pevent_filter_clear_trivial(struct event_filter *filter, enum filter_trivial_type type) { struct filter_type *filter_type; @@ -1514,13 +1516,15 @@ void pevent_filter_clear_trivial(struct event_filter *filter, int i; if (!filter->filters) - return; + return 0; /* * Two steps, first get all ids with trivial filters. * then remove those ids. */ for (i = 0; i < filter->filters; i++) { + int *new_ids; + filter_type = &filter->event_filters[i]; if (filter_type->filter->type != FILTER_ARG_BOOLEAN) continue; @@ -1535,19 +1539,24 @@ void pevent_filter_clear_trivial(struct event_filter *filter, break; } - ids = realloc(ids, sizeof(*ids) * (count + 1)); - if (!ids) - die("Can't allocate ids"); + new_ids = realloc(ids, sizeof(*ids) * (count + 1)); + if (!new_ids) { + free(ids); + return -1; + } + + ids = new_ids; ids[count++] = filter_type->event_id; } if (!count) - return; + return 0; for (i = 0; i < count; i++) pevent_filter_remove_event(filter, ids[i]); free(ids); + return 0; } /** -- cgit v1.2.3 From c506c96b61fa96c9a52ad4d25e895e45c1692650 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 11 Dec 2013 09:15:00 -0300 Subject: tools lib symbol: Start carving out symbol parsing routines from perf Eventually this should be useful to other tools/ living utilities. For now don't try to build any .a, just trying the minimal approach of separating existing code into multiple .c files that can then be included wherever they are needed, using whatever build machinery already in place. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-pfa8i5zpf4bf9rcccryi0lt3@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/symbol/kallsyms.c | 58 +++++++++++++++++++++++++++++++++++++++++++++ tools/lib/symbol/kallsyms.h | 24 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 tools/lib/symbol/kallsyms.c create mode 100644 tools/lib/symbol/kallsyms.h (limited to 'tools/lib') diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c new file mode 100644 index 000000000000..18bc271a4bbc --- /dev/null +++ b/tools/lib/symbol/kallsyms.c @@ -0,0 +1,58 @@ +#include "symbol/kallsyms.h" +#include +#include + +int kallsyms__parse(const char *filename, void *arg, + int (*process_symbol)(void *arg, const char *name, + char type, u64 start)) +{ + char *line = NULL; + size_t n; + int err = -1; + FILE *file = fopen(filename, "r"); + + if (file == NULL) + goto out_failure; + + err = 0; + + while (!feof(file)) { + u64 start; + int line_len, len; + char symbol_type; + char *symbol_name; + + line_len = getline(&line, &n, file); + if (line_len < 0 || !line) + break; + + line[--line_len] = '\0'; /* \n */ + + len = hex2u64(line, &start); + + len++; + if (len + 2 >= line_len) + continue; + + symbol_type = line[len]; + len += 2; + symbol_name = line + len; + len = line_len - len; + + if (len >= KSYM_NAME_LEN) { + err = -1; + break; + } + + err = process_symbol(arg, symbol_name, symbol_type, start); + if (err) + break; + } + + free(line); + fclose(file); + return err; + +out_failure: + return -1; +} diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h new file mode 100644 index 000000000000..6084f5e18b3c --- /dev/null +++ b/tools/lib/symbol/kallsyms.h @@ -0,0 +1,24 @@ +#ifndef __TOOLS_KALLSYMS_H_ +#define __TOOLS_KALLSYMS_H_ 1 + +#include +#include +#include + +#ifndef KSYM_NAME_LEN +#define KSYM_NAME_LEN 256 +#endif + +static inline u8 kallsyms2elf_type(char type) +{ + if (type == 'W') + return STB_WEAK; + + return isupper(type) ? STB_GLOBAL : STB_LOCAL; +} + +int kallsyms__parse(const char *filename, void *arg, + int (*process_symbol)(void *arg, const char *name, + char type, u64 start)); + +#endif /* __TOOLS_KALLSYMS_H_ */ -- cgit v1.2.3 From 9451a2fd78c785445afe0f6966b2043c3ee187ca Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:04 +0900 Subject: tools lib traceevent: Get rid of malloc_or_die() in show_error() Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index ab402fb2dcf7..d4b0bac80dc8 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -56,7 +56,21 @@ static void show_error(char **error_str, const char *fmt, ...) index = pevent_get_input_buf_ptr(); len = input ? strlen(input) : 0; - error = malloc_or_die(MAX_ERR_STR_SIZE + (len*2) + 3); + error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3); + if (error == NULL) { + /* + * Maybe it's due to len is too long. + * Retry without the input buffer part. + */ + len = 0; + + error = malloc(MAX_ERR_STR_SIZE); + if (error == NULL) { + /* no memory */ + *error_str = NULL; + return; + } + } if (len) { strcpy(error, input); -- cgit v1.2.3 From ef3072cd1d5c2ea229f7abf8d6475e0c200eeb71 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:05 +0900 Subject: tools lib traceevent: Get rid of die in add_filter_type() The realloc() should check return value and not to overwrite previous pointer in case of error. Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index d4b0bac80dc8..767de4f1e8ee 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -161,11 +161,13 @@ add_filter_type(struct event_filter *filter, int id) if (filter_type) return filter_type; - filter->event_filters = realloc(filter->event_filters, - sizeof(*filter->event_filters) * - (filter->filters + 1)); - if (!filter->event_filters) - die("Could not allocate filter"); + filter_type = realloc(filter->event_filters, + sizeof(*filter->event_filters) * + (filter->filters + 1)); + if (!filter_type) + return NULL; + + filter->event_filters = filter_type; for (i = 0; i < filter->filters; i++) { if (filter->event_filters[i].event_id > id) @@ -1180,6 +1182,12 @@ static int filter_event(struct event_filter *filter, } filter_type = add_filter_type(filter, event->id); + if (filter_type == NULL) { + show_error(error_str, "failed to add a new filter: %s", + filter_str ? filter_str : "true"); + return -1; + } + if (filter_type->filter) free_arg(filter_type->filter); filter_type->filter = arg; @@ -1417,6 +1425,9 @@ static int copy_filter_type(struct event_filter *filter, arg->boolean.value = 0; filter_type = add_filter_type(filter, event->id); + if (filter_type == NULL) + return -1; + filter_type->filter = arg; free(str); -- cgit v1.2.3 From 2e4eb10d7e59df71ab649343b3f1bff9259da15d Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:06 +0900 Subject: tools lib traceevent: Get rid of malloc_or_die() allocate_arg() Also check return value and handle it. Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 48 ++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 767de4f1e8ee..ab9cefe320b4 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -211,12 +211,7 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent) static struct filter_arg *allocate_arg(void) { - struct filter_arg *arg; - - arg = malloc_or_die(sizeof(*arg)); - memset(arg, 0, sizeof(*arg)); - - return arg; + return calloc(1, sizeof(struct filter_arg)); } static void free_arg(struct filter_arg *arg) @@ -369,6 +364,10 @@ create_arg_item(struct event_format *event, const char *token, struct filter_arg *arg; arg = allocate_arg(); + if (arg == NULL) { + show_error(error_str, "failed to allocate filter arg"); + return NULL; + } switch (type) { @@ -422,6 +421,9 @@ create_arg_op(enum filter_op_type btype) struct filter_arg *arg; arg = allocate_arg(); + if (!arg) + return NULL; + arg->type = FILTER_ARG_OP; arg->op.type = btype; @@ -434,6 +436,9 @@ create_arg_exp(enum filter_exp_type etype) struct filter_arg *arg; arg = allocate_arg(); + if (!arg) + return NULL; + arg->type = FILTER_ARG_EXP; arg->op.type = etype; @@ -446,6 +451,9 @@ create_arg_cmp(enum filter_exp_type etype) struct filter_arg *arg; arg = allocate_arg(); + if (!arg) + return NULL; + /* Use NUM and change if necessary */ arg->type = FILTER_ARG_NUM; arg->op.type = etype; @@ -909,8 +917,10 @@ static struct filter_arg *collapse_tree(struct filter_arg *arg) case FILTER_VAL_FALSE: free_arg(arg); arg = allocate_arg(); - arg->type = FILTER_ARG_BOOLEAN; - arg->boolean.value = ret == FILTER_VAL_TRUE; + if (arg) { + arg->type = FILTER_ARG_BOOLEAN; + arg->boolean.value = ret == FILTER_VAL_TRUE; + } } return arg; @@ -1057,6 +1067,8 @@ process_filter(struct event_format *event, struct filter_arg **parg, switch (op_type) { case OP_BOOL: arg = create_arg_op(btype); + if (arg == NULL) + goto fail_alloc; if (current_op) ret = add_left(arg, current_op); else @@ -1067,6 +1079,8 @@ process_filter(struct event_format *event, struct filter_arg **parg, case OP_NOT: arg = create_arg_op(btype); + if (arg == NULL) + goto fail_alloc; if (current_op) ret = add_right(current_op, arg, error_str); if (ret < 0) @@ -1086,6 +1100,8 @@ process_filter(struct event_format *event, struct filter_arg **parg, arg = create_arg_exp(etype); else arg = create_arg_cmp(ctype); + if (arg == NULL) + goto fail_alloc; if (current_op) ret = add_right(current_op, arg, error_str); @@ -1119,11 +1135,16 @@ process_filter(struct event_format *event, struct filter_arg **parg, current_op = current_exp; current_op = collapse_tree(current_op); + if (current_op == NULL) + goto fail_alloc; *parg = current_op; return 0; + fail_alloc: + show_error(error_str, "failed to allocate filter arg"); + goto fail; fail_print: show_error(error_str, "Syntax error"); fail: @@ -1154,6 +1175,10 @@ process_event(struct event_format *event, const char *filter_str, /* If parg is NULL, then make it into FALSE */ if (!*parg) { *parg = allocate_arg(); + if (*parg == NULL) { + show_error(error_str, "failed to allocate filter arg"); + return -1; + } (*parg)->type = FILTER_ARG_BOOLEAN; (*parg)->boolean.value = FILTER_FALSE; } @@ -1177,6 +1202,10 @@ static int filter_event(struct event_filter *filter, } else { /* just add a TRUE arg */ arg = allocate_arg(); + if (arg == NULL) { + show_error(error_str, "failed to allocate filter arg"); + return -1; + } arg->type = FILTER_ARG_BOOLEAN; arg->boolean.value = FILTER_TRUE; } @@ -1418,6 +1447,9 @@ static int copy_filter_type(struct event_filter *filter, if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) { /* Add trivial event */ arg = allocate_arg(); + if (arg == NULL) + return -1; + arg->type = FILTER_ARG_BOOLEAN; if (strcmp(str, "TRUE") == 0) arg->boolean.value = 1; -- cgit v1.2.3 From 91dfa49bdd8ef9600d850ef68ec892eb70824e3d Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:07 +0900 Subject: tools lib traceevent: Get rid of malloc_or_die() in read_token() Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-5-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index ab9cefe320b4..246ee81e1f93 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -109,7 +109,11 @@ static enum event_type read_token(char **tok) (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && pevent_peek_char() == '~') { /* append it */ - *tok = malloc_or_die(3); + *tok = malloc(3); + if (*tok == NULL) { + free_token(token); + return EVENT_ERROR; + } sprintf(*tok, "%c%c", *token, '~'); free_token(token); /* Now remove the '~' from the buffer */ @@ -1123,6 +1127,8 @@ process_filter(struct event_format *event, struct filter_arg **parg, break; case EVENT_NONE: break; + case EVENT_ERROR: + goto fail_alloc; default: goto fail_print; } -- cgit v1.2.3 From 605b8fda958a578e0a50ed1df3cac5a12f1fe8dc Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:08 +0900 Subject: tools lib traceevent: Get rid of malloc_or_die() in find_event() Make it return pevent_errno to distinguish malloc allocation failure. Since it'll be returned to user later, add more error code. Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-6-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 4 +++- tools/lib/traceevent/parse-filter.c | 27 +++++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 6e23f197175f..abdfd3c606ed 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -356,7 +356,9 @@ enum pevent_flag { _PE(READ_FORMAT_FAILED, "failed to read event format"), \ _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ - _PE(INVALID_ARG_TYPE, "invalid argument type") + _PE(INVALID_ARG_TYPE, "invalid argument type"), \ + _PE(INVALID_EVENT_NAME, "invalid event name"), \ + _PE(EVENT_NOT_FOUND, "No event found") #undef _PE #define _PE(__code, __str) PEVENT_ERRNO__ ## __code diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 246ee81e1f93..a0ab040e8f71 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -287,7 +287,7 @@ static int event_match(struct event_format *event, !regexec(ereg, event->name, 0, NULL, 0); } -static int +static enum pevent_errno find_event(struct pevent *pevent, struct event_list **events, char *sys_name, char *event_name) { @@ -306,23 +306,31 @@ find_event(struct pevent *pevent, struct event_list **events, sys_name = NULL; } - reg = malloc_or_die(strlen(event_name) + 3); + reg = malloc(strlen(event_name) + 3); + if (reg == NULL) + return PEVENT_ERRNO__MEM_ALLOC_FAILED; + sprintf(reg, "^%s$", event_name); ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB); free(reg); if (ret) - return -1; + return PEVENT_ERRNO__INVALID_EVENT_NAME; if (sys_name) { - reg = malloc_or_die(strlen(sys_name) + 3); + reg = malloc(strlen(sys_name) + 3); + if (reg == NULL) { + regfree(&ereg); + return PEVENT_ERRNO__MEM_ALLOC_FAILED; + } + sprintf(reg, "^%s$", sys_name); ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB); free(reg); if (ret) { regfree(&ereg); - return -1; + return PEVENT_ERRNO__INVALID_EVENT_NAME; } } @@ -342,9 +350,9 @@ find_event(struct pevent *pevent, struct event_list **events, regfree(&sreg); if (!match) - return -1; + return PEVENT_ERRNO__EVENT_NOT_FOUND; if (fail) - return -2; + return PEVENT_ERRNO__MEM_ALLOC_FAILED; return 0; } @@ -1312,7 +1320,10 @@ int pevent_filter_add_filter_str(struct event_filter *filter, /* Find this event */ ret = find_event(pevent, &events, strim(sys_name), strim(event_name)); if (ret < 0) { - if (event_name) + if (ret == PEVENT_ERRNO__MEM_ALLOC_FAILED) + show_error(error_str, + "Memory allocation failure"); + else if (event_name) show_error(error_str, "No event found under '%s.%s'", sys_name, event_name); -- cgit v1.2.3 From 02d62d6d17b9b718be2878477cdcae95df0d5b4e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:09 +0900 Subject: tools lib traceevent: Get rid of die() in add_right() Refactor it to return appropriate pevent_errno value. Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-7-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 8 +++++++- tools/lib/traceevent/parse-filter.c | 34 +++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 16 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index abdfd3c606ed..89e4dfd40db6 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -358,7 +358,13 @@ enum pevent_flag { _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ _PE(INVALID_ARG_TYPE, "invalid argument type"), \ _PE(INVALID_EVENT_NAME, "invalid event name"), \ - _PE(EVENT_NOT_FOUND, "No event found") + _PE(EVENT_NOT_FOUND, "no event found"), \ + _PE(SYNTAX_ERROR, "syntax error"), \ + _PE(ILLEGAL_RVALUE, "illegal rvalue"), \ + _PE(ILLEGAL_LVALUE, "illegal lvalue for string comparison"), \ + _PE(INVALID_REGEX, "regex did not compute"), \ + _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"), \ + _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer") #undef _PE #define _PE(__code, __str) PEVENT_ERRNO__ ## __code diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index a0ab040e8f71..c08ce594cabe 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -473,8 +473,8 @@ create_arg_cmp(enum filter_exp_type etype) return arg; } -static int add_right(struct filter_arg *op, struct filter_arg *arg, - char **error_str) +static enum pevent_errno +add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str) { struct filter_arg *left; char *str; @@ -505,9 +505,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, case FILTER_ARG_FIELD: break; default: - show_error(error_str, - "Illegal rvalue"); - return -1; + show_error(error_str, "Illegal rvalue"); + return PEVENT_ERRNO__ILLEGAL_RVALUE; } /* @@ -554,7 +553,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, if (left->type != FILTER_ARG_FIELD) { show_error(error_str, "Illegal lvalue for string comparison"); - return -1; + return PEVENT_ERRNO__ILLEGAL_LVALUE; } /* Make sure this is a valid string compare */ @@ -573,25 +572,31 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, show_error(error_str, "RegEx '%s' did not compute", str); - return -1; + return PEVENT_ERRNO__INVALID_REGEX; } break; default: show_error(error_str, "Illegal comparison for string"); - return -1; + return PEVENT_ERRNO__ILLEGAL_STRING_CMP; } op->type = FILTER_ARG_STR; op->str.type = op_type; op->str.field = left->field.field; op->str.val = strdup(str); - if (!op->str.val) - die("malloc string"); + if (!op->str.val) { + show_error(error_str, "Failed to allocate string filter"); + return PEVENT_ERRNO__MEM_ALLOC_FAILED; + } /* * Need a buffer to copy data for tests */ - op->str.buffer = malloc_or_die(op->str.field->size + 1); + op->str.buffer = malloc(op->str.field->size + 1); + if (!op->str.buffer) { + show_error(error_str, "Failed to allocate string filter"); + return PEVENT_ERRNO__MEM_ALLOC_FAILED; + } /* Null terminate this buffer */ op->str.buffer[op->str.field->size] = 0; @@ -609,7 +614,7 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, case FILTER_CMP_NOT_REGEX: show_error(error_str, "Op not allowed with integers"); - return -1; + return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP; default: break; @@ -629,9 +634,8 @@ static int add_right(struct filter_arg *op, struct filter_arg *arg, return 0; out_fail: - show_error(error_str, - "Syntax error"); - return -1; + show_error(error_str, "Syntax error"); + return PEVENT_ERRNO__SYNTAX_ERROR; } static struct filter_arg * -- cgit v1.2.3 From ff533fc058975579dffbb62a731f63911ae714be Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:10 +0900 Subject: tools lib traceevent: Make add_left() return pevent_errno So that it can propagate error properly. Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-8-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index c08ce594cabe..774c3e4c1d9f 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -648,7 +648,7 @@ rotate_op_right(struct filter_arg *a, struct filter_arg *b) return arg; } -static int add_left(struct filter_arg *op, struct filter_arg *arg) +static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg) { switch (op->type) { case FILTER_ARG_EXP: @@ -667,11 +667,11 @@ static int add_left(struct filter_arg *op, struct filter_arg *arg) /* left arg of compares must be a field */ if (arg->type != FILTER_ARG_FIELD && arg->type != FILTER_ARG_BOOLEAN) - return -1; + return PEVENT_ERRNO__INVALID_ARG_TYPE; op->num.left = arg; break; default: - return -1; + return PEVENT_ERRNO__INVALID_ARG_TYPE; } return 0; } -- cgit v1.2.3 From 7bb73553e2490ac6667387ee723e0faa61e9d999 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:11 +0900 Subject: tools lib traceevent: Get rid of die() in reparent_op_arg() To do that, make the function returns the error code. Also pass error_str so that it can set proper error message when error occurred. Signed-off-by: Namhyung Kim Reviewed-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-9-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 5 +- tools/lib/traceevent/parse-filter.c | 94 +++++++++++++++++++++++-------------- 2 files changed, 64 insertions(+), 35 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 89e4dfd40db6..5e4392d8e2d4 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -364,7 +364,10 @@ enum pevent_flag { _PE(ILLEGAL_LVALUE, "illegal lvalue for string comparison"), \ _PE(INVALID_REGEX, "regex did not compute"), \ _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"), \ - _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer") + _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"), \ + _PE(REPARENT_NOT_OP, "cannot reparent other than OP"), \ + _PE(REPARENT_FAILED, "failed to reparent filter OP"), \ + _PE(BAD_FILTER_ARG, "bad arg in filter tree") #undef _PE #define _PE(__code, __str) PEVENT_ERRNO__ ## __code diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 774c3e4c1d9f..9b05892566e0 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -784,15 +784,18 @@ enum filter_vals { FILTER_VAL_TRUE, }; -void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, - struct filter_arg *arg) +static enum pevent_errno +reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, + struct filter_arg *arg, char **error_str) { struct filter_arg *other_child; struct filter_arg **ptr; if (parent->type != FILTER_ARG_OP && - arg->type != FILTER_ARG_OP) - die("can not reparent other than OP"); + arg->type != FILTER_ARG_OP) { + show_error(error_str, "can not reparent other than OP"); + return PEVENT_ERRNO__REPARENT_NOT_OP; + } /* Get the sibling */ if (old_child->op.right == arg) { @@ -801,8 +804,10 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, } else if (old_child->op.left == arg) { ptr = &old_child->op.left; other_child = old_child->op.right; - } else - die("Error in reparent op, find other child"); + } else { + show_error(error_str, "Error in reparent op, find other child"); + return PEVENT_ERRNO__REPARENT_FAILED; + } /* Detach arg from old_child */ *ptr = NULL; @@ -813,23 +818,29 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, *parent = *arg; /* Free arg without recussion */ free(arg); - return; + return 0; } if (parent->op.right == old_child) ptr = &parent->op.right; else if (parent->op.left == old_child) ptr = &parent->op.left; - else - die("Error in reparent op"); + else { + show_error(error_str, "Error in reparent op"); + return PEVENT_ERRNO__REPARENT_FAILED; + } + *ptr = arg; free_arg(old_child); + return 0; } -enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) +/* Returns either filter_vals (success) or pevent_errno (failfure) */ +static int test_arg(struct filter_arg *parent, struct filter_arg *arg, + char **error_str) { - enum filter_vals lval, rval; + int lval, rval; switch (arg->type) { @@ -844,63 +855,68 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) return FILTER_VAL_NORM; case FILTER_ARG_EXP: - lval = test_arg(arg, arg->exp.left); + lval = test_arg(arg, arg->exp.left, error_str); if (lval != FILTER_VAL_NORM) return lval; - rval = test_arg(arg, arg->exp.right); + rval = test_arg(arg, arg->exp.right, error_str); if (rval != FILTER_VAL_NORM) return rval; return FILTER_VAL_NORM; case FILTER_ARG_NUM: - lval = test_arg(arg, arg->num.left); + lval = test_arg(arg, arg->num.left, error_str); if (lval != FILTER_VAL_NORM) return lval; - rval = test_arg(arg, arg->num.right); + rval = test_arg(arg, arg->num.right, error_str); if (rval != FILTER_VAL_NORM) return rval; return FILTER_VAL_NORM; case FILTER_ARG_OP: if (arg->op.type != FILTER_OP_NOT) { - lval = test_arg(arg, arg->op.left); + lval = test_arg(arg, arg->op.left, error_str); switch (lval) { case FILTER_VAL_NORM: break; case FILTER_VAL_TRUE: if (arg->op.type == FILTER_OP_OR) return FILTER_VAL_TRUE; - rval = test_arg(arg, arg->op.right); + rval = test_arg(arg, arg->op.right, error_str); if (rval != FILTER_VAL_NORM) return rval; - reparent_op_arg(parent, arg, arg->op.right); - return FILTER_VAL_NORM; + return reparent_op_arg(parent, arg, arg->op.right, + error_str); case FILTER_VAL_FALSE: if (arg->op.type == FILTER_OP_AND) return FILTER_VAL_FALSE; - rval = test_arg(arg, arg->op.right); + rval = test_arg(arg, arg->op.right, error_str); if (rval != FILTER_VAL_NORM) return rval; - reparent_op_arg(parent, arg, arg->op.right); - return FILTER_VAL_NORM; + return reparent_op_arg(parent, arg, arg->op.right, + error_str); + + default: + return lval; } } - rval = test_arg(arg, arg->op.right); + rval = test_arg(arg, arg->op.right, error_str); switch (rval) { case FILTER_VAL_NORM: + default: break; + case FILTER_VAL_TRUE: if (arg->op.type == FILTER_OP_OR) return FILTER_VAL_TRUE; if (arg->op.type == FILTER_OP_NOT) return FILTER_VAL_FALSE; - reparent_op_arg(parent, arg, arg->op.left); - return FILTER_VAL_NORM; + return reparent_op_arg(parent, arg, arg->op.left, + error_str); case FILTER_VAL_FALSE: if (arg->op.type == FILTER_OP_AND) @@ -908,26 +924,27 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) if (arg->op.type == FILTER_OP_NOT) return FILTER_VAL_TRUE; - reparent_op_arg(parent, arg, arg->op.left); - return FILTER_VAL_NORM; + return reparent_op_arg(parent, arg, arg->op.left, + error_str); } - return FILTER_VAL_NORM; + return rval; default: - die("bad arg in filter tree"); + show_error(error_str, "bad arg in filter tree"); + return PEVENT_ERRNO__BAD_FILTER_ARG; } return FILTER_VAL_NORM; } /* Remove any unknown event fields */ -static struct filter_arg *collapse_tree(struct filter_arg *arg) +static struct filter_arg *collapse_tree(struct filter_arg *arg, char **error_str) { enum filter_vals ret; - ret = test_arg(arg, arg); + ret = test_arg(arg, arg, error_str); switch (ret) { case FILTER_VAL_NORM: - return arg; + break; case FILTER_VAL_TRUE: case FILTER_VAL_FALSE: @@ -936,7 +953,16 @@ static struct filter_arg *collapse_tree(struct filter_arg *arg) if (arg) { arg->type = FILTER_ARG_BOOLEAN; arg->boolean.value = ret == FILTER_VAL_TRUE; + } else { + show_error(error_str, "Failed to allocate filter arg"); } + break; + + default: + /* test_arg() already set the error_str */ + free_arg(arg); + arg = NULL; + break; } return arg; @@ -1152,9 +1178,9 @@ process_filter(struct event_format *event, struct filter_arg **parg, if (!current_op) current_op = current_exp; - current_op = collapse_tree(current_op); + current_op = collapse_tree(current_op, error_str); if (current_op == NULL) - goto fail_alloc; + goto fail; *parg = current_op; -- cgit v1.2.3 From c8ea690dd0d1385a766d68c51832497181e013b8 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:12 +0900 Subject: tools lib traceevent: Refactor create_arg_item() So that it can return a proper pevent_errno value. Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-10-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 3 ++- tools/lib/traceevent/parse-filter.c | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 5e4392d8e2d4..57b66aed8122 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -367,7 +367,8 @@ enum pevent_flag { _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"), \ _PE(REPARENT_NOT_OP, "cannot reparent other than OP"), \ _PE(REPARENT_FAILED, "failed to reparent filter OP"), \ - _PE(BAD_FILTER_ARG, "bad arg in filter tree") + _PE(BAD_FILTER_ARG, "bad arg in filter tree"), \ + _PE(UNEXPECTED_TYPE, "unexpected type (not a value)") #undef _PE #define _PE(__code, __str) PEVENT_ERRNO__ ## __code diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 9b05892566e0..8d71208f0131 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -368,9 +368,9 @@ static void free_events(struct event_list *events) } } -static struct filter_arg * +static enum pevent_errno create_arg_item(struct event_format *event, const char *token, - enum event_type type, char **error_str) + enum event_type type, struct filter_arg **parg, char **error_str) { struct format_field *field; struct filter_arg *arg; @@ -378,7 +378,7 @@ create_arg_item(struct event_format *event, const char *token, arg = allocate_arg(); if (arg == NULL) { show_error(error_str, "failed to allocate filter arg"); - return NULL; + return PEVENT_ERRNO__MEM_ALLOC_FAILED; } switch (type) { @@ -392,7 +392,7 @@ create_arg_item(struct event_format *event, const char *token, if (!arg->value.str) { free_arg(arg); show_error(error_str, "failed to allocate string filter arg"); - return NULL; + return PEVENT_ERRNO__MEM_ALLOC_FAILED; } break; case EVENT_ITEM: @@ -420,11 +420,11 @@ create_arg_item(struct event_format *event, const char *token, break; default: free_arg(arg); - show_error(error_str, "expected a value but found %s", - token); - return NULL; + show_error(error_str, "expected a value but found %s", token); + return PEVENT_ERRNO__UNEXPECTED_TYPE; } - return arg; + *parg = arg; + return 0; } static struct filter_arg * @@ -993,8 +993,8 @@ process_filter(struct event_format *event, struct filter_arg **parg, case EVENT_SQUOTE: case EVENT_DQUOTE: case EVENT_ITEM: - arg = create_arg_item(event, token, type, error_str); - if (!arg) + ret = create_arg_item(event, token, type, &arg, error_str); + if (ret < 0) goto fail; if (!left_item) left_item = arg; -- cgit v1.2.3 From 42d6194d133cbaf12f34cbdc4111bd8f7dc0ed2a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:13 +0900 Subject: tools lib traceevent: Refactor process_filter() So that it can return a proper pevent_errno value. Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-11-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 6 +++- tools/lib/traceevent/parse-filter.c | 64 +++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 28 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 57b66aed8122..da942d59cc3a 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -368,7 +368,11 @@ enum pevent_flag { _PE(REPARENT_NOT_OP, "cannot reparent other than OP"), \ _PE(REPARENT_FAILED, "failed to reparent filter OP"), \ _PE(BAD_FILTER_ARG, "bad arg in filter tree"), \ - _PE(UNEXPECTED_TYPE, "unexpected type (not a value)") + _PE(UNEXPECTED_TYPE, "unexpected type (not a value)"), \ + _PE(ILLEGAL_TOKEN, "illegal token"), \ + _PE(INVALID_PAREN, "open parenthesis cannot come here"), \ + _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ + _PE(UNKNOWN_TOKEN, "unknown token") #undef _PE #define _PE(__code, __str) PEVENT_ERRNO__ ## __code diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 8d71208f0131..5aa5012a17ee 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -937,9 +937,10 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, } /* Remove any unknown event fields */ -static struct filter_arg *collapse_tree(struct filter_arg *arg, char **error_str) +static int collapse_tree(struct filter_arg *arg, + struct filter_arg **arg_collapsed, char **error_str) { - enum filter_vals ret; + int ret; ret = test_arg(arg, arg, error_str); switch (ret) { @@ -955,6 +956,7 @@ static struct filter_arg *collapse_tree(struct filter_arg *arg, char **error_str arg->boolean.value = ret == FILTER_VAL_TRUE; } else { show_error(error_str, "Failed to allocate filter arg"); + ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; } break; @@ -965,10 +967,11 @@ static struct filter_arg *collapse_tree(struct filter_arg *arg, char **error_str break; } - return arg; + *arg_collapsed = arg; + return ret; } -static int +static enum pevent_errno process_filter(struct event_format *event, struct filter_arg **parg, char **error_str, int not) { @@ -982,7 +985,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, enum filter_op_type btype; enum filter_exp_type etype; enum filter_cmp_type ctype; - int ret; + enum pevent_errno ret; *parg = NULL; @@ -1007,20 +1010,20 @@ process_filter(struct event_format *event, struct filter_arg **parg, if (not) { arg = NULL; if (current_op) - goto fail_print; + goto fail_syntax; free(token); *parg = current_exp; return 0; } } else - goto fail_print; + goto fail_syntax; arg = NULL; break; case EVENT_DELIM: if (*token == ',') { - show_error(error_str, - "Illegal token ','"); + show_error(error_str, "Illegal token ','"); + ret = PEVENT_ERRNO__ILLEGAL_TOKEN; goto fail; } @@ -1028,19 +1031,23 @@ process_filter(struct event_format *event, struct filter_arg **parg, if (left_item) { show_error(error_str, "Open paren can not come after item"); + ret = PEVENT_ERRNO__INVALID_PAREN; goto fail; } if (current_exp) { show_error(error_str, "Open paren can not come after expression"); + ret = PEVENT_ERRNO__INVALID_PAREN; goto fail; } ret = process_filter(event, &arg, error_str, 0); - if (ret != 1) { - if (ret == 0) + if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) { + if (ret == 0) { show_error(error_str, "Unbalanced number of '('"); + ret = PEVENT_ERRNO__UNBALANCED_PAREN; + } goto fail; } ret = 0; @@ -1048,7 +1055,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, /* A not wants just one expression */ if (not) { if (current_op) - goto fail_print; + goto fail_syntax; *parg = arg; return 0; } @@ -1063,19 +1070,19 @@ process_filter(struct event_format *event, struct filter_arg **parg, } else { /* ')' */ if (!current_op && !current_exp) - goto fail_print; + goto fail_syntax; /* Make sure everything is finished at this level */ if (current_exp && !check_op_done(current_exp)) - goto fail_print; + goto fail_syntax; if (current_op && !check_op_done(current_op)) - goto fail_print; + goto fail_syntax; if (current_op) *parg = current_op; else *parg = current_exp; - return 1; + return PEVENT_ERRNO__UNBALANCED_PAREN; } break; @@ -1087,21 +1094,22 @@ process_filter(struct event_format *event, struct filter_arg **parg, case OP_BOOL: /* Logic ops need a left expression */ if (!current_exp && !current_op) - goto fail_print; + goto fail_syntax; /* fall through */ case OP_NOT: /* logic only processes ops and exp */ if (left_item) - goto fail_print; + goto fail_syntax; break; case OP_EXP: case OP_CMP: if (!left_item) - goto fail_print; + goto fail_syntax; break; case OP_NONE: show_error(error_str, "Unknown op token %s", token); + ret = PEVENT_ERRNO__UNKNOWN_TOKEN; goto fail; } @@ -1152,7 +1160,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, ret = add_left(arg, left_item); if (ret < 0) { arg = NULL; - goto fail_print; + goto fail_syntax; } current_exp = arg; break; @@ -1161,25 +1169,25 @@ process_filter(struct event_format *event, struct filter_arg **parg, } arg = NULL; if (ret < 0) - goto fail_print; + goto fail_syntax; break; case EVENT_NONE: break; case EVENT_ERROR: goto fail_alloc; default: - goto fail_print; + goto fail_syntax; } } while (type != EVENT_NONE); if (!current_op && !current_exp) - goto fail_print; + goto fail_syntax; if (!current_op) current_op = current_exp; - current_op = collapse_tree(current_op, error_str); - if (current_op == NULL) + ret = collapse_tree(current_op, parg, error_str); + if (ret < 0) goto fail; *parg = current_op; @@ -1188,15 +1196,17 @@ process_filter(struct event_format *event, struct filter_arg **parg, fail_alloc: show_error(error_str, "failed to allocate filter arg"); + ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; goto fail; - fail_print: + fail_syntax: show_error(error_str, "Syntax error"); + ret = PEVENT_ERRNO__SYNTAX_ERROR; fail: free_arg(current_op); free_arg(current_exp); free_arg(arg); free(token); - return -1; + return ret; } static int -- cgit v1.2.3 From 69c770a690422c6cdc4ea52d9edbba7c20cd1aff Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:14 +0900 Subject: tools lib traceevent: Make pevent_filter_add_filter_str() return pevent_errno Refactor the pevent_filter_add_filter_str() to return a proper error code and get rid of the third error_str argument. Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-12-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 8 ++-- tools/lib/traceevent/parse-filter.c | 78 +++++++++++-------------------------- 2 files changed, 27 insertions(+), 59 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index da942d59cc3a..089964e56ed4 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -372,7 +372,8 @@ enum pevent_flag { _PE(ILLEGAL_TOKEN, "illegal token"), \ _PE(INVALID_PAREN, "open parenthesis cannot come here"), \ _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ - _PE(UNKNOWN_TOKEN, "unknown token") + _PE(UNKNOWN_TOKEN, "unknown token"), \ + _PE(FILTER_NOT_FOUND, "no filter found") #undef _PE #define _PE(__code, __str) PEVENT_ERRNO__ ## __code @@ -863,9 +864,8 @@ enum filter_trivial_type { FILTER_TRIVIAL_BOTH, }; -int pevent_filter_add_filter_str(struct event_filter *filter, - const char *filter_str, - char **error_str); +enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, + const char *filter_str); int pevent_filter_match(struct event_filter *filter, diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 5aa5012a17ee..78440d73e0ad 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -1209,7 +1209,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, return ret; } -static int +static enum pevent_errno process_event(struct event_format *event, const char *filter_str, struct filter_arg **parg, char **error_str) { @@ -1218,21 +1218,15 @@ process_event(struct event_format *event, const char *filter_str, pevent_buffer_init(filter_str, strlen(filter_str)); ret = process_filter(event, parg, error_str, 0); - if (ret == 1) { - show_error(error_str, - "Unbalanced number of ')'"); - return -1; - } if (ret < 0) return ret; /* If parg is NULL, then make it into FALSE */ if (!*parg) { *parg = allocate_arg(); - if (*parg == NULL) { - show_error(error_str, "failed to allocate filter arg"); - return -1; - } + if (*parg == NULL) + return PEVENT_ERRNO__MEM_ALLOC_FAILED; + (*parg)->type = FILTER_ARG_BOOLEAN; (*parg)->boolean.value = FILTER_FALSE; } @@ -1240,13 +1234,13 @@ process_event(struct event_format *event, const char *filter_str, return 0; } -static int filter_event(struct event_filter *filter, - struct event_format *event, - const char *filter_str, char **error_str) +static enum pevent_errno +filter_event(struct event_filter *filter, struct event_format *event, + const char *filter_str, char **error_str) { struct filter_type *filter_type; struct filter_arg *arg; - int ret; + enum pevent_errno ret; if (filter_str) { ret = process_event(event, filter_str, &arg, error_str); @@ -1256,20 +1250,16 @@ static int filter_event(struct event_filter *filter, } else { /* just add a TRUE arg */ arg = allocate_arg(); - if (arg == NULL) { - show_error(error_str, "failed to allocate filter arg"); - return -1; - } + if (arg == NULL) + return PEVENT_ERRNO__MEM_ALLOC_FAILED; + arg->type = FILTER_ARG_BOOLEAN; arg->boolean.value = FILTER_TRUE; } filter_type = add_filter_type(filter, event->id); - if (filter_type == NULL) { - show_error(error_str, "failed to add a new filter: %s", - filter_str ? filter_str : "true"); - return -1; - } + if (filter_type == NULL) + return PEVENT_ERRNO__MEM_ALLOC_FAILED; if (filter_type->filter) free_arg(filter_type->filter); @@ -1282,18 +1272,12 @@ static int filter_event(struct event_filter *filter, * pevent_filter_add_filter_str - add a new filter * @filter: the event filter to add to * @filter_str: the filter string that contains the filter - * @error_str: string containing reason for failed filter - * - * Returns 0 if the filter was successfully added - * -1 if there was an error. * - * On error, if @error_str points to a string pointer, - * it is set to the reason that the filter failed. - * This string must be freed with "free". + * Returns 0 if the filter was successfully added or a + * negative error code. */ -int pevent_filter_add_filter_str(struct event_filter *filter, - const char *filter_str, - char **error_str) +enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, + const char *filter_str) { struct pevent *pevent = filter->pevent; struct event_list *event; @@ -1304,23 +1288,20 @@ int pevent_filter_add_filter_str(struct event_filter *filter, char *event_name = NULL; char *sys_name = NULL; char *sp; - int rtn = 0; + enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */ int len; int ret; + char *error_str = NULL; /* clear buffer to reset show error */ pevent_buffer_init("", 0); - if (error_str) - *error_str = NULL; - filter_start = strchr(filter_str, ':'); if (filter_start) len = filter_start - filter_str; else len = strlen(filter_str); - do { next_event = strchr(filter_str, ','); if (next_event && @@ -1333,10 +1314,9 @@ int pevent_filter_add_filter_str(struct event_filter *filter, this_event = malloc(len + 1); if (this_event == NULL) { - show_error(error_str, "Memory allocation failure"); /* This can only happen when events is NULL, but still */ free_events(events); - return -1; + return PEVENT_ERRNO__MEM_ALLOC_FAILED; } memcpy(this_event, filter_str, len); this_event[len] = 0; @@ -1350,30 +1330,18 @@ int pevent_filter_add_filter_str(struct event_filter *filter, event_name = strtok_r(NULL, "/", &sp); if (!sys_name) { - show_error(error_str, "No filter found"); /* This can only happen when events is NULL, but still */ free_events(events); free(this_event); - return -1; + return PEVENT_ERRNO__FILTER_NOT_FOUND; } /* Find this event */ ret = find_event(pevent, &events, strim(sys_name), strim(event_name)); if (ret < 0) { - if (ret == PEVENT_ERRNO__MEM_ALLOC_FAILED) - show_error(error_str, - "Memory allocation failure"); - else if (event_name) - show_error(error_str, - "No event found under '%s.%s'", - sys_name, event_name); - else - show_error(error_str, - "No event found under '%s'", - sys_name); free_events(events); free(this_event); - return -1; + return ret; } free(this_event); } while (filter_str); @@ -1385,7 +1353,7 @@ int pevent_filter_add_filter_str(struct event_filter *filter, /* filter starts here */ for (event = events; event; event = event->next) { ret = filter_event(filter, event->event, filter_start, - error_str); + &error_str); /* Failures are returned if a parse error happened */ if (ret < 0) rtn = ret; -- cgit v1.2.3 From 41e12e580a7b0c151199f927193548b84d3e874c Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:15 +0900 Subject: tools lib traceevent: Refactor pevent_filter_match() to get rid of die() The test_filter() function is for testing given filter is matched to a given record. However it doesn't handle error cases properly so add a new argument err to save error info during the test and also pass it to internal test functions. The return value of pevent_filter_match() also converted to pevent_errno to indicate an exact error case. Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-13-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 21 ++++-- tools/lib/traceevent/parse-filter.c | 135 +++++++++++++++++++++++------------- 2 files changed, 99 insertions(+), 57 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 089964e56ed4..3ad784f5f647 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -357,6 +357,8 @@ enum pevent_flag { _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ _PE(INVALID_ARG_TYPE, "invalid argument type"), \ + _PE(INVALID_EXP_TYPE, "invalid expression type"), \ + _PE(INVALID_OP_TYPE, "invalid operator type"), \ _PE(INVALID_EVENT_NAME, "invalid event name"), \ _PE(EVENT_NOT_FOUND, "no event found"), \ _PE(SYNTAX_ERROR, "syntax error"), \ @@ -373,12 +375,16 @@ enum pevent_flag { _PE(INVALID_PAREN, "open parenthesis cannot come here"), \ _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ _PE(UNKNOWN_TOKEN, "unknown token"), \ - _PE(FILTER_NOT_FOUND, "no filter found") + _PE(FILTER_NOT_FOUND, "no filter found"), \ + _PE(NOT_A_NUMBER, "must have number field"), \ + _PE(NO_FILTER, "no filters exists"), \ + _PE(FILTER_MISS, "record does not match to filter") #undef _PE #define _PE(__code, __str) PEVENT_ERRNO__ ## __code enum pevent_errno { PEVENT_ERRNO__SUCCESS = 0, + PEVENT_ERRNO__FILTER_MATCH = PEVENT_ERRNO__SUCCESS, /* * Choose an arbitrary negative big number not to clash with standard @@ -853,10 +859,11 @@ struct event_filter { struct event_filter *pevent_filter_alloc(struct pevent *pevent); -#define FILTER_NONE -2 -#define FILTER_NOEXIST -1 -#define FILTER_MISS 0 -#define FILTER_MATCH 1 +/* for backward compatibility */ +#define FILTER_NONE PEVENT_ERRNO__FILTER_NOT_FOUND +#define FILTER_NOEXIST PEVENT_ERRNO__NO_FILTER +#define FILTER_MISS PEVENT_ERRNO__FILTER_MISS +#define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH enum filter_trivial_type { FILTER_TRIVIAL_FALSE, @@ -868,8 +875,8 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, const char *filter_str); -int pevent_filter_match(struct event_filter *filter, - struct pevent_record *record); +enum pevent_errno pevent_filter_match(struct event_filter *filter, + struct pevent_record *record); int pevent_event_filtered(struct event_filter *filter, int event_id); diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 78440d73e0ad..9303c55128db 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -1678,8 +1678,8 @@ int pevent_filter_event_has_trivial(struct event_filter *filter, } } -static int test_filter(struct event_format *event, - struct filter_arg *arg, struct pevent_record *record); +static int test_filter(struct event_format *event, struct filter_arg *arg, + struct pevent_record *record, enum pevent_errno *err); static const char * get_comm(struct event_format *event, struct pevent_record *record) @@ -1725,15 +1725,24 @@ get_value(struct event_format *event, } static unsigned long long -get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record); +get_arg_value(struct event_format *event, struct filter_arg *arg, + struct pevent_record *record, enum pevent_errno *err); static unsigned long long -get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) +get_exp_value(struct event_format *event, struct filter_arg *arg, + struct pevent_record *record, enum pevent_errno *err) { unsigned long long lval, rval; - lval = get_arg_value(event, arg->exp.left, record); - rval = get_arg_value(event, arg->exp.right, record); + lval = get_arg_value(event, arg->exp.left, record, err); + rval = get_arg_value(event, arg->exp.right, record, err); + + if (*err) { + /* + * There was an error, no need to process anymore. + */ + return 0; + } switch (arg->exp.type) { case FILTER_EXP_ADD: @@ -1768,39 +1777,51 @@ get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_ case FILTER_EXP_NOT: default: - die("error in exp"); + if (!*err) + *err = PEVENT_ERRNO__INVALID_EXP_TYPE; } return 0; } static unsigned long long -get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) +get_arg_value(struct event_format *event, struct filter_arg *arg, + struct pevent_record *record, enum pevent_errno *err) { switch (arg->type) { case FILTER_ARG_FIELD: return get_value(event, arg->field.field, record); case FILTER_ARG_VALUE: - if (arg->value.type != FILTER_NUMBER) - die("must have number field!"); + if (arg->value.type != FILTER_NUMBER) { + if (!*err) + *err = PEVENT_ERRNO__NOT_A_NUMBER; + } return arg->value.val; case FILTER_ARG_EXP: - return get_exp_value(event, arg, record); + return get_exp_value(event, arg, record, err); default: - die("oops in filter"); + if (!*err) + *err = PEVENT_ERRNO__INVALID_ARG_TYPE; } return 0; } -static int test_num(struct event_format *event, - struct filter_arg *arg, struct pevent_record *record) +static int test_num(struct event_format *event, struct filter_arg *arg, + struct pevent_record *record, enum pevent_errno *err) { unsigned long long lval, rval; - lval = get_arg_value(event, arg->num.left, record); - rval = get_arg_value(event, arg->num.right, record); + lval = get_arg_value(event, arg->num.left, record, err); + rval = get_arg_value(event, arg->num.right, record, err); + + if (*err) { + /* + * There was an error, no need to process anymore. + */ + return 0; + } switch (arg->num.type) { case FILTER_CMP_EQ: @@ -1822,7 +1843,8 @@ static int test_num(struct event_format *event, return lval <= rval; default: - /* ?? */ + if (!*err) + *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP; return 0; } } @@ -1869,8 +1891,8 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r return val; } -static int test_str(struct event_format *event, - struct filter_arg *arg, struct pevent_record *record) +static int test_str(struct event_format *event, struct filter_arg *arg, + struct pevent_record *record, enum pevent_errno *err) { const char *val; @@ -1894,48 +1916,57 @@ static int test_str(struct event_format *event, return regexec(&arg->str.reg, val, 0, NULL, 0); default: - /* ?? */ + if (!*err) + *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP; return 0; } } -static int test_op(struct event_format *event, - struct filter_arg *arg, struct pevent_record *record) +static int test_op(struct event_format *event, struct filter_arg *arg, + struct pevent_record *record, enum pevent_errno *err) { switch (arg->op.type) { case FILTER_OP_AND: - return test_filter(event, arg->op.left, record) && - test_filter(event, arg->op.right, record); + return test_filter(event, arg->op.left, record, err) && + test_filter(event, arg->op.right, record, err); case FILTER_OP_OR: - return test_filter(event, arg->op.left, record) || - test_filter(event, arg->op.right, record); + return test_filter(event, arg->op.left, record, err) || + test_filter(event, arg->op.right, record, err); case FILTER_OP_NOT: - return !test_filter(event, arg->op.right, record); + return !test_filter(event, arg->op.right, record, err); default: - /* ?? */ + if (!*err) + *err = PEVENT_ERRNO__INVALID_OP_TYPE; return 0; } } -static int test_filter(struct event_format *event, - struct filter_arg *arg, struct pevent_record *record) +static int test_filter(struct event_format *event, struct filter_arg *arg, + struct pevent_record *record, enum pevent_errno *err) { + if (*err) { + /* + * There was an error, no need to process anymore. + */ + return 0; + } + switch (arg->type) { case FILTER_ARG_BOOLEAN: /* easy case */ return arg->boolean.value; case FILTER_ARG_OP: - return test_op(event, arg, record); + return test_op(event, arg, record, err); case FILTER_ARG_NUM: - return test_num(event, arg, record); + return test_num(event, arg, record, err); case FILTER_ARG_STR: - return test_str(event, arg, record); + return test_str(event, arg, record, err); case FILTER_ARG_EXP: case FILTER_ARG_VALUE: @@ -1944,11 +1975,11 @@ static int test_filter(struct event_format *event, * Expressions, fields and values evaluate * to true if they return non zero */ - return !!get_arg_value(event, arg, record); + return !!get_arg_value(event, arg, record, err); default: - die("oops!"); - /* ?? */ + if (!*err) + *err = PEVENT_ERRNO__INVALID_ARG_TYPE; return 0; } } @@ -1961,8 +1992,7 @@ static int test_filter(struct event_format *event, * Returns 1 if filter found for @event_id * otherwise 0; */ -int pevent_event_filtered(struct event_filter *filter, - int event_id) +int pevent_event_filtered(struct event_filter *filter, int event_id) { struct filter_type *filter_type; @@ -1979,31 +2009,36 @@ int pevent_event_filtered(struct event_filter *filter, * @filter: filter struct with filter information * @record: the record to test against the filter * - * Returns: - * 1 - filter found for event and @record matches - * 0 - filter found for event and @record does not match - * -1 - no filter found for @record's event - * -2 - if no filters exist + * Returns: match result or error code (prefixed with PEVENT_ERRNO__) + * FILTER_MATCH - filter found for event and @record matches + * FILTER_MISS - filter found for event and @record does not match + * FILTER_NOT_FOUND - no filter found for @record's event + * NO_FILTER - if no filters exist + * otherwise - error occurred during test */ -int pevent_filter_match(struct event_filter *filter, - struct pevent_record *record) +enum pevent_errno pevent_filter_match(struct event_filter *filter, + struct pevent_record *record) { struct pevent *pevent = filter->pevent; struct filter_type *filter_type; int event_id; + int ret; + enum pevent_errno err = 0; if (!filter->filters) - return FILTER_NONE; + return PEVENT_ERRNO__NO_FILTER; event_id = pevent_data_type(pevent, record); filter_type = find_filter_type(filter, event_id); - if (!filter_type) - return FILTER_NOEXIST; + return PEVENT_ERRNO__FILTER_NOT_FOUND; + + ret = test_filter(filter_type->event, filter_type->filter, record, &err); + if (err) + return err; - return test_filter(filter_type->event, filter_type->filter, record) ? - FILTER_MATCH : FILTER_MISS; + return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS; } static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) -- cgit v1.2.3 From 553873e1df63a20559ac9c336765dc7055cfc3d4 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 9 Dec 2013 17:14:23 +0100 Subject: tools/: Convert to new topic libraries Move debugfs.* to api/fs/. We have a common tools/lib/api/ place where the Makefile lives and then we place the headers in subdirs. For example, all the fs-related stuff goes to tools/lib/api/fs/ from which we get libapikfs.a (acme got almost the naming he wanted :-)) and we link it into the tools which need it - in this case perf and tools/vm/page-types. acme: "Looking at the implementation, I think some tools can even link directly to the .o files, avoiding the .a file altogether. But that is just an optimization/finer granularity tools/lib/ cherrypicking that toolers can make use of." Fixup documentation cleaning target while at it. Signed-off-by: Borislav Petkov Acked-by: Ingo Molnar Cc: Adrian Hunter Cc: Andi Kleen Cc: Arjan van de Ven Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Cc: Robert Richter Cc: Stanislav Fomichev Cc: Stephane Eranian Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386605664-24041-2-git-send-email-bp@alien8.de Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/api/Makefile | 42 +++++++++++++++++++ tools/lib/api/fs/debugfs.c | 100 +++++++++++++++++++++++++++++++++++++++++++++ tools/lib/api/fs/debugfs.h | 29 +++++++++++++ tools/lib/lk/Makefile | 38 ----------------- tools/lib/lk/debugfs.c | 100 --------------------------------------------- tools/lib/lk/debugfs.h | 29 ------------- 6 files changed, 171 insertions(+), 167 deletions(-) create mode 100644 tools/lib/api/Makefile create mode 100644 tools/lib/api/fs/debugfs.c create mode 100644 tools/lib/api/fs/debugfs.h delete mode 100644 tools/lib/lk/Makefile delete mode 100644 tools/lib/lk/debugfs.c delete mode 100644 tools/lib/lk/debugfs.h (limited to 'tools/lib') diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile new file mode 100644 index 000000000000..ed2f51e11b80 --- /dev/null +++ b/tools/lib/api/Makefile @@ -0,0 +1,42 @@ +include ../../scripts/Makefile.include +include ../../perf/config/utilities.mak # QUIET_CLEAN + +CC = $(CROSS_COMPILE)gcc +AR = $(CROSS_COMPILE)ar + +# guard against environment variables +LIB_H= +LIB_OBJS= + +LIB_H += fs/debugfs.h + +LIB_OBJS += $(OUTPUT)fs/debugfs.o + +LIBFILE = libapikfs.a + +CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC +EXTLIBS = -lelf -lpthread -lrt -lm +ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 +ALL_LDFLAGS = $(LDFLAGS) + +RM = rm -f + +$(LIBFILE): $(LIB_OBJS) + $(QUIET_AR)$(RM) $@ && $(AR) rcs $(OUTPUT)$@ $(LIB_OBJS) + +$(LIB_OBJS): $(LIB_H) + +libapi_dirs: + $(QUIET_MKDIR)mkdir -p $(OUTPUT)fs/ + +$(OUTPUT)%.o: %.c libapi_dirs + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< +$(OUTPUT)%.s: %.c libapi_dirs + $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< +$(OUTPUT)%.o: %.S libapi_dirs + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< + +clean: + $(call QUIET_CLEAN, libapi) $(RM) $(LIB_OBJS) $(LIBFILE) + +.PHONY: clean diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c new file mode 100644 index 000000000000..7c4347962353 --- /dev/null +++ b/tools/lib/api/fs/debugfs.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debugfs.h" + +char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug"; + +static const char * const debugfs_known_mountpoints[] = { + "/sys/kernel/debug/", + "/debug/", + 0, +}; + +static bool debugfs_found; + +/* find the path to the mounted debugfs */ +const char *debugfs_find_mountpoint(void) +{ + const char * const *ptr; + char type[100]; + FILE *fp; + + if (debugfs_found) + return (const char *)debugfs_mountpoint; + + ptr = debugfs_known_mountpoints; + while (*ptr) { + if (debugfs_valid_mountpoint(*ptr) == 0) { + debugfs_found = true; + strcpy(debugfs_mountpoint, *ptr); + return debugfs_mountpoint; + } + ptr++; + } + + /* give up and parse /proc/mounts */ + fp = fopen("/proc/mounts", "r"); + if (fp == NULL) + return NULL; + + while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n", + debugfs_mountpoint, type) == 2) { + if (strcmp(type, "debugfs") == 0) + break; + } + fclose(fp); + + if (strcmp(type, "debugfs") != 0) + return NULL; + + debugfs_found = true; + + return debugfs_mountpoint; +} + +/* verify that a mountpoint is actually a debugfs instance */ + +int debugfs_valid_mountpoint(const char *debugfs) +{ + struct statfs st_fs; + + if (statfs(debugfs, &st_fs) < 0) + return -ENOENT; + else if (st_fs.f_type != (long) DEBUGFS_MAGIC) + return -ENOENT; + + return 0; +} + +/* mount the debugfs somewhere if it's not mounted */ +char *debugfs_mount(const char *mountpoint) +{ + /* see if it's already mounted */ + if (debugfs_find_mountpoint()) + goto out; + + /* if not mounted and no argument */ + if (mountpoint == NULL) { + /* see if environment variable set */ + mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT); + /* if no environment variable, use default */ + if (mountpoint == NULL) + mountpoint = "/sys/kernel/debug"; + } + + if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0) + return NULL; + + /* save the mountpoint */ + debugfs_found = true; + strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint)); +out: + return debugfs_mountpoint; +} diff --git a/tools/lib/api/fs/debugfs.h b/tools/lib/api/fs/debugfs.h new file mode 100644 index 000000000000..f19d3df9609d --- /dev/null +++ b/tools/lib/api/fs/debugfs.h @@ -0,0 +1,29 @@ +#ifndef __API_DEBUGFS_H__ +#define __API_DEBUGFS_H__ + +#define _STR(x) #x +#define STR(x) _STR(x) + +/* + * On most systems would have given us this, but not on some systems + * (e.g. GNU/Hurd). + */ +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +#ifndef DEBUGFS_MAGIC +#define DEBUGFS_MAGIC 0x64626720 +#endif + +#ifndef PERF_DEBUGFS_ENVIRONMENT +#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" +#endif + +const char *debugfs_find_mountpoint(void); +int debugfs_valid_mountpoint(const char *debugfs); +char *debugfs_mount(const char *mountpoint); + +extern char debugfs_mountpoint[]; + +#endif /* __API_DEBUGFS_H__ */ diff --git a/tools/lib/lk/Makefile b/tools/lib/lk/Makefile deleted file mode 100644 index 3dba0a4aebbf..000000000000 --- a/tools/lib/lk/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -include ../../scripts/Makefile.include - -CC = $(CROSS_COMPILE)gcc -AR = $(CROSS_COMPILE)ar - -# guard against environment variables -LIB_H= -LIB_OBJS= - -LIB_H += debugfs.h - -LIB_OBJS += $(OUTPUT)debugfs.o - -LIBFILE = liblk.a - -CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC -EXTLIBS = -lelf -lpthread -lrt -lm -ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ALL_LDFLAGS = $(LDFLAGS) - -RM = rm -f - -$(LIBFILE): $(LIB_OBJS) - $(QUIET_AR)$(RM) $@ && $(AR) rcs $(OUTPUT)$@ $(LIB_OBJS) - -$(LIB_OBJS): $(LIB_H) - -$(OUTPUT)%.o: %.c - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< -$(OUTPUT)%.s: %.c - $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< -$(OUTPUT)%.o: %.S - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< - -clean: - $(RM) $(LIB_OBJS) $(LIBFILE) - -.PHONY: clean diff --git a/tools/lib/lk/debugfs.c b/tools/lib/lk/debugfs.c deleted file mode 100644 index 7c4347962353..000000000000 --- a/tools/lib/lk/debugfs.c +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debugfs.h" - -char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug"; - -static const char * const debugfs_known_mountpoints[] = { - "/sys/kernel/debug/", - "/debug/", - 0, -}; - -static bool debugfs_found; - -/* find the path to the mounted debugfs */ -const char *debugfs_find_mountpoint(void) -{ - const char * const *ptr; - char type[100]; - FILE *fp; - - if (debugfs_found) - return (const char *)debugfs_mountpoint; - - ptr = debugfs_known_mountpoints; - while (*ptr) { - if (debugfs_valid_mountpoint(*ptr) == 0) { - debugfs_found = true; - strcpy(debugfs_mountpoint, *ptr); - return debugfs_mountpoint; - } - ptr++; - } - - /* give up and parse /proc/mounts */ - fp = fopen("/proc/mounts", "r"); - if (fp == NULL) - return NULL; - - while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n", - debugfs_mountpoint, type) == 2) { - if (strcmp(type, "debugfs") == 0) - break; - } - fclose(fp); - - if (strcmp(type, "debugfs") != 0) - return NULL; - - debugfs_found = true; - - return debugfs_mountpoint; -} - -/* verify that a mountpoint is actually a debugfs instance */ - -int debugfs_valid_mountpoint(const char *debugfs) -{ - struct statfs st_fs; - - if (statfs(debugfs, &st_fs) < 0) - return -ENOENT; - else if (st_fs.f_type != (long) DEBUGFS_MAGIC) - return -ENOENT; - - return 0; -} - -/* mount the debugfs somewhere if it's not mounted */ -char *debugfs_mount(const char *mountpoint) -{ - /* see if it's already mounted */ - if (debugfs_find_mountpoint()) - goto out; - - /* if not mounted and no argument */ - if (mountpoint == NULL) { - /* see if environment variable set */ - mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT); - /* if no environment variable, use default */ - if (mountpoint == NULL) - mountpoint = "/sys/kernel/debug"; - } - - if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0) - return NULL; - - /* save the mountpoint */ - debugfs_found = true; - strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint)); -out: - return debugfs_mountpoint; -} diff --git a/tools/lib/lk/debugfs.h b/tools/lib/lk/debugfs.h deleted file mode 100644 index 935c59bdb442..000000000000 --- a/tools/lib/lk/debugfs.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __LK_DEBUGFS_H__ -#define __LK_DEBUGFS_H__ - -#define _STR(x) #x -#define STR(x) _STR(x) - -/* - * On most systems would have given us this, but not on some systems - * (e.g. GNU/Hurd). - */ -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif - -#ifndef DEBUGFS_MAGIC -#define DEBUGFS_MAGIC 0x64626720 -#endif - -#ifndef PERF_DEBUGFS_ENVIRONMENT -#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" -#endif - -const char *debugfs_find_mountpoint(void); -int debugfs_valid_mountpoint(const char *debugfs); -char *debugfs_mount(const char *mountpoint); - -extern char debugfs_mountpoint[]; - -#endif /* __LK_DEBUGFS_H__ */ -- cgit v1.2.3 From f23b24f1bf90b56cfaeb2a1c9b77c46efe8916a6 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 17 Dec 2013 09:02:36 +0900 Subject: tools lib traceevent: Get rid of die() in some string conversion functions Those functions stringify filter arguments. As caller of those functions handles NULL string properly, it seems that it's enough to return NULL rather than calling die(). Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/878uvkgx9f.fsf@sejong.aot.lge.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/parse-filter.c | 67 +++++++++++-------------------------- 1 file changed, 19 insertions(+), 48 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 9303c55128db..e2842b926759 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -1361,8 +1361,10 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, if (ret >= 0 && pevent->test_filters) { char *test; test = pevent_filter_make_string(filter, event->event->id); - printf(" '%s: %s'\n", event->event->name, test); - free(test); + if (test) { + printf(" '%s: %s'\n", event->event->name, test); + free(test); + } } } @@ -2050,7 +2052,6 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) int left_val = -1; int right_val = -1; int val; - int len; switch (arg->op.type) { case FILTER_OP_AND: @@ -2097,11 +2098,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) default: break; } - str = malloc_or_die(6); - if (val) - strcpy(str, "TRUE"); - else - strcpy(str, "FALSE"); + asprintf(&str, val ? "TRUE" : "FALSE"); break; } } @@ -2119,10 +2116,7 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) break; } - len = strlen(left) + strlen(right) + strlen(op) + 10; - str = malloc_or_die(len); - snprintf(str, len, "(%s) %s (%s)", - left, op, right); + asprintf(&str, "(%s) %s (%s)", left, op, right); break; case FILTER_OP_NOT: @@ -2138,16 +2132,10 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) right_val = 0; if (right_val >= 0) { /* just return the opposite */ - str = malloc_or_die(6); - if (right_val) - strcpy(str, "FALSE"); - else - strcpy(str, "TRUE"); + asprintf(&str, right_val ? "FALSE" : "TRUE"); break; } - len = strlen(right) + strlen(op) + 3; - str = malloc_or_die(len); - snprintf(str, len, "%s(%s)", op, right); + asprintf(&str, "%s(%s)", op, right); break; default: @@ -2161,11 +2149,9 @@ static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) static char *val_to_str(struct event_filter *filter, struct filter_arg *arg) { - char *str; - - str = malloc_or_die(30); + char *str = NULL; - snprintf(str, 30, "%lld", arg->value.val); + asprintf(&str, "%lld", arg->value.val); return str; } @@ -2181,7 +2167,6 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) char *rstr; char *op; char *str = NULL; - int len; lstr = arg_to_str(filter, arg->exp.left); rstr = arg_to_str(filter, arg->exp.right); @@ -2220,12 +2205,11 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) op = "^"; break; default: - die("oops in exp"); + op = "[ERROR IN EXPRESSION TYPE]"; + break; } - len = strlen(op) + strlen(lstr) + strlen(rstr) + 4; - str = malloc_or_die(len); - snprintf(str, len, "%s %s %s", lstr, op, rstr); + asprintf(&str, "%s %s %s", lstr, op, rstr); out: free(lstr); free(rstr); @@ -2239,7 +2223,6 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) char *rstr; char *str = NULL; char *op = NULL; - int len; lstr = arg_to_str(filter, arg->num.left); rstr = arg_to_str(filter, arg->num.right); @@ -2270,10 +2253,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) if (!op) op = "<="; - len = strlen(lstr) + strlen(op) + strlen(rstr) + 4; - str = malloc_or_die(len); - sprintf(str, "%s %s %s", lstr, op, rstr); - + asprintf(&str, "%s %s %s", lstr, op, rstr); break; default: @@ -2291,7 +2271,6 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) { char *str = NULL; char *op = NULL; - int len; switch (arg->str.type) { case FILTER_CMP_MATCH: @@ -2309,12 +2288,8 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) if (!op) op = "!~"; - len = strlen(arg->str.field->name) + strlen(op) + - strlen(arg->str.val) + 6; - str = malloc_or_die(len); - snprintf(str, len, "%s %s \"%s\"", - arg->str.field->name, - op, arg->str.val); + asprintf(&str, "%s %s \"%s\"", + arg->str.field->name, op, arg->str.val); break; default: @@ -2326,15 +2301,11 @@ static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) { - char *str; + char *str = NULL; switch (arg->type) { case FILTER_ARG_BOOLEAN: - str = malloc_or_die(6); - if (arg->boolean.value) - strcpy(str, "TRUE"); - else - strcpy(str, "FALSE"); + asprintf(&str, arg->boolean.value ? "TRUE" : "FALSE"); return str; case FILTER_ARG_OP: @@ -2369,7 +2340,7 @@ static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) * * Returns a string that displays the filter contents. * This string must be freed with free(str). - * NULL is returned if no filter is found. + * NULL is returned if no filter is found or allocation failed. */ char * pevent_filter_make_string(struct event_filter *filter, int event_id) -- cgit v1.2.3 From bf19b82e7cf033319525a9eab12216b59c41c519 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 12 Dec 2013 16:36:17 +0900 Subject: tools lib traceevent: Introduce pevent_filter_strerror() The pevent_filter_strerror() function is for receiving actual error message from pevent_errno value. To do that, add a static buffer to event_filter for saving internal error message If a failed function saved other information in the static buffer returns the information, otherwise returns generic error message. Signed-off-by: Namhyung Kim Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1386833777-3790-15-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 17 +------ tools/lib/traceevent/event-parse.h | 7 ++- tools/lib/traceevent/parse-filter.c | 98 ++++++++++++++++++++----------------- 3 files changed, 61 insertions(+), 61 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 22566c271275..2ce565a73dd5 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -5230,22 +5230,7 @@ int pevent_strerror(struct pevent *pevent __maybe_unused, idx = errnum - __PEVENT_ERRNO__START - 1; msg = pevent_error_str[idx]; - - switch (errnum) { - case PEVENT_ERRNO__MEM_ALLOC_FAILED: - case PEVENT_ERRNO__PARSE_EVENT_FAILED: - case PEVENT_ERRNO__READ_ID_FAILED: - case PEVENT_ERRNO__READ_FORMAT_FAILED: - case PEVENT_ERRNO__READ_PRINT_FAILED: - case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED: - case PEVENT_ERRNO__INVALID_ARG_TYPE: - snprintf(buf, buflen, "%s", msg); - break; - - default: - /* cannot reach here */ - break; - } + snprintf(buf, buflen, "%s", msg); return 0; } diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 3ad784f5f647..cf5db9013f2c 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -851,10 +851,13 @@ struct filter_type { struct filter_arg *filter; }; +#define PEVENT_FILTER_ERROR_BUFSZ 1024 + struct event_filter { struct pevent *pevent; int filters; struct filter_type *event_filters; + char error_buffer[PEVENT_FILTER_ERROR_BUFSZ]; }; struct event_filter *pevent_filter_alloc(struct pevent *pevent); @@ -874,10 +877,12 @@ enum filter_trivial_type { enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, const char *filter_str); - enum pevent_errno pevent_filter_match(struct event_filter *filter, struct pevent_record *record); +int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err, + char *buf, size_t buflen); + int pevent_event_filtered(struct event_filter *filter, int event_id); diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index e2842b926759..b50234402fc2 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c @@ -38,55 +38,31 @@ struct event_list { struct event_format *event; }; -#define MAX_ERR_STR_SIZE 256 - -static void show_error(char **error_str, const char *fmt, ...) +static void show_error(char *error_buf, const char *fmt, ...) { unsigned long long index; const char *input; - char *error; va_list ap; int len; int i; - if (!error_str) - return; - input = pevent_get_input_buf(); index = pevent_get_input_buf_ptr(); len = input ? strlen(input) : 0; - error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3); - if (error == NULL) { - /* - * Maybe it's due to len is too long. - * Retry without the input buffer part. - */ - len = 0; - - error = malloc(MAX_ERR_STR_SIZE); - if (error == NULL) { - /* no memory */ - *error_str = NULL; - return; - } - } - if (len) { - strcpy(error, input); - error[len] = '\n'; + strcpy(error_buf, input); + error_buf[len] = '\n'; for (i = 1; i < len && i < index; i++) - error[len+i] = ' '; - error[len + i] = '^'; - error[len + i + 1] = '\n'; + error_buf[len+i] = ' '; + error_buf[len + i] = '^'; + error_buf[len + i + 1] = '\n'; len += i+2; } va_start(ap, fmt); - vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap); + vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap); va_end(ap); - - *error_str = error; } static void free_token(char *token) @@ -370,7 +346,7 @@ static void free_events(struct event_list *events) static enum pevent_errno create_arg_item(struct event_format *event, const char *token, - enum event_type type, struct filter_arg **parg, char **error_str) + enum event_type type, struct filter_arg **parg, char *error_str) { struct format_field *field; struct filter_arg *arg; @@ -474,7 +450,7 @@ create_arg_cmp(enum filter_exp_type etype) } static enum pevent_errno -add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str) +add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str) { struct filter_arg *left; char *str; @@ -786,7 +762,7 @@ enum filter_vals { static enum pevent_errno reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, - struct filter_arg *arg, char **error_str) + struct filter_arg *arg, char *error_str) { struct filter_arg *other_child; struct filter_arg **ptr; @@ -838,7 +814,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, /* Returns either filter_vals (success) or pevent_errno (failfure) */ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, - char **error_str) + char *error_str) { int lval, rval; @@ -938,7 +914,7 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, /* Remove any unknown event fields */ static int collapse_tree(struct filter_arg *arg, - struct filter_arg **arg_collapsed, char **error_str) + struct filter_arg **arg_collapsed, char *error_str) { int ret; @@ -973,7 +949,7 @@ static int collapse_tree(struct filter_arg *arg, static enum pevent_errno process_filter(struct event_format *event, struct filter_arg **parg, - char **error_str, int not) + char *error_str, int not) { enum event_type type; char *token = NULL; @@ -1211,7 +1187,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, static enum pevent_errno process_event(struct event_format *event, const char *filter_str, - struct filter_arg **parg, char **error_str) + struct filter_arg **parg, char *error_str) { int ret; @@ -1236,7 +1212,7 @@ process_event(struct event_format *event, const char *filter_str, static enum pevent_errno filter_event(struct event_filter *filter, struct event_format *event, - const char *filter_str, char **error_str) + const char *filter_str, char *error_str) { struct filter_type *filter_type; struct filter_arg *arg; @@ -1268,13 +1244,21 @@ filter_event(struct event_filter *filter, struct event_format *event, return 0; } +static void filter_init_error_buf(struct event_filter *filter) +{ + /* clear buffer to reset show error */ + pevent_buffer_init("", 0); + filter->error_buffer[0] = '\0'; +} + /** * pevent_filter_add_filter_str - add a new filter * @filter: the event filter to add to * @filter_str: the filter string that contains the filter * * Returns 0 if the filter was successfully added or a - * negative error code. + * negative error code. Use pevent_filter_strerror() to see + * actual error message in case of error. */ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, const char *filter_str) @@ -1291,10 +1275,8 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */ int len; int ret; - char *error_str = NULL; - /* clear buffer to reset show error */ - pevent_buffer_init("", 0); + filter_init_error_buf(filter); filter_start = strchr(filter_str, ':'); if (filter_start) @@ -1353,7 +1335,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, /* filter starts here */ for (event = events; event; event = event->next) { ret = filter_event(filter, event->event, filter_start, - &error_str); + filter->error_buffer); /* Failures are returned if a parse error happened */ if (ret < 0) rtn = ret; @@ -1381,6 +1363,32 @@ static void free_filter_type(struct filter_type *filter_type) free_arg(filter_type->filter); } +/** + * pevent_filter_strerror - fill error message in a buffer + * @filter: the event filter contains error + * @err: the error code + * @buf: the buffer to be filled in + * @buflen: the size of the buffer + * + * Returns 0 if message was filled successfully, -1 if error + */ +int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err, + char *buf, size_t buflen) +{ + if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END) + return -1; + + if (strlen(filter->error_buffer) > 0) { + size_t len = snprintf(buf, buflen, "%s", filter->error_buffer); + + if (len > buflen) + return -1; + return 0; + } + + return pevent_strerror(filter->pevent, err, buf, buflen); +} + /** * pevent_filter_remove_event - remove a filter for an event * @filter: the event filter to remove from @@ -2027,6 +2035,8 @@ enum pevent_errno pevent_filter_match(struct event_filter *filter, int ret; enum pevent_errno err = 0; + filter_init_error_buf(filter); + if (!filter->filters) return PEVENT_ERRNO__NO_FILTER; -- cgit v1.2.3 From db72a330587e10d6b8009e0dcf3d97aa9b1e2659 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:01 +0100 Subject: tools lib traceevent: Remove print_app_build variable Removing print_app_build variable, because it's not needed. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-4-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 6 ------ 1 file changed, 6 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 0d9cbb426b44..022c987d25b6 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -151,7 +151,6 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = print_compile = - print_app_build = print_fpic_compile = print_shared_lib_compile = print_plugin_obj_compile = @@ -160,7 +159,6 @@ ifeq ($(VERBOSE),1) else Q = @ print_compile = echo ' CC '$(OBJ); - print_app_build = echo ' BUILD '$(OBJ); print_fpic_compile = echo ' CC FPIC '$(OBJ); print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); print_plugin_obj_compile = echo ' CC FPIC '$(OBJ); @@ -173,10 +171,6 @@ do_fpic_compile = \ ($(print_fpic_compile) \ $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@) -do_app_build = \ - ($(print_app_build) \ - $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS)) - do_compile_shared_library = \ ($(print_shared_lib_compile) \ $(CC) --shared $^ -o $@) -- cgit v1.2.3 From c3d090f498a4d7a8905c92dbf83ae2aa4810fbef Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:02 +0100 Subject: tools lib traceevent: Use global QUIET_CC build output Using global QUIET_CC build output variable and getting rid of local print_compile. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-5-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 022c987d25b6..e852a8d54d84 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -67,6 +67,8 @@ PLUGIN_DIR = -DPLUGIN_DIR="$(DESTDIR)/$(plugin_dir)" PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' endif +include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include + # copy a bit from Linux kbuild ifeq ("$(origin V)", "command line") @@ -150,7 +152,6 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = - print_compile = print_fpic_compile = print_shared_lib_compile = print_plugin_obj_compile = @@ -158,7 +159,6 @@ ifeq ($(VERBOSE),1) print_install = else Q = @ - print_compile = echo ' CC '$(OBJ); print_fpic_compile = echo ' CC FPIC '$(OBJ); print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); print_plugin_obj_compile = echo ' CC FPIC '$(OBJ); @@ -188,16 +188,13 @@ do_build_static_lib = \ $(RM) $@; $(AR) rcs $@ $^) -define do_compile - $(print_compile) \ - $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@; -endef +do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@; $(obj)/%.o: $(src)/%.c - $(Q)$(call do_compile) + $(call do_compile) %.o: $(src)/%.c - $(Q)$(call do_compile) + $(call do_compile) PEVENT_LIB_OBJS = event-parse.o PEVENT_LIB_OBJS += event-plugin.o -- cgit v1.2.3 From bdebbacd421184234b5551c468e53956a9b6edf5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:03 +0100 Subject: tools lib traceevent: Add global QUIET_CC_FPIC build output Adding global QUIET_CC_FPIC build output variable and getting rid of local print_fpic_compile and print_plugin_obj_compile. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-6-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index e852a8d54d84..24203cc14649 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -152,33 +152,21 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = - print_fpic_compile = print_shared_lib_compile = - print_plugin_obj_compile = print_plugin_build = print_install = else Q = @ - print_fpic_compile = echo ' CC FPIC '$(OBJ); print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); - print_plugin_obj_compile = echo ' CC FPIC '$(OBJ); print_plugin_build = echo ' BUILD PLUGIN '$(OBJ); print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); print_install = echo ' INSTALL '$1; endif -do_fpic_compile = \ - ($(print_fpic_compile) \ - $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@) - do_compile_shared_library = \ ($(print_shared_lib_compile) \ $(CC) --shared $^ -o $@) -do_compile_plugin_obj = \ - ($(print_plugin_obj_compile) \ - $(CC) -c $(CFLAGS) -fPIC -o $@ $<) - do_plugin_build = \ ($(print_plugin_build) \ $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<) @@ -236,10 +224,10 @@ libtraceevent.a: $(PEVENT_LIB_OBJS) plugins: $(PLUGINS) $(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS - $(Q)$(do_fpic_compile) + $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@ $(PLUGIN_OBJS): %.o : $(src)/%.c - $(Q)$(do_compile_plugin_obj) + $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $< $(PLUGINS): %.so: %.o $(Q)$(do_plugin_build) -- cgit v1.2.3 From e6262e23134f575ae07ecc25bb69ddb63caebc95 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:04 +0100 Subject: tools lib traceevent: Use global QUIET_LINK build output Using global QUIET_LINK build output variable and getting rid of local print_static_lib_build, print_plugin_build and print_shared_lib_compile. We no longer distinguish between shared and static library in the build message. It's differenced by the built file suffix, like: $ make ... LINK libtraceevent.a LINK libtraceevent.so Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-7-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 24203cc14649..51be8ab76f9f 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -152,14 +152,9 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = - print_shared_lib_compile = - print_plugin_build = print_install = else Q = @ - print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); - print_plugin_build = echo ' BUILD PLUGIN '$(OBJ); - print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); print_install = echo ' INSTALL '$1; endif @@ -216,10 +211,10 @@ all: all_cmd all_cmd: $(CMD_TARGETS) libtraceevent.so: $(PEVENT_LIB_OBJS) - $(Q)$(do_compile_shared_library) + $(QUIET_LINK)$(CC) --shared $^ -o $@ libtraceevent.a: $(PEVENT_LIB_OBJS) - $(Q)$(do_build_static_lib) + $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ plugins: $(PLUGINS) @@ -230,7 +225,7 @@ $(PLUGIN_OBJS): %.o : $(src)/%.c $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $< $(PLUGINS): %.so: %.o - $(Q)$(do_plugin_build) + $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $< define make_version.h (echo '/* This file is automatically generated. Do not modify. */'; \ -- cgit v1.2.3 From 02a82c7bcd353b8cc4d4f8b3c872b527fbac7c31 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:05 +0100 Subject: tools lib traceevent: Use global QUIET_INSTALL build output Using global QUIET_INSTALL build output variable and factoring plugins installation so we could have only single install message for plugins: INSTALL trace_plugins Getting rid of local print_install. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-8-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 51be8ab76f9f..8ea4368381f0 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -152,10 +152,8 @@ override CFLAGS += $(udis86-flags) -D_GNU_SOURCE ifeq ($(VERBOSE),1) Q = - print_install = else Q = @ - print_install = echo ' INSTALL '$1; endif do_compile_shared_library = \ @@ -307,22 +305,25 @@ TAGS: force --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' define do_install - $(print_install) \ if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ fi; \ $(INSTALL) $1 '$(DESTDIR_SQ)$2' endef -install_lib: all_cmd install_plugins - $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ)) - -PLUGINS_INSTALL = $(subst .so,.install,$(PLUGINS)) +define do_install_plugins + for plugin in $1; do \ + $(call do_install,$$plugin,$(plugin_dir_SQ)); \ + done +endef -$(PLUGINS_INSTALL): %.install : %.so force - $(Q)$(call do_install,$<,$(plugin_dir_SQ)) +install_lib: all_cmd install_plugins + $(call QUIET_INSTALL, $(LIB_FILE)) \ + $(call do_install,$(LIB_FILE),$(bindir_SQ)) -install_plugins: $(PLUGINS_INSTALL) +install_plugins: $(PLUGINS) + $(call QUIET_INSTALL, trace_plugins) \ + $(call do_install_plugins, $(PLUGINS)) install: install_lib -- cgit v1.2.3 From 4a953c716af285c94432e2d303ca5ee8f66129c0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:06 +0100 Subject: tools lib traceevent: Use global QUIET_CLEAN build output Using global QUIET_CLEAN build output variable and so we could have only single clean message: CLEAN libtraceevent Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-9-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 8ea4368381f0..3496c9ce84d4 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -328,8 +328,9 @@ install_plugins: $(PLUGINS) install: install_lib clean: - $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d - $(RM) TRACEEVENT-CFLAGS tags TAGS + $(call QUIET_CLEAN, libtraceevent) \ + $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \ + $(RM) TRACEEVENT-CFLAGS tags TAGS endif # skip-makefile -- cgit v1.2.3 From 4c7aafc950178cd78f8cbda916ee8208afe039b5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Dec 2013 14:42:07 +0100 Subject: tools lib traceevent: Use global 'O' processing code Using global 'O' processing code because it's already setup due to the scripts/Makefile.include include. Using global variable OUTPUT instead of the local BUILD_OUTPUT. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1387460527-15030-10-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 3496c9ce84d4..ca4ab78425d1 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -83,18 +83,13 @@ ifeq ("$(origin O)", "command line") endif ifeq ($(BUILD_SRC),) -ifneq ($(BUILD_OUTPUT),) +ifneq ($(OUTPUT),) define build_output - $(if $(VERBOSE:1=),@)+$(MAKE) -C $(BUILD_OUTPUT) \ - BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1 + $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \ + BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1 endef -saved-output := $(BUILD_OUTPUT) -BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd) -$(if $(BUILD_OUTPUT),, \ - $(error output directory "$(saved-output)" does not exist)) - all: sub-make $(MAKECMDGOALS): sub-make @@ -106,7 +101,7 @@ sub-make: force # Leave processing to above invocation of make skip-makefile := 1 -endif # BUILD_OUTPUT +endif # OUTPUT endif # BUILD_SRC # We process the rest of the Makefile if this is the final invocation of make -- cgit v1.2.3 From 198430b56d4ab49d77381ef7cd3daf418a2c00c0 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 2 Jan 2014 10:53:04 +0100 Subject: tools lib traceevent: Replace tabs with spaces for all non-commands statements The tabbed indentation in non-commands statements could be sometimes considered as follow up for the rule command in the Makefile. This error is hard to find, so as a precaution replacing tabs with spaces for all non-commands statements. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://marc.info/?t=136484403900003&r=1&w=2 Link: http://lkml.kernel.org/r/20140102095304.GA1196@krava.brq.redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 54 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index ca4ab78425d1..76fe0aeb874e 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -86,8 +86,8 @@ ifeq ($(BUILD_SRC),) ifneq ($(OUTPUT),) define build_output - $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \ - BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1 + $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \ + BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1 endef all: sub-make @@ -221,23 +221,23 @@ $(PLUGINS): %.so: %.o $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $< define make_version.h - (echo '/* This file is automatically generated. Do not modify. */'; \ - echo \#define VERSION_CODE $(shell \ - expr $(VERSION) \* 256 + $(PATCHLEVEL)); \ - echo '#define EXTRAVERSION ' $(EXTRAVERSION); \ - echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \ - echo '#define FILE_VERSION '$(FILE_VERSION); \ - ) > $1 + (echo '/* This file is automatically generated. Do not modify. */'; \ + echo \#define VERSION_CODE $(shell \ + expr $(VERSION) \* 256 + $(PATCHLEVEL)); \ + echo '#define EXTRAVERSION ' $(EXTRAVERSION); \ + echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \ + echo '#define FILE_VERSION '$(FILE_VERSION); \ + ) > $1 endef define update_version.h - ($(call make_version.h, $@.tmp); \ - if [ -r $@ ] && cmp -s $@ $@.tmp; then \ - rm -f $@.tmp; \ - else \ - echo ' UPDATE $@'; \ - mv -f $@.tmp $@; \ - fi); + ($(call make_version.h, $@.tmp); \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + echo ' UPDATE $@'; \ + mv -f $@.tmp $@; \ + fi); endef ep_version.h: force @@ -246,13 +246,13 @@ ep_version.h: force VERSION_FILES = ep_version.h define update_dir - (echo $1 > $@.tmp; \ - if [ -r $@ ] && cmp -s $@ $@.tmp; then \ - rm -f $@.tmp; \ - else \ - echo ' UPDATE $@'; \ - mv -f $@.tmp $@; \ - fi); + (echo $1 > $@.tmp; \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + echo ' UPDATE $@'; \ + mv -f $@.tmp $@; \ + fi); endef ## make deps @@ -262,10 +262,10 @@ all_deps := $(all_objs:%.o=.%.d) # let .d file also depends on the source and header files define check_deps - @set -e; $(RM) $@; \ - $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ - sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ - $(RM) $@.$$$$ + @set -e; $(RM) $@; \ + $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + $(RM) $@.$$$$ endef $(all_deps): .%.d: $(src)/%.c -- cgit v1.2.3 From 9bb8e5edcf37182d0c97e98131cc3c5c03014b0e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 1 Jan 2014 17:50:50 +0100 Subject: tools lib traceevent: Shut up plugins make message Getting rid of following build output: $ make O=/tmp/build/perf -C tools/perf/ install-bin ... make[3]: Nothing to be done for `plugins'. make[2]: Nothing to be done for `plugins'. ... which triggers when traceevent library needs to be rebuilt, but we have plugins built already. Adding extra 'plugins' target with nop which is visible and triggers in both Makefile parts (for detached output directory (O=...) the traceevent Makefile spawns sub make for the build itself). Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1388595050-23005-2-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 76fe0aeb874e..f778d48ac609 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -329,9 +329,12 @@ clean: endif # skip-makefile -PHONY += force +PHONY += force plugins force: +plugins: + @echo > /dev/null + # Declare the contents of the .PHONY variable as phony. We keep that # information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY) -- cgit v1.2.3 From 3c6d8d84423932f1d9949179c6acdf2405515ee4 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 19 Dec 2013 18:17:44 +0900 Subject: tools lib traceevent: Add state member to struct trace_seq The trace_seq->state is for tracking errors during the use of trace_seq APIs and getting rid of die() in it. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/87fvopalbb.fsf@sejong.aot.lge.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 2 +- tools/lib/traceevent/event-parse.h | 7 +++++ tools/lib/traceevent/trace-seq.c | 55 +++++++++++++++++++++++++++++--------- 3 files changed, 50 insertions(+), 14 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index f778d48ac609..56d52a33a3df 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -136,7 +136,7 @@ export Q VERBOSE EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION) -INCLUDES = -I. $(CONFIG_INCLUDES) +INCLUDES = -I. -I $(srctree)/../../include $(CONFIG_INCLUDES) # Set compile option CFLAGS if not set elsewhere CFLAGS ?= -g -Wall diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index cf5db9013f2c..3c890cb28db7 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -58,6 +58,12 @@ struct pevent_record { #endif }; +enum trace_seq_fail { + TRACE_SEQ__GOOD, + TRACE_SEQ__BUFFER_POISONED, + TRACE_SEQ__MEM_ALLOC_FAILED, +}; + /* * Trace sequences are used to allow a function to call several other functions * to create a string of data to use (up to a max of PAGE_SIZE). @@ -68,6 +74,7 @@ struct trace_seq { unsigned int buffer_size; unsigned int len; unsigned int readpos; + enum trace_seq_fail state; }; void trace_seq_init(struct trace_seq *s); diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c index d7f2e68bc5b9..f7112138e6af 100644 --- a/tools/lib/traceevent/trace-seq.c +++ b/tools/lib/traceevent/trace-seq.c @@ -22,6 +22,7 @@ #include #include +#include #include "event-parse.h" #include "event-utils.h" @@ -32,10 +33,21 @@ #define TRACE_SEQ_POISON ((void *)0xdeadbeef) #define TRACE_SEQ_CHECK(s) \ do { \ - if ((s)->buffer == TRACE_SEQ_POISON) \ - die("Usage of trace_seq after it was destroyed"); \ + if (WARN_ONCE((s)->buffer == TRACE_SEQ_POISON, \ + "Usage of trace_seq after it was destroyed")) \ + (s)->state = TRACE_SEQ__BUFFER_POISONED; \ } while (0) +#define TRACE_SEQ_CHECK_RET_N(s, n) \ +do { \ + TRACE_SEQ_CHECK(s); \ + if ((s)->state != TRACE_SEQ__GOOD) \ + return n; \ +} while (0) + +#define TRACE_SEQ_CHECK_RET(s) TRACE_SEQ_CHECK_RET_N(s, ) +#define TRACE_SEQ_CHECK_RET0(s) TRACE_SEQ_CHECK_RET_N(s, 0) + /** * trace_seq_init - initialize the trace_seq structure * @s: a pointer to the trace_seq structure to initialize @@ -46,6 +58,7 @@ void trace_seq_init(struct trace_seq *s) s->readpos = 0; s->buffer_size = TRACE_SEQ_BUF_SIZE; s->buffer = malloc_or_die(s->buffer_size); + s->state = TRACE_SEQ__GOOD; } /** @@ -71,7 +84,7 @@ void trace_seq_destroy(struct trace_seq *s) { if (!s) return; - TRACE_SEQ_CHECK(s); + TRACE_SEQ_CHECK_RET(s); free(s->buffer); s->buffer = TRACE_SEQ_POISON; } @@ -80,8 +93,9 @@ static void expand_buffer(struct trace_seq *s) { s->buffer_size += TRACE_SEQ_BUF_SIZE; s->buffer = realloc(s->buffer, s->buffer_size); - if (!s->buffer) - die("Can't allocate trace_seq buffer memory"); + if (WARN_ONCE(!s->buffer, + "Can't allocate trace_seq buffer memory")) + s->state = TRACE_SEQ__MEM_ALLOC_FAILED; } /** @@ -105,9 +119,9 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...) int len; int ret; - TRACE_SEQ_CHECK(s); - try_again: + TRACE_SEQ_CHECK_RET0(s); + len = (s->buffer_size - 1) - s->len; va_start(ap, fmt); @@ -141,9 +155,9 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) int len; int ret; - TRACE_SEQ_CHECK(s); - try_again: + TRACE_SEQ_CHECK_RET0(s); + len = (s->buffer_size - 1) - s->len; ret = vsnprintf(s->buffer + s->len, len, fmt, args); @@ -172,13 +186,15 @@ int trace_seq_puts(struct trace_seq *s, const char *str) { int len; - TRACE_SEQ_CHECK(s); + TRACE_SEQ_CHECK_RET0(s); len = strlen(str); while (len > ((s->buffer_size - 1) - s->len)) expand_buffer(s); + TRACE_SEQ_CHECK_RET0(s); + memcpy(s->buffer + s->len, str, len); s->len += len; @@ -187,11 +203,13 @@ int trace_seq_puts(struct trace_seq *s, const char *str) int trace_seq_putc(struct trace_seq *s, unsigned char c) { - TRACE_SEQ_CHECK(s); + TRACE_SEQ_CHECK_RET0(s); while (s->len >= (s->buffer_size - 1)) expand_buffer(s); + TRACE_SEQ_CHECK_RET0(s); + s->buffer[s->len++] = c; return 1; @@ -199,7 +217,7 @@ int trace_seq_putc(struct trace_seq *s, unsigned char c) void trace_seq_terminate(struct trace_seq *s) { - TRACE_SEQ_CHECK(s); + TRACE_SEQ_CHECK_RET(s); /* There's always one character left on the buffer */ s->buffer[s->len] = 0; @@ -208,5 +226,16 @@ void trace_seq_terminate(struct trace_seq *s) int trace_seq_do_printf(struct trace_seq *s) { TRACE_SEQ_CHECK(s); - return printf("%.*s", s->len, s->buffer); + + switch (s->state) { + case TRACE_SEQ__GOOD: + return printf("%.*s", s->len, s->buffer); + case TRACE_SEQ__BUFFER_POISONED: + puts("Usage of trace_seq after it was destroyed"); + break; + case TRACE_SEQ__MEM_ALLOC_FAILED: + puts("Can't allocate trace_seq buffer memory"); + break; + } + return -1; } -- cgit v1.2.3 From 3026bba3c37711234771349ca020d9a85e572f60 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 15 Jan 2014 10:45:25 +0900 Subject: tools lib traceevent: Check return value of realloc() If realloc() fails, it'll leak the buffer. Also increate buffer size only if the allocation succeeded. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389750340-15965-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/trace-seq.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c index f7112138e6af..e454a2c66cac 100644 --- a/tools/lib/traceevent/trace-seq.c +++ b/tools/lib/traceevent/trace-seq.c @@ -91,11 +91,16 @@ void trace_seq_destroy(struct trace_seq *s) static void expand_buffer(struct trace_seq *s) { - s->buffer_size += TRACE_SEQ_BUF_SIZE; - s->buffer = realloc(s->buffer, s->buffer_size); - if (WARN_ONCE(!s->buffer, - "Can't allocate trace_seq buffer memory")) + char *buf; + + buf = realloc(s->buffer, s->buffer_size + TRACE_SEQ_BUF_SIZE); + if (WARN_ONCE(!buf, "Can't allocate trace_seq buffer memory")) { s->state = TRACE_SEQ__MEM_ALLOC_FAILED; + return; + } + + s->buffer = buf; + s->buffer_size += TRACE_SEQ_BUF_SIZE; } /** -- cgit v1.2.3 From 504586e0954bcf9550dfdea37d3234174ed1d68f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 15 Jan 2014 10:45:26 +0900 Subject: tools lib traceevent: Get rid of malloc_or_die() in trace_seq_init() Use plain malloc() and check its return value. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389750340-15965-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/trace-seq.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c index e454a2c66cac..ec3bd16a5488 100644 --- a/tools/lib/traceevent/trace-seq.c +++ b/tools/lib/traceevent/trace-seq.c @@ -57,8 +57,11 @@ void trace_seq_init(struct trace_seq *s) s->len = 0; s->readpos = 0; s->buffer_size = TRACE_SEQ_BUF_SIZE; - s->buffer = malloc_or_die(s->buffer_size); - s->state = TRACE_SEQ__GOOD; + s->buffer = malloc(s->buffer_size); + if (s->buffer != NULL) + s->state = TRACE_SEQ__GOOD; + else + s->state = TRACE_SEQ__MEM_ALLOC_FAILED; } /** -- cgit v1.2.3 From e825e756f84eab0e68d7d6644c018c3412748406 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 15 Jan 2014 10:45:27 +0900 Subject: tools lib traceevent: Get rid of die() finally!! Now all of its users were gone. :) Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389750340-15965-5-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-utils.h | 4 ---- tools/lib/traceevent/parse-utils.c | 44 -------------------------------------- 2 files changed, 48 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-utils.h b/tools/lib/traceevent/event-utils.h index e76c9acb92cd..d1dc2170e402 100644 --- a/tools/lib/traceevent/event-utils.h +++ b/tools/lib/traceevent/event-utils.h @@ -23,18 +23,14 @@ #include /* Can be overridden */ -void die(const char *fmt, ...); -void *malloc_or_die(unsigned int size); void warning(const char *fmt, ...); void pr_stat(const char *fmt, ...); void vpr_stat(const char *fmt, va_list ap); /* Always available */ -void __die(const char *fmt, ...); void __warning(const char *fmt, ...); void __pr_stat(const char *fmt, ...); -void __vdie(const char *fmt, ...); void __vwarning(const char *fmt, ...); void __vpr_stat(const char *fmt, ...); diff --git a/tools/lib/traceevent/parse-utils.c b/tools/lib/traceevent/parse-utils.c index bba701cf10e6..eda07fa31dca 100644 --- a/tools/lib/traceevent/parse-utils.c +++ b/tools/lib/traceevent/parse-utils.c @@ -25,40 +25,6 @@ #define __weak __attribute__((weak)) -void __vdie(const char *fmt, va_list ap) -{ - int ret = errno; - - if (errno) - perror("trace-cmd"); - else - ret = -1; - - fprintf(stderr, " "); - vfprintf(stderr, fmt, ap); - - fprintf(stderr, "\n"); - exit(ret); -} - -void __die(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - __vdie(fmt, ap); - va_end(ap); -} - -void __weak die(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - __vdie(fmt, ap); - va_end(ap); -} - void __vwarning(const char *fmt, va_list ap) { if (errno) @@ -117,13 +83,3 @@ void __weak pr_stat(const char *fmt, ...) __vpr_stat(fmt, ap); va_end(ap); } - -void __weak *malloc_or_die(unsigned int size) -{ - void *data; - - data = malloc(size); - if (!data) - die("malloc"); - return data; -} -- cgit v1.2.3 From 8d0c2224ca6e04ba51c403805e7e1e2ca536520b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 15 Jan 2014 10:45:28 +0900 Subject: tools lib traceevent: Make plugin unload function receive pevent The PEVENT_PLUGIN_UNLOADER function might need some cleanup using pevent like unregister some handlers. So pass pevent as argument. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389750340-15965-6-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 7 ++++--- tools/lib/traceevent/event-plugin.c | 4 ++-- tools/lib/traceevent/plugin_function.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 3c890cb28db7..a3beca56cb35 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -105,7 +105,7 @@ typedef int (*pevent_event_handler_func)(struct trace_seq *s, void *context); typedef int (*pevent_plugin_load_func)(struct pevent *pevent); -typedef int (*pevent_plugin_unload_func)(void); +typedef int (*pevent_plugin_unload_func)(struct pevent *pevent); struct plugin_option { struct plugin_option *next; @@ -130,7 +130,7 @@ struct plugin_option { * PEVENT_PLUGIN_UNLOADER: (optional) * The function called just before unloading * - * int PEVENT_PLUGIN_UNLOADER(void) + * int PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) * * PEVENT_PLUGIN_OPTIONS: (optional) * Plugin options that can be set before loading @@ -411,7 +411,8 @@ enum pevent_errno { struct plugin_list; struct plugin_list *traceevent_load_plugins(struct pevent *pevent); -void traceevent_unload_plugins(struct plugin_list *plugin_list); +void traceevent_unload_plugins(struct plugin_list *plugin_list, + struct pevent *pevent); struct cmdline; struct cmdline_list; diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c index 125f5676bcb5..0c8bf6780e4d 100644 --- a/tools/lib/traceevent/event-plugin.c +++ b/tools/lib/traceevent/event-plugin.c @@ -197,7 +197,7 @@ traceevent_load_plugins(struct pevent *pevent) } void -traceevent_unload_plugins(struct plugin_list *plugin_list) +traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent) { pevent_plugin_unload_func func; struct plugin_list *list; @@ -207,7 +207,7 @@ traceevent_unload_plugins(struct plugin_list *plugin_list) plugin_list = list->next; func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME); if (func) - func(); + func(pevent); dlclose(list->handle); free(list->name); free(list); diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c index aad92ad5e96f..39461485f9a7 100644 --- a/tools/lib/traceevent/plugin_function.c +++ b/tools/lib/traceevent/plugin_function.c @@ -144,7 +144,7 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) return 0; } -void PEVENT_PLUGIN_UNLOADER(void) +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) { int i, x; -- cgit v1.2.3 From 0e9e79a13ab9d56b86db6538305babc23b1445cc Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Wed, 15 Jan 2014 10:44:07 +0000 Subject: tools lib traceevent: fix pointer-integer size mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scsi and cfg80211 plugins cast between unsigned long long and pointers, which is problematic for architectures where unsigned long long is wider than the native pointer size: linux/tools/lib/traceevent/plugin_scsi.c: In function ‘process_scsi_trace_parse_cdb’: linux/tools/lib/traceevent/plugin_scsi.c:408:26: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] scsi_trace_parse_cdb(s, (unsigned char *) args[1], args[2]); linux/tools/lib/traceevent/plugin_cfg80211.c: In function ‘process___le16_to_cpup’: linux/tools/lib/traceevent/plugin_cfg80211.c:11:18: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] uint16_t *val = (uint16_t *) args[0]; This patch adds an intermediate cast to unsigned long, silencing the warning. Signed-off-by: Mark Rutland Acked-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Ingo Molnar Cc: Jiri Olsa Cc: Will Deacon Link: http://lkml.kernel.org/r/1389782648-4417-3-git-send-email-mark.rutland@arm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_cfg80211.c | 2 +- tools/lib/traceevent/plugin_scsi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c index dcab8e873c21..57e98221db20 100644 --- a/tools/lib/traceevent/plugin_cfg80211.c +++ b/tools/lib/traceevent/plugin_cfg80211.c @@ -8,7 +8,7 @@ static unsigned long long process___le16_to_cpup(struct trace_seq *s, unsigned long long *args) { - uint16_t *val = (uint16_t *) args[0]; + uint16_t *val = (uint16_t *) (unsigned long) args[0]; return val ? (long long) le16toh(*val) : 0; } diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c index 6fb8e3e3fcad..7ef16cc96562 100644 --- a/tools/lib/traceevent/plugin_scsi.c +++ b/tools/lib/traceevent/plugin_scsi.c @@ -405,7 +405,7 @@ scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len) unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s, unsigned long long *args) { - scsi_trace_parse_cdb(s, (unsigned char *) args[1], args[2]); + scsi_trace_parse_cdb(s, (unsigned char *) (unsigned long) args[1], args[2]); return 0; } -- cgit v1.2.3 From ad13701d4905e820f32ce3c2590e19ca65765d63 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:07 +0900 Subject: tools lib traceevent: Add pevent_unregister_event_handler() When a plugin is unloaded it needs to unregister its handler from pevent. So add an unregister function to do it. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 113 ++++++++++++++++++++++++++++++++----- tools/lib/traceevent/event-parse.h | 3 + 2 files changed, 102 insertions(+), 14 deletions(-) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 2ce565a73dd5..d1973cb8388b 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -5560,6 +5560,29 @@ int pevent_register_print_function(struct pevent *pevent, return ret; } +static struct event_format *pevent_search_event(struct pevent *pevent, int id, + const char *sys_name, + const char *event_name) +{ + struct event_format *event; + + if (id >= 0) { + /* search by id */ + event = pevent_find_event(pevent, id); + if (!event) + return NULL; + if (event_name && (strcmp(event_name, event->name) != 0)) + return NULL; + if (sys_name && (strcmp(sys_name, event->system) != 0)) + return NULL; + } else { + event = pevent_find_event_by_name(pevent, sys_name, event_name); + if (!event) + return NULL; + } + return event; +} + /** * pevent_register_event_handler - register a way to parse an event * @pevent: the handle to the pevent @@ -5584,20 +5607,9 @@ int pevent_register_event_handler(struct pevent *pevent, int id, struct event_format *event; struct event_handler *handle; - if (id >= 0) { - /* search by id */ - event = pevent_find_event(pevent, id); - if (!event) - goto not_found; - if (event_name && (strcmp(event_name, event->name) != 0)) - goto not_found; - if (sys_name && (strcmp(sys_name, event->system) != 0)) - goto not_found; - } else { - event = pevent_find_event_by_name(pevent, sys_name, event_name); - if (!event) - goto not_found; - } + event = pevent_search_event(pevent, id, sys_name, event_name); + if (event == NULL) + goto not_found; pr_stat("overriding event (%d) %s:%s with new print handler", event->id, event->system, event->name); @@ -5637,6 +5649,79 @@ int pevent_register_event_handler(struct pevent *pevent, int id, return -1; } +static int handle_matches(struct event_handler *handler, int id, + const char *sys_name, const char *event_name, + pevent_event_handler_func func, void *context) +{ + if (id >= 0 && id != handler->id) + return 0; + + if (event_name && (strcmp(event_name, handler->event_name) != 0)) + return 0; + + if (sys_name && (strcmp(sys_name, handler->sys_name) != 0)) + return 0; + + if (func != handler->func || context != handler->context) + return 0; + + return 1; +} + +/** + * pevent_unregister_event_handler - unregister an existing event handler + * @pevent: the handle to the pevent + * @id: the id of the event to unregister + * @sys_name: the system name the handler belongs to + * @event_name: the name of the event handler + * @func: the function to call to parse the event information + * @context: the data to be passed to @func + * + * This function removes existing event handler (parser). + * + * If @id is >= 0, then it is used to find the event. + * else @sys_name and @event_name are used. + * + * Returns 0 if handler was removed successfully, -1 if event was not found. + */ +int pevent_unregister_event_handler(struct pevent *pevent, int id, + const char *sys_name, const char *event_name, + pevent_event_handler_func func, void *context) +{ + struct event_format *event; + struct event_handler *handle; + struct event_handler **next; + + event = pevent_search_event(pevent, id, sys_name, event_name); + if (event == NULL) + goto not_found; + + if (event->handler == func && event->context == context) { + pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.", + event->id, event->system, event->name); + + event->handler = NULL; + event->context = NULL; + return 0; + } + +not_found: + for (next = &pevent->handlers; *next; next = &(*next)->next) { + handle = *next; + if (handle_matches(handle, id, sys_name, event_name, + func, context)) + break; + } + + if (!(*next)) + return -1; + + *next = handle->next; + free_handler(handle); + + return 0; +} + /** * pevent_alloc - create a pevent handle */ diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index a3beca56cb35..c48acfbc6230 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -624,6 +624,9 @@ int pevent_print_func_field(struct trace_seq *s, const char *fmt, int pevent_register_event_handler(struct pevent *pevent, int id, const char *sys_name, const char *event_name, pevent_event_handler_func func, void *context); +int pevent_unregister_event_handler(struct pevent *pevent, int id, + const char *sys_name, const char *event_name, + pevent_event_handler_func func, void *context); int pevent_register_print_function(struct pevent *pevent, pevent_func_handler func, enum pevent_func_arg_type ret_type, -- cgit v1.2.3 From 20c7e5abbd0cdfaa656f46af052a6e6a8ce94775 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:08 +0900 Subject: tools lib traceevent: Add pevent_unregister_print_function() When a plugin unloaded it needs to unregister its print handler from pevent. So add an unregister function to do it. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 23 +++++++++++++++++++++++ tools/lib/traceevent/event-parse.h | 2 ++ 2 files changed, 25 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index d1973cb8388b..1587ea392ad6 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -5560,6 +5560,29 @@ int pevent_register_print_function(struct pevent *pevent, return ret; } +/** + * pevent_unregister_print_function - unregister a helper function + * @pevent: the handle to the pevent + * @func: the function to process the helper function + * @name: the name of the helper function + * + * This function removes existing print handler for function @name. + * + * Returns 0 if the handler was removed successully, -1 otherwise. + */ +int pevent_unregister_print_function(struct pevent *pevent, + pevent_func_handler func, char *name) +{ + struct pevent_function_handler *func_handle; + + func_handle = find_func_handler(pevent, name); + if (func_handle && func_handle->func == func) { + remove_func_handler(pevent, name); + return 0; + } + return -1; +} + static struct event_format *pevent_search_event(struct pevent *pevent, int id, const char *sys_name, const char *event_name) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index c48acfbc6230..791c539374c7 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -631,6 +631,8 @@ int pevent_register_print_function(struct pevent *pevent, pevent_func_handler func, enum pevent_func_arg_type ret_type, char *name, ...); +int pevent_unregister_print_function(struct pevent *pevent, + pevent_func_handler func, char *name); struct format_field *pevent_find_common_field(struct event_format *event, const char *name); struct format_field *pevent_find_field(struct event_format *event, const char *name); -- cgit v1.2.3 From ac668c7b7d87c1895faf196a337b5ddfd32a0e21 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:09 +0900 Subject: tools lib traceevent: Unregister handler when function plugin is unloaded The function handler should be unregistered when the plugin is unloaded otherwise it'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_function.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_function.c b/tools/lib/traceevent/plugin_function.c index 39461485f9a7..80ba4ff1fe84 100644 --- a/tools/lib/traceevent/plugin_function.c +++ b/tools/lib/traceevent/plugin_function.c @@ -148,6 +148,9 @@ void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) { int i, x; + pevent_unregister_event_handler(pevent, -1, "ftrace", "function", + function_handler, NULL); + for (i = 0; i <= cpus; i++) { for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++) free(fstack[i].stack[x]); -- cgit v1.2.3 From 4061edaa54744dca833051119e763f073dd3c334 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:10 +0900 Subject: tools lib traceevent: Unregister handler when hrtimer plugin is unloaded The timer handlers should be unregistered when the plugin is unloaded otherwise they'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-5-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_hrtimer.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_hrtimer.c b/tools/lib/traceevent/plugin_hrtimer.c index 0b0ebf30aa44..12bf14cc1152 100644 --- a/tools/lib/traceevent/plugin_hrtimer.c +++ b/tools/lib/traceevent/plugin_hrtimer.c @@ -76,3 +76,13 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) timer_start_handler, NULL); return 0; } + +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) +{ + pevent_unregister_event_handler(pevent, -1, + "timer", "hrtimer_expire_entry", + timer_expire_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "timer", "hrtimer_start", + timer_start_handler, NULL); +} -- cgit v1.2.3 From 11e99c55414ebade1031a0ed3b49915824c7c3ea Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:11 +0900 Subject: tools lib traceevent: Unregister handler when kmem plugin is unloaded The kmem handlers should be unregistered when the plugin is unloaded otherwise they'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-6-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_kmem.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_kmem.c b/tools/lib/traceevent/plugin_kmem.c index 7115c8037ea8..70650ff48d78 100644 --- a/tools/lib/traceevent/plugin_kmem.c +++ b/tools/lib/traceevent/plugin_kmem.c @@ -70,3 +70,25 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) call_site_handler, NULL); return 0; } + +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) +{ + pevent_unregister_event_handler(pevent, -1, "kmem", "kfree", + call_site_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc", + call_site_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc_node", + call_site_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_alloc", + call_site_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "kmem", + "kmem_cache_alloc_node", + call_site_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_free", + call_site_handler, NULL); +} -- cgit v1.2.3 From 354a2bd0318e0758f93b8b24553f3376fa9dfa21 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:12 +0900 Subject: tools lib traceevent: Unregister handler when kvm plugin is unloaded The kvm handlers should be unregistered when the plugin is unloaded otherwise they'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-7-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_kvm.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_kvm.c b/tools/lib/traceevent/plugin_kvm.c index a0e282c6b967..9e0e8c61b43b 100644 --- a/tools/lib/traceevent/plugin_kvm.c +++ b/tools/lib/traceevent/plugin_kvm.c @@ -434,3 +434,32 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) PEVENT_FUNC_ARG_VOID); return 0; } + +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) +{ + pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_exit", + kvm_exit_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_emulate_insn", + kvm_emulate_insn_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page", + kvm_mmu_get_page_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page", + kvm_mmu_print_role, NULL); + + pevent_unregister_event_handler(pevent, -1, + "kvmmmu", "kvm_mmu_unsync_page", + kvm_mmu_print_role, NULL); + + pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page", + kvm_mmu_print_role, NULL); + + pevent_unregister_event_handler(pevent, -1, "kvmmmu", + "kvm_mmu_prepare_zap_page", kvm_mmu_print_role, + NULL); + + pevent_unregister_print_function(pevent, process_is_writable_pte, + "is_writable_pte"); +} -- cgit v1.2.3 From 02bafd377c1137d0705f224881cd21de123204f0 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:13 +0900 Subject: tools lib traceevent: Unregister handler when sched_switch plugin is unloaded The event handlers should be unregistered when the plugin is unloaded otherwise they'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-8-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_sched_switch.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c index fea3724aa24f..f1ce60065258 100644 --- a/tools/lib/traceevent/plugin_sched_switch.c +++ b/tools/lib/traceevent/plugin_sched_switch.c @@ -146,3 +146,15 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) sched_wakeup_handler, NULL); return 0; } + +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) +{ + pevent_unregister_event_handler(pevent, -1, "sched", "sched_switch", + sched_switch_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup", + sched_wakeup_handler, NULL); + + pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup_new", + sched_wakeup_handler, NULL); +} -- cgit v1.2.3 From ec7c6debdd446ad2262f236d13964efae90ba0f7 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:14 +0900 Subject: tools lib traceevent: Unregister handler when mac80211 plugin is unloaded The event handler should be unregistered when the plugin is unloaded otherwise it'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-9-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_mac80211.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_mac80211.c b/tools/lib/traceevent/plugin_mac80211.c index 558a3b91c046..7e15a0f1c2fd 100644 --- a/tools/lib/traceevent/plugin_mac80211.c +++ b/tools/lib/traceevent/plugin_mac80211.c @@ -93,3 +93,10 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) drv_bss_info_changed, NULL); return 0; } + +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) +{ + pevent_unregister_event_handler(pevent, -1, "mac80211", + "drv_bss_info_changed", + drv_bss_info_changed, NULL); +} -- cgit v1.2.3 From 6024cf3898d25088b01025d72a6929839de9c7b6 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:15 +0900 Subject: tools lib traceevent: Unregister handler when cfg80211 plugin is unloaded The function handler should be unregistered when the plugin is unloaded otherwise it'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-10-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_cfg80211.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_cfg80211.c b/tools/lib/traceevent/plugin_cfg80211.c index 57e98221db20..c066b25905f8 100644 --- a/tools/lib/traceevent/plugin_cfg80211.c +++ b/tools/lib/traceevent/plugin_cfg80211.c @@ -22,3 +22,9 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) PEVENT_FUNC_ARG_VOID); return 0; } + +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) +{ + pevent_unregister_print_function(pevent, process___le16_to_cpup, + "__le16_to_cpup"); +} -- cgit v1.2.3 From 0247a967d4c1986821b3c7cbad324468fa6f2ae3 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:16 +0900 Subject: tools lib traceevent: Unregister handler when jbd2 plugin is is unloaded The function handlers should be unregistered when the plugin unloaded otherwise they'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-11-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_jbd2.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_jbd2.c b/tools/lib/traceevent/plugin_jbd2.c index 2f93f81f0bac..0db714c721be 100644 --- a/tools/lib/traceevent/plugin_jbd2.c +++ b/tools/lib/traceevent/plugin_jbd2.c @@ -66,3 +66,12 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) PEVENT_FUNC_ARG_VOID); return 0; } + +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) +{ + pevent_unregister_print_function(pevent, process_jbd2_dev_to_name, + "jbd2_dev_to_name"); + + pevent_unregister_print_function(pevent, process_jiffies_to_msecs, + "jiffies_to_msecs"); +} -- cgit v1.2.3 From a157112cfc67b3889f6493933cbd32620aa4be18 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:17 +0900 Subject: tools lib traceevent: Unregister handler when scsi plugin is unloaded The function handler should be unregistered when the plugin is unloaded otherwise it'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-12-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_scsi.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_scsi.c b/tools/lib/traceevent/plugin_scsi.c index 7ef16cc96562..eda326fc8620 100644 --- a/tools/lib/traceevent/plugin_scsi.c +++ b/tools/lib/traceevent/plugin_scsi.c @@ -421,3 +421,9 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) PEVENT_FUNC_ARG_VOID); return 0; } + +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) +{ + pevent_unregister_print_function(pevent, process_scsi_trace_parse_cdb, + "scsi_trace_parse_cdb"); +} -- cgit v1.2.3 From bf6b3a95ff439b1dcd6151b3f38810f3cec1e319 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 16 Jan 2014 11:31:18 +0900 Subject: tools lib traceevent: Unregister handler when xen plugin is unloaded The function handler should be unregistered when the plugin is unloaded otherwise it'll try to access invalid memory. Signed-off-by: Namhyung Kim Reviewed-by: Jiri Olsa Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1389839478-5887-13-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/plugin_xen.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools/lib') diff --git a/tools/lib/traceevent/plugin_xen.c b/tools/lib/traceevent/plugin_xen.c index e7794298f3a9..3a413eaada68 100644 --- a/tools/lib/traceevent/plugin_xen.c +++ b/tools/lib/traceevent/plugin_xen.c @@ -128,3 +128,9 @@ int PEVENT_PLUGIN_LOADER(struct pevent *pevent) PEVENT_FUNC_ARG_VOID); return 0; } + +void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent) +{ + pevent_unregister_print_function(pevent, process_xen_hypercall_name, + "xen_hypercall_name"); +} -- cgit v1.2.3