From patchwork Mon Jan 6 15:40:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 11319547 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 44B5D14B4 for ; Mon, 6 Jan 2020 15:41:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EE77D20731 for ; Mon, 6 Jan 2020 15:41:08 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HCZb4Zr9" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726497AbgAFPlI (ORCPT ); Mon, 6 Jan 2020 10:41:08 -0500 Received: from mail-lf1-f43.google.com ([209.85.167.43]:45102 "EHLO mail-lf1-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726296AbgAFPlI (ORCPT ); Mon, 6 Jan 2020 10:41:08 -0500 Received: by mail-lf1-f43.google.com with SMTP id 203so36608911lfa.12 for ; Mon, 06 Jan 2020 07:41:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=v6zohj5xtFojEoiwzyzjq6+tPt29IyMPlugWGhisugU=; b=HCZb4Zr9/1rG1zOabzUYe65LQHWSfxxjFqG0Sjr32JkC6s8YzodRN7Rdq2BN29BdLB OuHfRgubdWMSz6lLAWQjxtCgEIZr/glqWEssM92GlBvZem3L2j1QqOOsnjO/yApHB3XS wVMOS05FB/I+lMX9UHQFNJ4Q1XfN5P1yGdwlsrA2IZ0laXW0quPROS5w+iMT0YWXjQ+t Vv3lS/r9L4S9oW4jlHanZ93WTIe8KXK+W9gGj9TVztPLZw5wHw/16tAaq3S73jzClRRa gY5YT03NEUtxiBj85ptIKRwpjPpAq1Jwpz6TyoQzQp+RhT16uJVGjucgOg8XvHDJ2yOc gWjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=v6zohj5xtFojEoiwzyzjq6+tPt29IyMPlugWGhisugU=; b=sfkDxlM09CxSoARBojz1TasnznGcWol6JhDB3YSdfdcawnYh9K11nji6R8ulB9w+1T G2xVt/lCrTtL6y7z1uWVv9vbBuF2QRw3HbFoGN8U7eTZJqXglhsQg6UcwDaluzVfuh6G 4vlHhOJR7CH0mc18f7y4AvZAhhd6OFeRfLk8rNdBRlLWsTdF62njs+rWvow1pyD7hdaI KwibGKwkrhKsN71H6COfH1dR0QlmYMUrPbWasa5YTLvcmeMP1vWaseqSk0Nd8NM9QaSD 6qX5OsGlEmJuxV4WNqaycY0Uoqkm1zkG8ML6gZ57Cawa4b5yNrcMZZQTtsc44mVSmdhm FLDQ== X-Gm-Message-State: APjAAAU66rf/s/krb8eMvt5hPZdP+uE8fCd+2zLZoEsFwI2lbECAwFKW 62qYxpHX0Oap1kafRslMB+jR7msXZJo= X-Google-Smtp-Source: APXvYqxAwwrgjPbGEDZMA/7n34zNLgPwt/J20klEGLQa2yq7COuMIVEjpm1hzA33b17X15dHRCyvHQ== X-Received: by 2002:a19:f10e:: with SMTP id p14mr56941555lfh.3.1578325262386; Mon, 06 Jan 2020 07:41:02 -0800 (PST) Received: from oberon.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id u25sm29257677lfk.46.2020.01.06.07.41.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jan 2020 07:41:01 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 1/5] trace-cmd: Introduce libtracefs library Date: Mon, 6 Jan 2020 17:40:54 +0200 Message-Id: <20200106154058.60660-2-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200106154058.60660-1-tz.stoyanov@gmail.com> References: <20200106154058.60660-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Add a skeleton for new library: libtracefs. It provides APIs for accessing files from tracefs. - Added new directories lib/tracefs include/tracefs - Integrated the libtracefs build into the trace-cmd compilation - The library is installed by "make install_libs" in: libtrasefs.so in $(libdir)/tracefs trasefs.h in $(includedir)/tracefs - Added implementation of initial APIs: char *tracefs_get_tracing_file(const char *name); void tracefs_put_tracing_file(char *name); const char *tracefs_get_tracing_dir(void); char *tracefs_find_tracing_dir(void); Signed-off-by: Tzvetomir Stoyanov (VMware) --- Makefile | 27 +++- include/trace-cmd/trace-cmd.h | 9 -- include/tracefs/tracefs.h | 20 +++ lib/trace-cmd/trace-output.c | 3 +- lib/trace-cmd/trace-recorder.c | 7 +- lib/trace-cmd/trace-util.c | 136 --------------------- lib/tracefs/Makefile | 46 +++++++ lib/tracefs/include/tracefs-local.h | 12 ++ lib/tracefs/tracefs-utils.c | 183 ++++++++++++++++++++++++++++ tracecmd/Makefile | 2 +- tracecmd/trace-check-events.c | 3 +- tracecmd/trace-list.c | 19 +-- tracecmd/trace-record.c | 127 +++++++++---------- tracecmd/trace-show.c | 5 +- tracecmd/trace-snapshot.c | 9 +- tracecmd/trace-stack.c | 9 +- tracecmd/trace-stat.c | 17 +-- 17 files changed, 390 insertions(+), 244 deletions(-) create mode 100644 include/tracefs/tracefs.h create mode 100644 lib/tracefs/Makefile create mode 100644 lib/tracefs/include/tracefs-local.h create mode 100644 lib/tracefs/tracefs-utils.c diff --git a/Makefile b/Makefile index 48d88e7..aa803ba 100644 --- a/Makefile +++ b/Makefile @@ -183,12 +183,19 @@ LIBTRACECMD_DIR = $(obj)/lib/trace-cmd LIBTRACECMD_STATIC = $(LIBTRACECMD_DIR)/libtracecmd.a LIBTRACECMD_SHARED = $(LIBTRACECMD_DIR)/libtracecmd.so -TRACE_LIBS = -L$(LIBTRACECMD_DIR) -ltracecmd -L$(LIBTRACEEVENT_DIR) -ltraceevent +LIBTRACEFS_DIR = $(obj)/lib/tracefs +LIBTRACEFS_STATIC = $(LIBTRACEFS_DIR)/libtracefs.a +LIBTRACEFS_SHARED = $(LIBTRACEFS_DIR)/libtracefs.so + +TRACE_LIBS = -L$(LIBTRACECMD_DIR) -ltracecmd \ + -L$(LIBTRACEEVENT_DIR) -ltraceevent \ + -L$(LIBTRACEFS_DIR) -ltracefs export LIBS TRACE_LIBS export LIBTRACEEVENT_DIR LIBTRACECMD_DIR export LIBTRACECMD_STATIC LIBTRACECMD_SHARED export LIBTRACEEVENT_STATIC LIBTRACEEVENT_SHARED +export LIBTRACEFS_STATIC LIBTRACEFS_SHARED export Q SILENT VERBOSE EXT @@ -198,8 +205,10 @@ include scripts/utils.mk INCLUDES = -I$(src)/include -I$(src)/../../include INCLUDES += -I$(src)/include/traceevent INCLUDES += -I$(src)/include/trace-cmd +INCLUDES += -I$(src)/include/tracefs INCLUDES += -I$(src)/lib/traceevent/include INCLUDES += -I$(src)/lib/trace-cmd/include +INCLUDES += -I$(src)/lib/tracefs/include INCLUDES += -I$(src)/tracecmd/include INCLUDES += -I$(obj)/tracecmd/include @@ -277,7 +286,7 @@ gui: force $(CMD_TARGETS) $(kshark-dir)/build/Makefile @echo "gui build complete" @echo " kernelshark located at $(kshark-dir)/bin" -trace-cmd: force $(LIBTRACEEVENT_STATIC) $(LIBTRACECMD_STATIC) +trace-cmd: force $(LIBTRACEEVENT_STATIC) $(LIBTRACECMD_STATIC) $(LIBTRACEFS_STATIC) $(Q)$(MAKE) -C $(src)/tracecmd $(obj)/tracecmd/$@ $(LIBTRACEEVENT_SHARED): force $(obj)/lib/traceevent/plugins/traceevent_plugin_dir @@ -292,12 +301,21 @@ $(LIBTRACECMD_STATIC): force $(LIBTRACECMD_SHARED): force $(Q)$(MAKE) -C $(src)/lib/trace-cmd $@ +$(LIBTRACEFS_STATIC): force + $(Q)$(MAKE) -C $(src)/lib/tracefs $@ + +$(LIBTRACEFS_SHARED): force + $(Q)$(MAKE) -C $(src)/lib/tracefs $@ + + libtraceevent.so: $(LIBTRACEEVENT_SHARED) libtraceevent.a: $(LIBTRACEEVENT_STATIC) libtracecmd.a: $(LIBTRACECMD_STATIC) libtracecmd.so: $(LIBTRACECMD_SHARED) +libtracefs.a: $(LIBTRACEFS_STATIC) +libtracefs.so: $(LIBTRACEFS_SHARED) -libs: $(LIBTRACECMD_SHARED) $(LIBTRACEEVENT_SHARED) +libs: $(LIBTRACECMD_SHARED) $(LIBTRACEEVENT_SHARED) $(LIBTRACEFS_SHARED) plugins: force $(obj)/lib/traceevent/plugins/traceevent_plugin_dir $(obj)/lib/traceevent/plugins/trace_python_dir $(Q)$(MAKE) -C $(src)/lib/traceevent/plugins @@ -353,10 +371,12 @@ install_gui: install_cmd gui install_libs: libs $(Q)$(call do_install,$(LIBTRACECMD_SHARED),$(libdir_SQ)/trace-cmd) $(Q)$(call do_install,$(LIBTRACEEVENT_SHARED),$(libdir_SQ)/traceevent) + $(Q)$(call do_install,$(LIBTRACEFS_SHARED),$(libdir_SQ)/tracefs) $(Q)$(call do_install,$(src)/include/traceevent/event-parse.h,$(includedir_SQ)/traceevent) $(Q)$(call do_install,$(src)/include/traceevent/trace-seq.h,$(includedir_SQ)/traceevent) $(Q)$(call do_install,$(src)/include/trace-cmd/trace-cmd.h,$(includedir_SQ)/trace-cmd) $(Q)$(call do_install,$(src)/include/trace-cmd/trace-filter-hash.h,$(includedir_SQ)/trace-cmd) + $(Q)$(call do_install,$(src)/include/tracefs/tracefs.h,$(includedir_SQ)/tracefs) doc: $(MAKE) -C $(src)/Documentation all @@ -379,6 +399,7 @@ clean: $(RM) tags TAGS cscope* $(MAKE) -C $(src)/lib/traceevent clean $(MAKE) -C $(src)/lib/trace-cmd clean + $(MAKE) -C $(src)/lib/tracefs clean $(MAKE) -C $(src)/lib/traceevent/plugins clean $(MAKE) -C $(src)/python clean $(MAKE) -C $(src)/tracecmd clean diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 13afce7..66736ae 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -64,12 +64,6 @@ static inline int tracecmd_host_bigendian(void) return *ptr == 0x01020304; } -/* tracecmd_get_tracing_dir must *not* be freed */ -const char *tracecmd_get_tracing_dir(void); - -/* tracecmd_find_tracing_dir must be freed */ -char *tracecmd_find_tracing_dir(void); - /* --- Opening and Reading the trace.dat file --- */ enum { @@ -208,9 +202,6 @@ tracecmd_get_show_data_func(struct tracecmd_input *handle); void tracecmd_set_show_data_func(struct tracecmd_input *handle, tracecmd_show_data_func func); -char *tracecmd_get_tracing_file(const char *name); -void tracecmd_put_tracing_file(char *name); - int tracecmd_record_at_buffer_start(struct tracecmd_input *handle, struct tep_record *record); unsigned long long tracecmd_page_ts(struct tracecmd_input *handle, struct tep_record *record); diff --git a/include/tracefs/tracefs.h b/include/tracefs/tracefs.h new file mode 100644 index 0000000..e844c75 --- /dev/null +++ b/include/tracefs/tracefs.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/* + * Copyright (C) 2019, VMware, Tzvetomir Stoyanov + * + */ +#ifndef _TRACE_FS_H +#define _TRACE_FS_H + +#include "traceevent/event-parse.h" + +char *tracefs_get_tracing_file(const char *name); +void tracefs_put_tracing_file(char *name); + +/* tracefs_get_tracing_dir must *not* be freed */ +const char *tracefs_get_tracing_dir(void); + +/* tracefs_find_tracing_dir must be freed */ +char *tracefs_find_tracing_dir(void); + +#endif /* _TRACE_FS_H */ diff --git a/lib/trace-cmd/trace-output.c b/lib/trace-cmd/trace-output.c index be4d3f5..a3dda27 100644 --- a/lib/trace-cmd/trace-output.c +++ b/lib/trace-cmd/trace-output.c @@ -20,6 +20,7 @@ #include #include +#include "tracefs.h" #include "trace-cmd-local.h" #include "list.h" #include "trace-msg.h" @@ -238,7 +239,7 @@ static tsize_t copy_file(struct tracecmd_output *handle, static const char *find_tracing_dir(struct tracecmd_output *handle) { if (!handle->tracing_dir) - handle->tracing_dir = tracecmd_find_tracing_dir(); + handle->tracing_dir = tracefs_find_tracing_dir(); return handle->tracing_dir; } diff --git a/lib/trace-cmd/trace-recorder.c b/lib/trace-cmd/trace-recorder.c index 36c9a96..2a6e2b6 100644 --- a/lib/trace-cmd/trace-recorder.c +++ b/lib/trace-cmd/trace-recorder.c @@ -12,6 +12,7 @@ #include #include +#include "tracefs.h" #include "trace-cmd.h" #include "event-utils.h" @@ -306,7 +307,7 @@ struct tracecmd_recorder *tracecmd_create_recorder_fd(int fd, int cpu, unsigned { const char *tracing; - tracing = tracecmd_get_tracing_dir(); + tracing = tracefs_get_tracing_dir(); if (!tracing) { errno = ENODEV; return NULL; @@ -319,7 +320,7 @@ struct tracecmd_recorder *tracecmd_create_recorder(const char *file, int cpu, un { const char *tracing; - tracing = tracecmd_get_tracing_dir(); + tracing = tracefs_get_tracing_dir(); if (!tracing) { errno = ENODEV; return NULL; @@ -333,7 +334,7 @@ tracecmd_create_recorder_maxkb(const char *file, int cpu, unsigned flags, int ma { const char *tracing; - tracing = tracecmd_get_tracing_dir(); + tracing = tracefs_get_tracing_dir(); if (!tracing) { errno = ENODEV; return NULL; diff --git a/lib/trace-cmd/trace-util.c b/lib/trace-cmd/trace-util.c index b5bb0d5..1394469 100644 --- a/lib/trace-cmd/trace-util.c +++ b/lib/trace-cmd/trace-util.c @@ -23,8 +23,6 @@ #include "event-utils.h" #define LOCAL_PLUGIN_DIR ".trace-cmd/plugins" -#define TRACEFS_PATH "/sys/kernel/tracing" -#define DEBUGFS_PATH "/sys/kernel/debug" #define PROC_STACK_FILE "/proc/sys/kernel/stack_tracer_enabled" int tracecmd_disable_sys_plugins; @@ -33,9 +31,6 @@ static bool debug; static FILE *logfp; -#define _STR(x) #x -#define STR(x) _STR(x) - /** * tracecmd_set_debug - Set debug mode of the tracecmd library * @set_debug: The new "debug" mode. If true, the tracecmd library is @@ -147,113 +142,6 @@ void tracecmd_parse_ftrace_printk(struct tep_handle *pevent, } } -static int mount_debugfs(void) -{ - struct stat st; - int ret; - - /* make sure debugfs exists */ - ret = stat(DEBUGFS_PATH, &st); - if (ret < 0) - return -1; - - ret = mount("nodev", DEBUGFS_PATH, - "debugfs", 0, NULL); - - return ret; -} - -static int mount_tracefs(void) -{ - struct stat st; - int ret; - - /* make sure debugfs exists */ - ret = stat(TRACEFS_PATH, &st); - if (ret < 0) - return -1; - - ret = mount("nodev", TRACEFS_PATH, - "tracefs", 0, NULL); - - return ret; -} - -char *tracecmd_find_tracing_dir(void) -{ - char *debug_str = NULL; - char fspath[PATH_MAX+1]; - char *tracing_dir; - char type[100]; - int use_debug = 0; - FILE *fp; - - if ((fp = fopen("/proc/mounts","r")) == NULL) { - warning("Can't open /proc/mounts for read"); - return NULL; - } - - while (fscanf(fp, "%*s %" - STR(PATH_MAX) - "s %99s %*s %*d %*d\n", - fspath, type) == 2) { - if (strcmp(type, "tracefs") == 0) - break; - if (!debug_str && strcmp(type, "debugfs") == 0) { - debug_str = strdup(fspath); - if (!debug_str) { - fclose(fp); - return NULL; - } - } - } - fclose(fp); - - if (strcmp(type, "tracefs") != 0) { - if (mount_tracefs() < 0) { - if (debug_str) { - strncpy(fspath, debug_str, PATH_MAX); - fspath[PATH_MAX] = 0; - } else { - if (mount_debugfs() < 0) { - warning("debugfs not mounted, please mount"); - free(debug_str); - return NULL; - } - strcpy(fspath, DEBUGFS_PATH); - } - use_debug = 1; - } else - strcpy(fspath, TRACEFS_PATH); - } - free(debug_str); - - if (use_debug) { - int ret; - - ret = asprintf(&tracing_dir, "%s/tracing", fspath); - if (ret < 0) - return NULL; - } else { - tracing_dir = strdup(fspath); - if (!tracing_dir) - return NULL; - } - - return tracing_dir; -} - -const char *tracecmd_get_tracing_dir(void) -{ - static const char *tracing_dir; - - if (tracing_dir) - return tracing_dir; - - tracing_dir = tracecmd_find_tracing_dir(); - return tracing_dir; -} - /* FIXME: append_file() is duplicated and could be consolidated */ static char *append_file(const char *dir, const char *name) { @@ -863,30 +751,6 @@ void trace_util_free_plugin_files(char **files) free(files); } -char *tracecmd_get_tracing_file(const char *name) -{ - static const char *tracing; - char *file; - int ret; - - if (!tracing) { - tracing = tracecmd_find_tracing_dir(); - if (!tracing) - return NULL; - } - - ret = asprintf(&file, "%s/%s", tracing, name); - if (ret < 0) - return NULL; - - return file; -} - -void tracecmd_put_tracing_file(char *name) -{ - free(name); -} - void __noreturn __vdie(const char *fmt, va_list ap) { int ret = errno; diff --git a/lib/tracefs/Makefile b/lib/tracefs/Makefile new file mode 100644 index 0000000..86d7845 --- /dev/null +++ b/lib/tracefs/Makefile @@ -0,0 +1,46 @@ + + +include $(src)/scripts/utils.mk + +bdir:=$(obj)/lib/tracefs + +DEFAULT_TARGET = $(bdir)/libtracefs.a + +OBJS = +OBJS += tracefs-utils.o + +OBJS := $(OBJS:%.o=$(bdir)/%.o) +DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) + +all: $(DEFAULT_TARGET) + +$(bdir): + @mkdir -p $(bdir) + +$(OBJS): | $(bdir) +$(DEPS): | $(bdir) + +$(bdir)/libtracefs.a: $(OBJS) + $(Q)$(call do_build_static_lib) + +$(bdir)/libtracefs.so: $(OBJS) + $(Q)$(call do_compile_shared_library) + +$(bdir)/%.o: %.c + $(Q)$(call do_fpic_compile) + +$(DEPS): $(bdir)/.%.d: %.c + $(Q)$(CC) -M $(CPPFLAGS) $(CFLAGS) $< > $@ + +$(OBJS): $(bdir)/%.o : $(bdir)/.%.d + +dep_includes := $(wildcard $(DEPS)) + +ifneq ($(dep_includes),) + include $(dep_includes) +endif + +clean: + $(RM) $(bdir)/*.a $(bdir)/*.so $(bdir)/*.o $(bdir)/.*.d + +.PHONY: clean diff --git a/lib/tracefs/include/tracefs-local.h b/lib/tracefs/include/tracefs-local.h new file mode 100644 index 0000000..231edd1 --- /dev/null +++ b/lib/tracefs/include/tracefs-local.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/* + * Copyright (C) 2019, VMware, Tzvetomir Stoyanov + * + */ +#ifndef _TRACE_FS_LOCAL_H +#define _TRACE_FS_LOCAL_H + +/* Can be overridden */ +void warning(const char *fmt, ...); + +#endif /* _TRACE_FS_LOCAL_H */ diff --git a/lib/tracefs/tracefs-utils.c b/lib/tracefs/tracefs-utils.c new file mode 100644 index 0000000..0ef16fc --- /dev/null +++ b/lib/tracefs/tracefs-utils.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt + * + * Updates: + * Copyright (C) 2019, VMware, Tzvetomir Stoyanov + * + */ +#include +#include +#include +#include + +#include "tracefs.h" + +#define TRACEFS_PATH "/sys/kernel/tracing" +#define DEBUGFS_PATH "/sys/kernel/debug" + +#define _STR(x) #x +#define STR(x) _STR(x) + +void __attribute__((weak)) warning(const char *fmt, ...) +{ +} + +static int mount_tracefs(void) +{ + struct stat st; + int ret; + + /* make sure debugfs exists */ + ret = stat(TRACEFS_PATH, &st); + if (ret < 0) + return -1; + + ret = mount("nodev", TRACEFS_PATH, + "tracefs", 0, NULL); + + return ret; +} + +static int mount_debugfs(void) +{ + struct stat st; + int ret; + + /* make sure debugfs exists */ + ret = stat(DEBUGFS_PATH, &st); + if (ret < 0) + return -1; + + ret = mount("nodev", DEBUGFS_PATH, + "debugfs", 0, NULL); + + return ret; +} + +/** + * tracefs_find_tracing_dir - Find tracing directory + * + * Returns string containing the full path to the system's tracing directory. + * The string must be freed by free() + */ +char *tracefs_find_tracing_dir(void) +{ + char *debug_str = NULL; + char fspath[PATH_MAX+1]; + char *tracing_dir; + char type[100]; + int use_debug = 0; + FILE *fp; + + fp = fopen("/proc/mounts", "r"); + if (!fp) { + warning("Can't open /proc/mounts for read"); + return NULL; + } + + while (fscanf(fp, "%*s %" + STR(PATH_MAX) + "s %99s %*s %*d %*d\n", + fspath, type) == 2) { + if (strcmp(type, "tracefs") == 0) + break; + if (!debug_str && strcmp(type, "debugfs") == 0) { + debug_str = strdup(fspath); + if (!debug_str) { + fclose(fp); + return NULL; + } + } + } + fclose(fp); + + if (strcmp(type, "tracefs") != 0) { + if (mount_tracefs() < 0) { + if (debug_str) { + strncpy(fspath, debug_str, PATH_MAX); + fspath[PATH_MAX] = 0; + } else { + if (mount_debugfs() < 0) { + warning("debugfs not mounted, please mount"); + free(debug_str); + return NULL; + } + strcpy(fspath, DEBUGFS_PATH); + } + use_debug = 1; + } else + strcpy(fspath, TRACEFS_PATH); + } + free(debug_str); + + if (use_debug) { + int ret; + + ret = asprintf(&tracing_dir, "%s/tracing", fspath); + if (ret < 0) + return NULL; + } else { + tracing_dir = strdup(fspath); + if (!tracing_dir) + return NULL; + } + + return tracing_dir; +} + +/** + * tracefs_get_tracing_dir - Get tracing directory + * + * Returns string containing the full path to the system's tracing directory. + * Must use tracefs_put_tracing_file() to free the returned string. + */ +const char *tracefs_get_tracing_dir(void) +{ + static const char *tracing_dir; + + if (tracing_dir) + return tracing_dir; + + tracing_dir = tracefs_find_tracing_dir(); + return tracing_dir; +} + +/** + * tracefs_get_tracing_file - Get tracing file + * @name: tracing file name + * + * Returns string containing the full path to a tracing file in + * the system's tracing directory. + * + * Must use tracefs_put_tracing_file() to free the returned string. + */ +char *tracefs_get_tracing_file(const char *name) +{ + static const char *tracing; + char *file; + int ret; + + if (!tracing) { + tracing = tracefs_find_tracing_dir(); + if (!tracing) + return NULL; + } + + ret = asprintf(&file, "%s/%s", tracing, name); + if (ret < 0) + return NULL; + + return file; +} + +/** + * tracefs_put_tracing_file - Free tracing file or directory name + * + * Frees tracing file or directory, returned by + * tracefs_get_tracing_file() or tracefs_get_tracing_dir() APIs + */ +void tracefs_put_tracing_file(char *name) +{ + free(name); +} diff --git a/tracecmd/Makefile b/tracecmd/Makefile index 29a623b..d00d8e0 100644 --- a/tracecmd/Makefile +++ b/tracecmd/Makefile @@ -62,7 +62,7 @@ $(all_objs): | $(bdir) $(bdir)/trace-cmd: $(ALL_OBJS) $(Q)$(do_app_build) -$(bdir)/trace-cmd: $(LIBTRACECMD_STATIC) $(LIBTRACEEVENT_STATIC) +$(bdir)/trace-cmd: $(LIBTRACECMD_STATIC) $(LIBTRACEEVENT_STATIC) $(LIBTRACEFS_STATIC) $(bdir)/%.o: %.c $(Q)$(call do_compile) diff --git a/tracecmd/trace-check-events.c b/tracecmd/trace-check-events.c index b09fcd0..a8ee60a 100644 --- a/tracecmd/trace-check-events.c +++ b/tracecmd/trace-check-events.c @@ -7,6 +7,7 @@ #include #include +#include "tracefs.h" #include "trace-local.h" void trace_check_events(int argc, char **argv) @@ -28,7 +29,7 @@ void trace_check_events(int argc, char **argv) break; } } - tracing = tracecmd_get_tracing_dir(); + tracing = tracefs_get_tracing_dir(); if (!tracing) { printf("Can not find or mount tracing directory!\n" diff --git a/tracecmd/trace-list.c b/tracecmd/trace-list.c index 65099a5..86e3358 100644 --- a/tracecmd/trace-list.c +++ b/tracecmd/trace-list.c @@ -6,6 +6,7 @@ #include +#include "tracefs.h" #include "trace-local.h" @@ -35,7 +36,7 @@ void show_instance_file(struct buffer_instance *instance, const char *name) path = get_instance_file(instance, name); dump_file_content(path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } enum { @@ -49,9 +50,9 @@ void show_file(const char *name) { char *path; - path = tracecmd_get_tracing_file(name); + path = tracefs_get_tracing_file(name); dump_file_content(path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } typedef int (*process_file_func)(char *buf, int len); @@ -86,11 +87,11 @@ static void process_file_re(process_file_func func, free(str); - path = tracecmd_get_tracing_file(name); + path = tracefs_get_tracing_file(name); fp = fopen(path, "r"); if (!fp) die("reading %s", path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); do { n = getline(&buf, &l, fp); @@ -132,12 +133,12 @@ static char *get_event_file(const char *type, char *buf, int len) if (!event) die("no event found in %s\n", buf); - path = tracecmd_get_tracing_file("events"); + path = tracefs_get_tracing_file("events"); ret = asprintf(&file, "%s/%s/%s/%s", path, system, event, type); if (ret < 0) die("Failed to allocate event file %s %s", system, event); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return file; } @@ -282,9 +283,9 @@ static void show_buffers(void) char *path; int printed = 0; - path = tracecmd_get_tracing_file("instances"); + path = tracefs_get_tracing_file("instances"); dir = opendir(path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (!dir) die("Can not read instance directory"); diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 80b2234..5355813 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -39,6 +39,7 @@ #include #endif +#include "tracefs.h" #include "version.h" #include "trace-local.h" #include "trace-msg.h" @@ -337,21 +338,21 @@ static void test_set_event_pid(void) if (tested) return; - path = tracecmd_get_tracing_file("set_event_pid"); + path = tracefs_get_tracing_file("set_event_pid"); ret = stat(path, &st); if (!ret) { have_set_event_pid = 1; reset_save_file(path, RESET_DEFAULT_PRIO); } - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); - path = tracecmd_get_tracing_file("options/event-fork"); + path = tracefs_get_tracing_file("options/event-fork"); ret = stat(path, &st); if (!ret) { have_event_fork = 1; reset_save_file(path, RESET_DEFAULT_PRIO); } - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); tested = 1; } @@ -442,13 +443,13 @@ static int __add_all_instances(const char *tracing_dir) */ void add_all_instances(void) { - char *tracing_dir = tracecmd_find_tracing_dir(); + char *tracing_dir = tracefs_find_tracing_dir(); if (!tracing_dir) die("malloc"); __add_all_instances(tracing_dir); - tracecmd_put_tracing_file(tracing_dir); + tracefs_put_tracing_file(tracing_dir); } /** @@ -474,7 +475,7 @@ void tracecmd_stat_cpu_instance(struct buffer_instance *instance, path = get_instance_file(instance, file); free(file); fd = open(path, O_RDONLY); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (fd < 0) return; @@ -772,9 +773,9 @@ static int set_ftrace(int set, int use_proc) int ret; /* First check if the function-trace option exists */ - path = tracecmd_get_tracing_file("options/function-trace"); + path = tracefs_get_tracing_file("options/function-trace"); ret = set_ftrace_enable(path, set); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); /* Always enable ftrace_enable proc file when set is true */ if (ret < 0 || set || use_proc) @@ -790,7 +791,7 @@ static int set_ftrace(int set, int use_proc) * * Returns the path name of the @file for the given @instance. * - * Must use tracecmd_put_tracing_file() to free the returned string. + * Must use tracefs_put_tracing_file() to free the returned string. */ char * get_instance_file(struct buffer_instance *instance, const char *file) @@ -803,10 +804,10 @@ get_instance_file(struct buffer_instance *instance, const char *file) ret = asprintf(&buf, "instances/%s/%s", instance->name, file); if (ret < 0) die("Failed to allocate name for %s/%s", instance->name, file); - path = tracecmd_get_tracing_file(buf); + path = tracefs_get_tracing_file(buf); free(buf); } else - path = tracecmd_get_tracing_file(file); + path = tracefs_get_tracing_file(file); return path; } @@ -825,7 +826,7 @@ get_instance_dir(struct buffer_instance *instance) ret = asprintf(&buf, "instances/%s", instance->name); if (ret < 0) die("Failed to allocate for instance %s", instance->name); - path = tracecmd_get_tracing_file(buf); + path = tracefs_get_tracing_file(buf); free(buf); return path; @@ -868,7 +869,7 @@ write_instance_file(struct buffer_instance *instance, ret = stat(path, &st); if (ret == 0) ret = write_file(path, str, type); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return ret; } @@ -886,7 +887,7 @@ static void __clear_trace(struct buffer_instance *instance) fp = fopen(path, "w"); if (!fp) die("writing to '%s'", path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); fwrite("0", 1, 1, fp); fclose(fp); } @@ -905,11 +906,11 @@ static void clear_trace(void) char *path; /* reset the trace */ - path = tracecmd_get_tracing_file("trace"); + path = tracefs_get_tracing_file("trace"); fp = fopen(path, "w"); if (!fp) die("writing to '%s'", path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); fwrite("0", 1, 1, fp); fclose(fp); } @@ -956,7 +957,7 @@ static void update_ftrace_pid(const char *pid, int reset) if (fd >= 0) close(fd); if (path) - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); fd = -1; path = NULL; return; @@ -970,7 +971,7 @@ static void update_ftrace_pid(const char *pid, int reset) if (fd < 0) { if (!path) - path = tracecmd_get_tracing_file("set_ftrace_pid"); + path = tracefs_get_tracing_file("set_ftrace_pid"); if (!path) return; ret = stat(path, &st); @@ -1601,12 +1602,12 @@ set_plugin_instance(struct buffer_instance *instance, const char *name) * plugin for those if name is "nop". */ if (!strncmp(name, "nop", 3)) { - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return; } die("writing to '%s'", path); } - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); fwrite(name, 1, strlen(name), fp); fclose(fp); @@ -1619,11 +1620,11 @@ set_plugin_instance(struct buffer_instance *instance, const char *name) path = get_instance_file(instance, "options/func_stack_trace"); fp = fopen(path, "w"); if (!fp) { - tracecmd_put_tracing_file(path); - path = tracecmd_get_tracing_file("options/func_stack_trace"); + tracefs_put_tracing_file(path); + path = tracefs_get_tracing_file("options/func_stack_trace"); fp = fopen(path, "w"); if (!fp) { - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return; } } @@ -1632,7 +1633,7 @@ set_plugin_instance(struct buffer_instance *instance, const char *name) * the original content. */ add_reset_file(path, "0", RESET_HIGH_PRIO); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); fwrite(&zero, 1, 1, fp); fclose(fp); } @@ -1662,11 +1663,11 @@ static int set_option(const char *option) FILE *fp; char *path; - path = tracecmd_get_tracing_file("trace_options"); + path = tracefs_get_tracing_file("trace_options"); fp = fopen(path, "w"); if (!fp) warning("writing to '%s'", path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (!fp) return -1; @@ -1693,7 +1694,7 @@ static void disable_func_stack_trace_instance(struct buffer_instance *instance) path = get_instance_file(instance, "current_tracer"); ret = stat(path, &st); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (ret < 0) return; @@ -1727,7 +1728,7 @@ static void add_reset_options(void) if (keep) return; - path = tracecmd_get_tracing_file("trace_options"); + path = tracefs_get_tracing_file("trace_options"); content = get_file_content(path); for (opt = options; opt; opt = opt->next) { @@ -1790,7 +1791,7 @@ static void add_reset_options(void) add_reset_file(path, option, RESET_DEFAULT_PRIO); } - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); free(content); } @@ -1819,14 +1820,14 @@ static void set_saved_cmdlines_size(struct common_record_context *ctx) if (!ctx->saved_cmdlines_size) return; - path = tracecmd_get_tracing_file("saved_cmdlines_size"); + path = tracefs_get_tracing_file("saved_cmdlines_size"); if (!path) goto err; reset_save_file(path, RESET_DEFAULT_PRIO); fd = open(path, O_WRONLY); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (fd < 0) goto err; @@ -1852,7 +1853,7 @@ static int trace_check_file_exists(struct buffer_instance *instance, char *file) path = get_instance_file(instance, file); ret = stat(path, &st); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return ret < 0 ? 0 : 1; } @@ -1884,11 +1885,11 @@ static void old_update_events(const char *name, char update) name = "*:*"; /* need to use old way */ - path = tracecmd_get_tracing_file("set_event"); + path = tracefs_get_tracing_file("set_event"); fp = fopen(path, "w"); if (!fp) die("opening '%s'", path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); /* Disable the event with "!" */ if (update == '0') @@ -1935,12 +1936,12 @@ reset_events_instance(struct buffer_instance *instance) die("opening to '%s'", path); ret = write(fd, &c, 1); close(fd); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); path = get_instance_file(instance, "events/*/filter"); globbuf.gl_offs = 0; ret = glob(path, 0, NULL, &globbuf); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (ret < 0) return; @@ -2182,9 +2183,9 @@ static void check_tracing_enabled(void) char *path; if (fd < 0) { - path = tracecmd_get_tracing_file("tracing_enabled"); + path = tracefs_get_tracing_file("tracing_enabled"); fd = open(path, O_WRONLY | O_CLOEXEC); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (fd < 0) return; @@ -2205,7 +2206,7 @@ static int open_instance_fd(struct buffer_instance *instance, if (is_top_instance(instance)) die("opening '%s'", path); } - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return fd; } @@ -2526,7 +2527,7 @@ static void set_mask(struct buffer_instance *instance) close(fd); out: - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); free(instance->cpumask); instance->cpumask = NULL; } @@ -2583,7 +2584,7 @@ static void set_clock(struct buffer_instance *instance) add_reset_file(path, str, RESET_DEFAULT_PRIO); free(content); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); write_instance_file(instance, "trace_clock", instance->clock, "clock"); } @@ -2598,7 +2599,7 @@ static void set_max_graph_depth(struct buffer_instance *instance, char *max_grap path = get_instance_file(instance, "max_graph_depth"); reset_save_file(path, RESET_DEFAULT_PRIO); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); ret = write_instance_file(instance, "max_graph_depth", max_graph_depth, NULL); if (ret < 0) @@ -2721,7 +2722,7 @@ static int expand_event_files(struct buffer_instance *instance, globbuf.gl_offs = 0; ret = glob(path, 0, NULL, &globbuf); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); free(p); if (ret < 0) @@ -3182,7 +3183,7 @@ create_recorder_instance_pipe(struct buffer_instance *instance, if (instance->name) path = get_instance_dir(instance); else - path = tracecmd_find_tracing_dir(); + path = tracefs_find_tracing_dir(); if (!path) die("malloc"); @@ -3193,7 +3194,7 @@ create_recorder_instance_pipe(struct buffer_instance *instance, recorder = tracecmd_create_buffer_recorder_fd(brass[1], cpu, flags, path); if (instance->name) - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return recorder; } @@ -3234,7 +3235,7 @@ create_recorder_instance(struct buffer_instance *instance, const char *file, int record = tracecmd_create_buffer_recorder_maxkb(file, cpu, recorder_flags, path, max_kb); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return record; } @@ -3287,9 +3288,9 @@ static int create_recorder(struct buffer_instance *instance, int cpu, if (instance->name && !is_agent(instance)) path = get_instance_dir(instance); else - path = tracecmd_find_tracing_dir(); + path = tracefs_find_tracing_dir(); recorder = tracecmd_create_buffer_recorder_fd(fd, cpu, flags, path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } else { file = get_temp_file(instance, cpu); recorder = create_recorder_instance(instance, file, cpu, brass); @@ -4124,7 +4125,7 @@ static int write_func_file(struct buffer_instance *instance, close(fd); ret = 0; free: - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return ret; failed: die("Failed to write %s to %s.\n" @@ -4142,7 +4143,7 @@ static int functions_filtered(struct buffer_instance *instance) path = get_instance_file(instance, "set_ftrace_filter"); fd = open(path, O_RDONLY); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (fd < 0) { if (is_top_instance(instance)) warning("Can not set set_ftrace_filter"); @@ -4265,7 +4266,7 @@ static unsigned long long find_time_stamp(struct tep_handle *pevent) int fd; int r; - path = tracecmd_get_tracing_file("per_cpu"); + path = tracefs_get_tracing_file("per_cpu"); if (!path) return 0; @@ -4304,7 +4305,7 @@ static unsigned long long find_time_stamp(struct tep_handle *pevent) closedir(dir); out: - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return ts; } @@ -4319,7 +4320,7 @@ static char *read_instance_file(struct buffer_instance *instance, char *file, in path = get_instance_file(instance, file); fd = open(path, O_RDONLY); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (fd < 0) { warning("%s not found, --date ignored", file); return NULL; @@ -4400,9 +4401,9 @@ static char *get_date_to_ts(void) goto out_pevent; } - path = tracecmd_get_tracing_file("trace_marker"); + path = tracefs_get_tracing_file("trace_marker"); tfd = open(path, O_WRONLY); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); if (tfd < 0) { warning("Can not open 'trace_marker', --date ignored"); goto out_pevent; @@ -4491,7 +4492,7 @@ static void set_buffer_size_instance(struct buffer_instance *instance) warning("Can't write to %s", path); close(fd); out: - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } void set_buffer_size(void) @@ -4560,7 +4561,7 @@ static void clear_instance_triggers(struct buffer_instance *instance) trace_event_iter_free(iter); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } static void @@ -4621,7 +4622,7 @@ static void clear_instance_filters(struct buffer_instance *instance) trace_event_iter_free(iter); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } static void clear_filters(void) @@ -4687,7 +4688,7 @@ static void clear_func_filters(void) for (i = 0; files[i]; i++) { path = get_instance_file(instance, files[i]); clear_func_filter(path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } } } @@ -4712,7 +4713,7 @@ static void make_instances(void) } else /* Don't delete instances that already exist */ instance->flags |= BUFFER_FL_KEEP; - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } } @@ -4734,7 +4735,7 @@ void tracecmd_remove_instances(void) ret = rmdir(path); if (ret < 0) die("rmdir %s", path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } } @@ -5043,7 +5044,7 @@ static int test_stacktrace_trigger(struct buffer_instance *instance) ret = 1; close(fd); out: - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return ret; } diff --git a/tracecmd/trace-show.c b/tracecmd/trace-show.c index 96bfe77..391d329 100644 --- a/tracecmd/trace-show.c +++ b/tracecmd/trace-show.c @@ -7,6 +7,7 @@ #include #include +#include "tracefs.h" #include "trace-local.h" enum { @@ -157,9 +158,9 @@ void trace_show(int argc, char **argv) if (show_name) { char *name; - name = tracecmd_get_tracing_file(file); + name = tracefs_get_tracing_file(file); printf("%s\n", name); - tracecmd_put_tracing_file(name); + tracefs_put_tracing_file(name); } show_file(file); if (buffer) diff --git a/tracecmd/trace-snapshot.c b/tracecmd/trace-snapshot.c index a9a512a..34630b4 100644 --- a/tracecmd/trace-snapshot.c +++ b/tracecmd/trace-snapshot.c @@ -12,6 +12,7 @@ #include #include +#include "tracefs.h" #include "trace-local.h" static void write_file(const char *name, char *val) @@ -20,7 +21,7 @@ static void write_file(const char *name, char *val) int fd; ssize_t n; - path = tracecmd_get_tracing_file(name); + path = tracefs_get_tracing_file(name); fd = open(path, O_WRONLY); if (fd < 0) die("writing %s", path); @@ -29,7 +30,7 @@ static void write_file(const char *name, char *val) if (n < 0) die("failed to write to %s\n", path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); close(fd); } @@ -91,11 +92,11 @@ void trace_snapshot (int argc, char **argv) file = cpu_path; } - name = tracecmd_get_tracing_file(file); + name = tracefs_get_tracing_file(file); ret = stat(name, &st); if (ret < 0) die("Snapshot feature is not supported by this kernel"); - tracecmd_put_tracing_file(name); + tracefs_put_tracing_file(name); if (!reset_snap && !take_snap && !free_snap) { show_file(file); diff --git a/tracecmd/trace-stack.c b/tracecmd/trace-stack.c index bb002c0..5e88b36 100644 --- a/tracecmd/trace-stack.c +++ b/tracecmd/trace-stack.c @@ -15,6 +15,7 @@ #include #include +#include "tracefs.h" #include "trace-local.h" #define PROC_FILE "/proc/sys/kernel/stack_tracer_enabled" @@ -86,7 +87,7 @@ static void reset_trace(void) int fd; int n; - path = tracecmd_get_tracing_file("stack_max_size"); + path = tracefs_get_tracing_file("stack_max_size"); fd = open(path, O_WRONLY); if (fd < 0) die("writing %s", path); @@ -95,7 +96,7 @@ static void reset_trace(void) n = write(fd, buf, 1); if (n < 0) die("writing into %s", path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); close(fd); } @@ -116,11 +117,11 @@ static void read_trace(void) else printf("(stack tracer not running)\n"); - path = tracecmd_get_tracing_file("stack_trace"); + path = tracefs_get_tracing_file("stack_trace"); fp = fopen(path, "r"); if (!fp) die("reading to '%s'", path); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); while ((r = getline(&buf, &n, fp)) >= 0) { /* diff --git a/tracecmd/trace-stat.c b/tracecmd/trace-stat.c index 538f4ad..7a1d9bb 100644 --- a/tracecmd/trace-stat.c +++ b/tracecmd/trace-stat.c @@ -13,6 +13,7 @@ #include #include +#include "tracefs.h" #include "trace-local.h" #ifndef BUFSIZ @@ -32,7 +33,7 @@ static int get_instance_file_fd(struct buffer_instance *instance, path = get_instance_file(instance, file); fd = open(path, O_RDONLY); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); return fd; } @@ -383,7 +384,7 @@ static void report_events(struct buffer_instance *instance) if (!processed && !processed_part) printf(" (none enabled)\n"); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } static void @@ -456,7 +457,7 @@ static void report_event_filters(struct buffer_instance *instance) trace_event_iter_free(iter); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } static void @@ -529,7 +530,7 @@ static void report_event_triggers(struct buffer_instance *instance) trace_event_iter_free(iter); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } enum func_states { @@ -604,7 +605,7 @@ static void report_graph_funcs(struct buffer_instance *instance) list_functions(path, "Function Graph Filter"); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); path = get_instance_file(instance, "set_graph_notrace"); if (!path) @@ -612,7 +613,7 @@ static void report_graph_funcs(struct buffer_instance *instance) list_functions(path, "Function Graph No Trace"); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } static void report_ftrace_filters(struct buffer_instance *instance) @@ -625,7 +626,7 @@ static void report_ftrace_filters(struct buffer_instance *instance) list_functions(path, "Function Filter"); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); path = get_instance_file(instance, "set_ftrace_notrace"); if (!path) @@ -633,7 +634,7 @@ static void report_ftrace_filters(struct buffer_instance *instance) list_functions(path, "Function No Trace"); - tracecmd_put_tracing_file(path); + tracefs_put_tracing_file(path); } static void report_buffers(struct buffer_instance *instance) From patchwork Mon Jan 6 15:40:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 11319545 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8865114B4 for ; Mon, 6 Jan 2020 15:41:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5C17620731 for ; Mon, 6 Jan 2020 15:41:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="q0UMkI31" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726478AbgAFPlG (ORCPT ); Mon, 6 Jan 2020 10:41:06 -0500 Received: from mail-lj1-f196.google.com ([209.85.208.196]:37747 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726477AbgAFPlG (ORCPT ); Mon, 6 Jan 2020 10:41:06 -0500 Received: by mail-lj1-f196.google.com with SMTP id o13so39934432ljg.4 for ; Mon, 06 Jan 2020 07:41:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=c2jWLLJDiFObEztdL+pOYiUhIcTI8FuCkBUWPUwASXk=; b=q0UMkI31BvfFVS0y5x2CzPHTZiyiAiGaqZNHXbmefKHMLdxt+GMNK0npk1FKRyYr3F k/5csq6/dinosJRaH/pbo/PcoaV1RfPK4FYbGJzx4ngycA8NfiLYZT6vOoSwZ1FbxwKy mAT1zeTJ/oN4HKOO1F7DyMueOm+NIH/GJRk/Y3Bsy/kGX9SHOIUlw+zHBrVUulzrZG71 Zl16ZAWtfbkHP9Mg9XIlIOyjLdcDChzXMLGvK+U613El3p0ipN3vPthTc+YS4Ft+STAH 6a1DcZXJueg3Om+2CRJq/zzxV8v/Px5uw4T9mXwMd1FgCunIOWt9oBiqjzER33GSQNd6 o1hw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=c2jWLLJDiFObEztdL+pOYiUhIcTI8FuCkBUWPUwASXk=; b=gzpfm+ih5mFEmChGRwYlIt7mnS0Pa5bDjXesJPtnken2tcR0+ugmKizafF71O+cE/z gg4p9nHTA0TTYOJPEWwOvEDKwj0TBku0QCumL/cLtZ7aorQYNWD6/sqJljPwlrlqQoff KqWgaRW/w1cANxJBOP6kJGQ5lcytllLCoSQN3RRDlVHFLxC5y9XLNEBxhygXg5qoP1yF gHl94SnlzXdcF+zlMqjNYr3SbvBttyHGVpH9S1dpsQE3Ffruoe97/dEG4xVUy3TvkKRC tk3k8gnyqHejapDxGchcFSROE91kbWxhzKiIjaniI3oyHLjvVJJqeRkuVoRIMefm+iWw swkQ== X-Gm-Message-State: APjAAAVh5knH57yNw5n56I5I+M+406/AoSzbrBPp3WW6tSuEnPVaQHVz 5Q8HMFjlZiiTf+gsPMr1xRMXP2Gdgfo= X-Google-Smtp-Source: APXvYqyD0WyGE8Xmv6k8DIV1Lj8F+vkd/wavGE+UpjE3jQZ10haRMCfb6cLiOoiWztObnYVokbhplQ== X-Received: by 2002:a2e:a361:: with SMTP id i1mr58099746ljn.29.1578325263618; Mon, 06 Jan 2020 07:41:03 -0800 (PST) Received: from oberon.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id u25sm29257677lfk.46.2020.01.06.07.41.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jan 2020 07:41:02 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 2/5] kernel-shark: Use new tracefs library Date: Mon, 6 Jan 2020 17:40:55 +0200 Message-Id: <20200106154058.60660-3-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200106154058.60660-1-tz.stoyanov@gmail.com> References: <20200106154058.60660-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Link libtracefs to kernel-shark and use its API: tracefs_get_tracing_dir() Signed-off-by: Tzvetomir Stoyanov (VMware) --- kernel-shark/CMakeLists.txt | 3 ++- kernel-shark/build/FindTraceCmd.cmake | 30 +++++++++++++++++++++++++++ kernel-shark/src/CMakeLists.txt | 2 ++ kernel-shark/src/KsCaptureDialog.cpp | 4 ++-- kernel-shark/src/libkshark.h | 1 + 5 files changed, 37 insertions(+), 3 deletions(-) diff --git a/kernel-shark/CMakeLists.txt b/kernel-shark/CMakeLists.txt index 20478b9..8786b83 100644 --- a/kernel-shark/CMakeLists.txt +++ b/kernel-shark/CMakeLists.txt @@ -76,7 +76,8 @@ endif (CMAKE_BUILD_TYPE MATCHES Package) include_directories(${KS_DIR}/src/ ${KS_DIR}/build/src/ ${JSONC_INCLUDE_DIR} - ${TRACECMD_INCLUDE_DIR}) + ${TRACECMD_INCLUDE_DIR} + ${TRACEFS_INCLUDE_DIR}) message("") message(STATUS "C flags : " ${CMAKE_C_FLAGS}) diff --git a/kernel-shark/build/FindTraceCmd.cmake b/kernel-shark/build/FindTraceCmd.cmake index d3e145c..f27fafe 100644 --- a/kernel-shark/build/FindTraceCmd.cmake +++ b/kernel-shark/build/FindTraceCmd.cmake @@ -6,6 +6,8 @@ # TRACEEVENT_FOUND, If false, do not try to use traceevent. # # TRACECMD_INCLUDE_DIR, where to find trace-cmd header. +# TRACEFS_INCLUDE_DIR, where to find tracefs header. +# TRACEFS_LIBRARY, the tracefs library. # TRACECMD_LIBRARY, the trace-cmd library. # TRACECMD_FOUND, If false, do not try to use trace-cmd. @@ -31,12 +33,21 @@ find_path(TRACECMD_INCLUDE_DIR NAMES trace-cmd/trace-cmd.h PATHS $ENV{TRACE_CMD}/include/ ${CMAKE_SOURCE_DIR}/../include/ NO_DEFAULT_PATH) +find_path(TRACEFS_INCLUDE_DIR NAMES tracefs/tracefs.h + PATHS $ENV{TRACE_CMD}/include/ + ${CMAKE_SOURCE_DIR}/../include/ + NO_DEFAULT_PATH) find_library(TRACECMD_LIBRARY NAMES trace-cmd/libtracecmd.a PATHS $ENV{TRACE_CMD}/lib/ ${CMAKE_SOURCE_DIR}/../lib/ NO_DEFAULT_PATH) +find_library(TRACEFS_LIBRARY NAMES trace-cmd/libtracefs.a + PATHS $ENV{TRACE_CMD}/lib/ + ${CMAKE_SOURCE_DIR}/../lib/ + NO_DEFAULT_PATH) + find_library(TRACEEVENT_LIBRARY NAMES traceevent/libtraceevent.a PATHS $ENV{TRACE_CMD}/lib/ ${CMAKE_SOURCE_DIR}/../lib/ @@ -46,7 +57,9 @@ find_library(TRACEEVENT_LIBRARY NAMES traceevent/libtraceevent.a # search was successful "find_path" will do nothing this time. find_program(TRACECMD_EXECUTABLE NAMES trace-cmd) find_path(TRACECMD_INCLUDE_DIR NAMES trace-cmd/trace-cmd.h) +find_path(TRACEFS_INCLUDE_DIR NAMES tracefs/tracefs.h) find_library(TRACECMD_LIBRARY NAMES trace-cmd/libtracecmd.so) +find_library(TRACEFS_LIBRARY NAMES tracefs/libtracefs.so) find_library(TRACEEVENT_LIBRARY NAMES traceevent/libtraceevent.so) IF (TRACECMD_INCLUDE_DIR AND TRACECMD_LIBRARY) @@ -65,6 +78,23 @@ ELSE (TRACECMD_FOUND) ENDIF (TRACECMD_FOUND) +IF (TRACEFS_INCLUDE_DIR AND TRACEFS_LIBRARY) + + SET(TRACEFS_FOUND TRUE) + +ENDIF (TRACEFS_INCLUDE_DIR AND TRACEFS_LIBRARY) + +IF (TRACEFS_FOUND) + + MESSAGE(STATUS "Found tracefs: ${TRACEFS_LIBRARY}") + +ELSE (TRACEFS_FOUND) + + MESSAGE(FATAL_ERROR "\nCould not find tracefs!\n") + +ENDIF (TRACEFS_FOUND) + + IF (TRACEEVENT_LIBRARY) SET(TRACEEVENT_FOUND TRUE) diff --git a/kernel-shark/src/CMakeLists.txt b/kernel-shark/src/CMakeLists.txt index e20a030..33b5db8 100644 --- a/kernel-shark/src/CMakeLists.txt +++ b/kernel-shark/src/CMakeLists.txt @@ -9,6 +9,7 @@ add_library(kshark SHARED libkshark.c target_link_libraries(kshark ${TRACEEVENT_LIBRARY} ${TRACECMD_LIBRARY} + ${TRACEFS_LIBRARY} ${JSONC_LIBRARY} ${CMAKE_DL_LIBS}) @@ -69,6 +70,7 @@ if (Qt5Widgets_FOUND AND Qt5Network_FOUND) Qt5::Network ${TRACEEVENT_LIBRARY} ${TRACECMD_LIBRARY} + ${TRACEFS_LIBRARY} ${CMAKE_DL_LIBS}) set_target_properties(kshark-gui PROPERTIES SUFFIX ".so.${KS_VERSION_STRING}") diff --git a/kernel-shark/src/KsCaptureDialog.cpp b/kernel-shark/src/KsCaptureDialog.cpp index ad05917..548b6fb 100644 --- a/kernel-shark/src/KsCaptureDialog.cpp +++ b/kernel-shark/src/KsCaptureDialog.cpp @@ -26,7 +26,7 @@ extern "C" { static inline tep_handle *local_events() { - return tracecmd_local_events(tracecmd_get_tracing_dir()); + return tracecmd_local_events(tracefs_get_tracing_dir()); } /** @@ -204,7 +204,7 @@ QStringList KsCaptureControl::_getPlugins() QStringList pluginList; char **all_plugins; - all_plugins = tracecmd_local_plugins(tracecmd_get_tracing_dir()); + all_plugins = tracecmd_local_plugins(tracefs_get_tracing_dir()); if (!all_plugins) return pluginList; diff --git a/kernel-shark/src/libkshark.h b/kernel-shark/src/libkshark.h index 3407db1..b05aa90 100644 --- a/kernel-shark/src/libkshark.h +++ b/kernel-shark/src/libkshark.h @@ -28,6 +28,7 @@ extern "C" { #include "trace-cmd/trace-cmd.h" #include "trace-cmd/trace-filter-hash.h" #include "traceevent/event-parse.h" +#include "tracefs/tracefs.h" // KernelShark #include "libkshark-plugin.h" From patchwork Mon Jan 6 15:40:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 11319549 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C3906921 for ; Mon, 6 Jan 2020 15:41:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 82A872075A for ; Mon, 6 Jan 2020 15:41:10 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Za6/tj63" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726504AbgAFPlK (ORCPT ); Mon, 6 Jan 2020 10:41:10 -0500 Received: from mail-lj1-f193.google.com ([209.85.208.193]:38619 "EHLO mail-lj1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726477AbgAFPlK (ORCPT ); Mon, 6 Jan 2020 10:41:10 -0500 Received: by mail-lj1-f193.google.com with SMTP id w1so29399080ljh.5 for ; Mon, 06 Jan 2020 07:41:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FvnnnTVtTieDZClA9wX6X2MhOgxSCvE/gG61ey0anVI=; b=Za6/tj63diKSWbI8844gF8HyQe3iiju98LPFSTpPPI/tjrI3qwviZA0yIjdwbtHTTI ITw5N9GHFZovdxsgb/EWFKuXKAzDn24ueSmFO8LGJAsnnayx2RkO5KiWrjOGRK54Dp9v houub6ArC6t5HLaEUHq8Nz83j62su+3g9vIDOZRJiXPHERGlCjBTFVDoF/Pbf5ALvdRG nOTy1KjoRuVlg4M+6ArDbWPiISlNU7rPjLcjcUq3pH7boTlM47ZMToBIeSIotVbnuybD y8bDpd4lGj1C9fdZJ8b9Mjcy10UYFF8E+YDNDNf6DLV8/FmKXIB3jVMhVRhX5752CDLh m/fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FvnnnTVtTieDZClA9wX6X2MhOgxSCvE/gG61ey0anVI=; b=Tn49/n6bJxIFaYiCr4wu20H4e5LPysELB3uwsExSoIXuUgS8EG2JFlUCI1KcW25l2G 0zCuzYCKUJ+IExjeeWtMZCzHuZewUI09A4nC7f1eyKq2MqWSZ8oHptsL4U9iTltmnQhn Cpnbfc+O+RhAcxw1r8XxV+eQGksK/zYzguxMaOexQEDeSHc4atNAVg5KqmhrBP2kFNxa JS/3HXtt1/rJ/wS0sfRPC3edkchQM9vDeggU94MSH74pKYkRdda0EvjyscUU5ESaujbT cinCPX+O/8LwqTZbU3iEuWSFSBZw+yee+wZKaeeO6O4WnwY6PBZCaDMyeYtbfbESIaHe uxKg== X-Gm-Message-State: APjAAAUcnrZbCTRwDJupU2ekbf9zHs4uGNmB8inFgNdBqkm1QPE7D0kB oD9JKtPPsG+B3SHddzDZ17w= X-Google-Smtp-Source: APXvYqwVMsSZwXxtCEVjYbDxdmYVs+L2qzLmLJ/V5ppGgUQ3ib4J7LS1eJxiRXlYVeOHrenS7J2OmA== X-Received: by 2002:a2e:8e85:: with SMTP id z5mr47228336ljk.212.1578325265053; Mon, 06 Jan 2020 07:41:05 -0800 (PST) Received: from oberon.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id u25sm29257677lfk.46.2020.01.06.07.41.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jan 2020 07:41:04 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 3/5] trace-cmd: New libtracefs APIs for ftrace instances Date: Mon, 6 Jan 2020 17:40:56 +0200 Message-Id: <20200106154058.60660-4-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200106154058.60660-1-tz.stoyanov@gmail.com> References: <20200106154058.60660-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org The functionality related to ftrace instances is moved from trace-cmd application to libtracefs. The following new library APIs are introduced: struct tracefs_instance; struct tracefs_instance *tracefs_alloc_instance(const char *name); int tracefs_free_instance(struct tracefs_instance *instance); int tracefs_make_instance(struct tracefs_instance *instance); int tracefs_remove_instance(struct tracefs_instance *instance); char *tracefs_get_instance_name(struct tracefs_instance *instance); char *tracefs_get_instance_file(struct tracefs_instance *instance, const char *file); char *tracefs_get_instance_dir(struct tracefs_instance *instance); int tracefs_write_instance_file(struct tracefs_instance *instance, const char *file, const char *str, const char *type); char *tracefs_read_instance_file(struct tracefs_instance *instance, char *file, int *psize); Signed-off-by: Tzvetomir Stoyanov (VMware) --- include/tracefs/tracefs.h | 17 ++ lib/tracefs/Makefile | 1 + lib/tracefs/include/tracefs-local.h | 1 + lib/tracefs/tracefs-instance.c | 267 ++++++++++++++++++++++++++++ lib/tracefs/tracefs-utils.c | 43 +++++ tracecmd/include/trace-local.h | 5 +- tracecmd/trace-list.c | 2 +- tracecmd/trace-record.c | 264 +++++++++------------------ tracecmd/trace-show.c | 2 + tracecmd/trace-stat.c | 21 ++- 10 files changed, 431 insertions(+), 192 deletions(-) create mode 100644 lib/tracefs/tracefs-instance.c diff --git a/include/tracefs/tracefs.h b/include/tracefs/tracefs.h index e844c75..6b27ff7 100644 --- a/include/tracefs/tracefs.h +++ b/include/tracefs/tracefs.h @@ -17,4 +17,21 @@ const char *tracefs_get_tracing_dir(void); /* tracefs_find_tracing_dir must be freed */ char *tracefs_find_tracing_dir(void); +/* ftarce instances */ +struct tracefs_instance; + +struct tracefs_instance *tracefs_alloc_instance(const char *name); +int tracefs_free_instance(struct tracefs_instance *instance); +int tracefs_make_instance(struct tracefs_instance *instance); +int tracefs_remove_instance(struct tracefs_instance *instance); +char *tracefs_get_instance_name(struct tracefs_instance *instance); +char * +tracefs_get_instance_file(struct tracefs_instance *instance, const char *file); +char *tracefs_get_instance_dir(struct tracefs_instance *instance); +int tracefs_write_instance_file(struct tracefs_instance *instance, + const char *file, const char *str, + const char *type); +char *tracefs_read_instance_file(struct tracefs_instance *instance, + char *file, int *psize); + #endif /* _TRACE_FS_H */ diff --git a/lib/tracefs/Makefile b/lib/tracefs/Makefile index 86d7845..4030272 100644 --- a/lib/tracefs/Makefile +++ b/lib/tracefs/Makefile @@ -8,6 +8,7 @@ DEFAULT_TARGET = $(bdir)/libtracefs.a OBJS = OBJS += tracefs-utils.o +OBJS += tracefs-instance.o OBJS := $(OBJS:%.o=$(bdir)/%.o) DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) diff --git a/lib/tracefs/include/tracefs-local.h b/lib/tracefs/include/tracefs-local.h index 231edd1..fe327a0 100644 --- a/lib/tracefs/include/tracefs-local.h +++ b/lib/tracefs/include/tracefs-local.h @@ -8,5 +8,6 @@ /* Can be overridden */ void warning(const char *fmt, ...); +int str_read_file(const char *file, char **buffer); #endif /* _TRACE_FS_LOCAL_H */ diff --git a/lib/tracefs/tracefs-instance.c b/lib/tracefs/tracefs-instance.c new file mode 100644 index 0000000..14e8eed --- /dev/null +++ b/lib/tracefs/tracefs-instance.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt + * + * Updates: + * Copyright (C) 2019, VMware, Tzvetomir Stoyanov + * + */ + +#include +#include +#include +#include +#include +#include + +#include "tracefs.h" +#include "tracefs-local.h" + +struct tracefs_instance { + char *name; +}; + +/** + * tracefs_alloc_instance - allocate a new ftrace instance + * @name: The name of the instance (instance will point to this) + * + * Returns a newly allocated instance, or NULL in case of an error. + */ +struct tracefs_instance *tracefs_alloc_instance(const char *name) +{ + struct tracefs_instance *instance; + + instance = calloc(1, sizeof(*instance)); + if (!instance) + return NULL; + if (name) + instance->name = strdup(name); + + return instance; +} + +/** + * tracefs_free_instance - Free an instance, previously allocated by + tracefs_alloc_instance() + * @instance: Pointer to the instance to be freed + * + * Returns -1 in case of an error, or 0 otherwise. + */ +int tracefs_free_instance(struct tracefs_instance *instance) +{ + if (!instance) + return -1; + + free(instance->name); + free(instance); + return 0; +} + +/** + * tracefs_make_instance - Create a new ftrace instance + * @instance: Pointer to the instance to be created + * + * Returns 1 if the instance already exist, 0 if the instance + * is created successful or -1 in case of an error + */ +int tracefs_make_instance(struct tracefs_instance *instance) +{ + struct stat st; + char *path; + int ret; + + path = tracefs_get_instance_dir(instance); + ret = stat(path, &st); + if (ret < 0) { + ret = mkdir(path, 0777); + if (ret < 0) + return ret; + + } else + ret = 1; + tracefs_put_tracing_file(path); + return ret; +} + +/** + * tracefs_remove_instance - Remove a ftrace instance + * @instance: Pointer to the instance to be removed + * + * Returns -1 in case of an error, or 0 otherwise. + */ +int tracefs_remove_instance(struct tracefs_instance *instance) +{ + char *path; + int ret; + + if (!instance || !instance->name) { + warning("Cannot remove top instance"); + return -1; + } + + path = tracefs_get_instance_dir(instance); + ret = rmdir(path); + tracefs_put_tracing_file(path); + + return ret; +} + +/** + * tracefs_get_instance_file - return the path to an instance file. + * @instance: ftrace instance, can be NULL for the top instance + * @file: name of file to return + * + * Returns the path of the @file for the given @instance, or NULL in + * case of an error. + * + * Must use tracefs_put_tracing_file() to free the returned string. + */ +char * +tracefs_get_instance_file(struct tracefs_instance *instance, const char *file) +{ + char *path; + char *buf; + int ret; + + if (instance && instance->name) { + ret = asprintf(&buf, "instances/%s/%s", instance->name, file); + if (ret < 0) { + warning("Failed to allocate name for %s/%s", + instance->name, file); + return NULL; + } + path = tracefs_get_tracing_file(buf); + free(buf); + } else + path = tracefs_get_tracing_file(file); + + return path; +} + +/** + * tracefs_get_instance_dir - return the path to the instance directory. + * @instance: ftrace instance, can be NULL for the top instance + * + * Returns the full path to the instance directory + * + * Must use tracefs_put_tracing_file() to free the returned string. + */ +char *tracefs_get_instance_dir(struct tracefs_instance *instance) +{ + char *buf; + char *path; + int ret; + + if (instance && instance->name) { + ret = asprintf(&buf, "instances/%s", instance->name); + if (ret < 0) { + warning("Failed to allocate path for instance %s", + instance->name); + return NULL; + } + path = tracefs_get_tracing_file(buf); + free(buf); + } else + path = tracefs_find_tracing_dir(); + + return path; +} + +/** + * tracefs_get_instance_name - return the name of an instance + * @instance: ftrace instance + * + * Returns the name of the given @instance. + * The returned string must *not* be freed. + */ +char *tracefs_get_instance_name(struct tracefs_instance *instance) +{ + if (instance) + return instance->name; + return NULL; +} + +static int write_file(const char *file, const char *str, const char *type) +{ + char buf[BUFSIZ]; + int ret; + int fd; + + fd = open(file, O_WRONLY | O_TRUNC); + if (fd < 0) { + warning("Failed to open '%s'", file); + return -1; + } + ret = write(fd, str, strlen(str)); + close(fd); + if (ret < 0 && type) { + /* write failed */ + fd = open(file, O_RDONLY); + if (fd < 0) { + warning("Failed to write in '%s'", file); + return -1; + } + + while ((ret = read(fd, buf, BUFSIZ)) > 0) + fprintf(stderr, "%.*s", ret, buf); + warning("Failed %s of %s\n", type, file); + close(fd); + } + return ret; +} + + +/** + * tracefs_write_instance_file - Write in trace file of specific instance. + * @instance: ftrace instance, can be NULL for the top instance + * @file: name of the file + * @str: nul terminated string, that will be written in the file. + * @type: nul terminated string, describing the current write operation. + * Used for logging purposes. + * + * Returns the number of written bytes, or -1 in case of an error + */ +int tracefs_write_instance_file(struct tracefs_instance *instance, + const char *file, const char *str, + const char *type) +{ + struct stat st; + char *path; + int ret; + + path = tracefs_get_instance_file(instance, file); + ret = stat(path, &st); + if (ret == 0) + ret = write_file(path, str, type); + tracefs_put_tracing_file(path); + + return ret; +} + +/** + * tracefs_read_instance_file - Read from a trace file of specific instance. + * @instance: ftrace instance, can be NULL for the top instance + * @file: name of the file + * @psize: returns the number of bytes read + * + * Returns a pointer to a nul terminated string, read from the file, or NULL in + * case of an error. + * The return string must be freed by free() + */ +char *tracefs_read_instance_file(struct tracefs_instance *instance, + char *file, int *psize) +{ + char *buf = NULL; + int size = 0; + char *path; + + path = tracefs_get_instance_file(instance, file); + + size = str_read_file(path, &buf); + + tracefs_put_tracing_file(path); + if (buf && psize) + *psize = size; + + return buf; +} diff --git a/lib/tracefs/tracefs-utils.c b/lib/tracefs/tracefs-utils.c index 0ef16fc..bdab130 100644 --- a/lib/tracefs/tracefs-utils.c +++ b/lib/tracefs/tracefs-utils.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include "tracefs.h" @@ -181,3 +184,43 @@ void tracefs_put_tracing_file(char *name) { free(name); } + +int str_read_file(const char *file, char **buffer) +{ + char stbuf[BUFSIZ]; + char *buf = NULL; + int size = 0; + char *nbuf; + int fd; + int r; + + fd = open(file, O_RDONLY); + if (fd < 0) { + warning("File %s not found", file); + return -1; + } + + do { + r = read(fd, stbuf, BUFSIZ); + if (r <= 0) + continue; + nbuf = realloc(buf, size+r+1); + if (!nbuf) { + warning("Failed to allocate file buffer"); + size = -1; + break; + } + buf = nbuf; + memcpy(buf+size, stbuf, r); + size += r; + } while (r); + + close(fd); + if (size > 0) { + buf[size] = '\0'; + *buffer = buf; + } else + free(buf); + + return size; +} diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index fedc0b7..c7310e5 100644 --- a/tracecmd/include/trace-local.h +++ b/tracecmd/include/trace-local.h @@ -181,7 +181,7 @@ struct pid_addr_maps { struct buffer_instance { struct buffer_instance *next; - const char *name; + struct tracefs_instance *tracefs; char *cpumask; struct event_list *events; struct event_list **event_next; @@ -225,6 +225,8 @@ struct buffer_instance { bool use_fifos; }; +void init_top_instance(void); + extern struct buffer_instance top_instance; extern struct buffer_instance *buffer_instances; extern struct buffer_instance *first_instance; @@ -238,7 +240,6 @@ extern struct buffer_instance *first_instance; struct buffer_instance *create_instance(const char *name); void add_instance(struct buffer_instance *instance, int cpu_count); -char *get_instance_file(struct buffer_instance *instance, const char *file); void update_first_instance(struct buffer_instance *instance, int topt); void show_instance_file(struct buffer_instance *instance, const char *name); diff --git a/tracecmd/trace-list.c b/tracecmd/trace-list.c index 86e3358..d5c0707 100644 --- a/tracecmd/trace-list.c +++ b/tracecmd/trace-list.c @@ -34,7 +34,7 @@ void show_instance_file(struct buffer_instance *instance, const char *name) { char *path; - path = get_instance_file(instance, name); + path = tracefs_get_instance_file(instance->tracefs, name); dump_file_content(path); tracefs_put_tracing_file(path); } diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 5355813..62f67d5 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -174,7 +174,7 @@ static struct reset_file *reset_files; /* Triggers need to be cleared in a special way */ static struct reset_file *reset_triggers; -struct buffer_instance top_instance = { .flags = BUFFER_FL_KEEP }; +struct buffer_instance top_instance; struct buffer_instance *buffer_instances; struct buffer_instance *first_instance; @@ -372,7 +372,11 @@ struct buffer_instance *create_instance(const char *name) if (!instance) return NULL; memset(instance, 0, sizeof(*instance)); - instance->name = name; + instance->tracefs = tracefs_alloc_instance(name); + if (!instance->tracefs) { + free(instance); + return NULL; + } return instance; } @@ -472,7 +476,7 @@ void tracecmd_stat_cpu_instance(struct buffer_instance *instance, return; snprintf(file, 40, "per_cpu/cpu%d/stats", cpu); - path = get_instance_file(instance, file); + path = tracefs_get_instance_file(instance->tracefs, file); free(file); fd = open(path, O_RDONLY); tracefs_put_tracing_file(path); @@ -511,10 +515,11 @@ static void reset_event_list(struct buffer_instance *instance) static char *get_temp_file(struct buffer_instance *instance, int cpu) { - const char *name = instance->name; + const char *name; char *file = NULL; int size; + name = tracefs_get_instance_name(instance->tracefs); if (name) { size = snprintf(file, 0, "%s.%s.cpu%d", output_file, name, cpu); file = malloc(size + 1); @@ -558,9 +563,10 @@ static void put_temp_file(char *file) static void delete_temp_file(struct buffer_instance *instance, int cpu) { - const char *name = instance->name; + const char *name; char file[PATH_MAX]; + name = tracefs_get_instance_name(instance->tracefs); if (name) snprintf(file, PATH_MAX, "%s.%s.cpu%d", output_file, name, cpu); else @@ -784,54 +790,6 @@ static int set_ftrace(int set, int use_proc) return 0; } -/** - * get_instance_file - return the path to a instance file. - * @instance: buffer instance for the file - * @file: name of file to return - * - * Returns the path name of the @file for the given @instance. - * - * Must use tracefs_put_tracing_file() to free the returned string. - */ -char * -get_instance_file(struct buffer_instance *instance, const char *file) -{ - char *buf; - char *path; - int ret; - - if (instance->name) { - ret = asprintf(&buf, "instances/%s/%s", instance->name, file); - if (ret < 0) - die("Failed to allocate name for %s/%s", instance->name, file); - path = tracefs_get_tracing_file(buf); - free(buf); - } else - path = tracefs_get_tracing_file(file); - - return path; -} - -static char * -get_instance_dir(struct buffer_instance *instance) -{ - char *buf; - char *path; - int ret; - - /* only works for instances */ - if (!instance->name) - return NULL; - - ret = asprintf(&buf, "instances/%s", instance->name); - if (ret < 0) - die("Failed to allocate for instance %s", instance->name); - path = tracefs_get_tracing_file(buf); - free(buf); - - return path; -} - static int write_file(const char *file, const char *str, const char *type) { char buf[BUFSIZ]; @@ -857,23 +815,6 @@ static int write_file(const char *file, const char *str, const char *type) return ret; } -static int -write_instance_file(struct buffer_instance *instance, - const char *file, const char *str, const char *type) -{ - struct stat st; - char *path; - int ret; - - path = get_instance_file(instance, file); - ret = stat(path, &st); - if (ret == 0) - ret = write_file(path, str, type); - tracefs_put_tracing_file(path); - - return ret; -} - static void __clear_trace(struct buffer_instance *instance) { FILE *fp; @@ -883,7 +824,7 @@ static void __clear_trace(struct buffer_instance *instance) return; /* reset the trace */ - path = get_instance_file(instance, "trace"); + path = tracefs_get_instance_file(instance->tracefs, "trace"); fp = fopen(path, "w"); if (!fp) die("writing to '%s'", path); @@ -917,8 +858,8 @@ static void clear_trace(void) static void reset_max_latency(struct buffer_instance *instance) { - write_instance_file(instance, - "tracing_max_latency", "0", "max_latency"); + tracefs_write_instance_file(instance->tracefs, + "tracing_max_latency", "0", "max_latency"); } static void add_filter_pid(int pid, int exclude) @@ -1364,7 +1305,8 @@ static void add_event_pid(const char *buf) struct buffer_instance *instance; for_all_instances(instance) - write_instance_file(instance, "set_event_pid", buf, "event_pid"); + tracefs_write_instance_file(instance->tracefs, + "set_event_pid", buf, "event_pid"); } static void add_new_filter_pid(int pid) @@ -1593,7 +1535,7 @@ set_plugin_instance(struct buffer_instance *instance, const char *name) if (is_guest(instance)) return; - path = get_instance_file(instance, "current_tracer"); + path = tracefs_get_instance_file(instance->tracefs, "current_tracer"); fp = fopen(path, "w"); if (!fp) { /* @@ -1617,7 +1559,7 @@ set_plugin_instance(struct buffer_instance *instance, const char *name) /* Make sure func_stack_trace option is disabled */ /* First try instance file, then top level */ - path = get_instance_file(instance, "options/func_stack_trace"); + path = tracefs_get_instance_file(instance->tracefs, "options/func_stack_trace"); fp = fopen(path, "w"); if (!fp) { tracefs_put_tracing_file(path); @@ -1678,8 +1620,6 @@ static int set_option(const char *option) return 0; } -static char *read_instance_file(struct buffer_instance *instance, char *file, int *psize); - static void disable_func_stack_trace_instance(struct buffer_instance *instance) { struct stat st; @@ -1692,13 +1632,14 @@ static void disable_func_stack_trace_instance(struct buffer_instance *instance) if (is_guest(instance)) return; - path = get_instance_file(instance, "current_tracer"); + path = tracefs_get_instance_file(instance->tracefs, "current_tracer"); ret = stat(path, &st); tracefs_put_tracing_file(path); if (ret < 0) return; - content = read_instance_file(instance, "current_tracer", &size); + content = tracefs_read_instance_file(instance->tracefs, + "current_tracer", &size); cond = strstrip(content); if (memcmp(cond, "function", size - (cond - content)) !=0) goto out; @@ -1851,7 +1792,7 @@ static int trace_check_file_exists(struct buffer_instance *instance, char *file) char *path; int ret; - path = get_instance_file(instance, file); + path = tracefs_get_instance_file(instance->tracefs, file); ret = stat(path, &st); tracefs_put_tracing_file(path); @@ -1930,7 +1871,7 @@ reset_events_instance(struct buffer_instance *instance) } c = '0'; - path = get_instance_file(instance, "events/enable"); + path = tracefs_get_instance_file(instance->tracefs, "events/enable"); fd = open(path, O_WRONLY); if (fd < 0) die("opening to '%s'", path); @@ -1938,7 +1879,7 @@ reset_events_instance(struct buffer_instance *instance) close(fd); tracefs_put_tracing_file(path); - path = get_instance_file(instance, "events/*/filter"); + path = tracefs_get_instance_file(instance->tracefs, "events/*/filter"); globbuf.gl_offs = 0; ret = glob(path, 0, NULL, &globbuf); tracefs_put_tracing_file(path); @@ -2199,7 +2140,7 @@ static int open_instance_fd(struct buffer_instance *instance, int fd; char *path; - path = get_instance_file(instance, file); + path = tracefs_get_instance_file(instance->tracefs, file); fd = open(path, flags); if (fd < 0) { /* instances may not be created yet */ @@ -2508,7 +2449,7 @@ static void set_mask(struct buffer_instance *instance) if (!instance->cpumask) return; - path = get_instance_file(instance, "tracing_cpumask"); + path = tracefs_get_instance_file(instance->tracefs, "tracing_cpumask"); if (!path) die("could not allocate path"); reset_save_file(path, RESET_DEFAULT_PRIO); @@ -2569,7 +2510,8 @@ static void set_clock(struct buffer_instance *instance) return; /* The current clock is in brackets, reset it when we are done */ - content = read_instance_file(instance, "trace_clock", NULL); + content = tracefs_read_instance_file(instance->tracefs, + "trace_clock", NULL); /* check if first clock is set */ if (*content == '[') @@ -2580,13 +2522,14 @@ static void set_clock(struct buffer_instance *instance) die("Can not find clock in trace_clock"); str = strtok(NULL, "]"); } - path = get_instance_file(instance, "trace_clock"); + path = tracefs_get_instance_file(instance->tracefs, "trace_clock"); add_reset_file(path, str, RESET_DEFAULT_PRIO); free(content); tracefs_put_tracing_file(path); - write_instance_file(instance, "trace_clock", instance->clock, "clock"); + tracefs_write_instance_file(instance->tracefs, + "trace_clock", instance->clock, "clock"); } static void set_max_graph_depth(struct buffer_instance *instance, char *max_graph_depth) @@ -2597,11 +2540,11 @@ static void set_max_graph_depth(struct buffer_instance *instance, char *max_grap if (is_guest(instance)) return; - path = get_instance_file(instance, "max_graph_depth"); + path = tracefs_get_instance_file(instance->tracefs, "max_graph_depth"); reset_save_file(path, RESET_DEFAULT_PRIO); tracefs_put_tracing_file(path); - ret = write_instance_file(instance, "max_graph_depth", max_graph_depth, - NULL); + ret = tracefs_write_instance_file(instance->tracefs, "max_graph_depth", + max_graph_depth, NULL); if (ret < 0) die("could not write to max_graph_depth"); } @@ -2718,7 +2661,7 @@ static int expand_event_files(struct buffer_instance *instance, if (ret < 0) die("Failed to allocate event filter path for %s", file); - path = get_instance_file(instance, p); + path = tracefs_get_instance_file(instance->tracefs, p); globbuf.gl_offs = 0; ret = glob(path, 0, NULL, &globbuf); @@ -3180,10 +3123,7 @@ create_recorder_instance_pipe(struct buffer_instance *instance, unsigned flags = recorder_flags | TRACECMD_RECORD_BLOCK; char *path; - if (instance->name) - path = get_instance_dir(instance); - else - path = tracefs_find_tracing_dir(); + path = tracefs_get_instance_dir(instance->tracefs); if (!path) die("malloc"); @@ -3193,8 +3133,7 @@ create_recorder_instance_pipe(struct buffer_instance *instance, recorder = tracecmd_create_buffer_recorder_fd(brass[1], cpu, flags, path); - if (instance->name) - tracefs_put_tracing_file(path); + tracefs_put_tracing_file(path); return recorder; } @@ -3228,10 +3167,10 @@ create_recorder_instance(struct buffer_instance *instance, const char *file, int if (brass) return create_recorder_instance_pipe(instance, cpu, brass); - if (!instance->name) + if (!tracefs_get_instance_name(instance->tracefs)) return tracecmd_create_recorder_maxkb(file, cpu, recorder_flags, max_kb); - path = get_instance_dir(instance); + path = tracefs_get_instance_dir(instance->tracefs); record = tracecmd_create_buffer_recorder_maxkb(file, cpu, recorder_flags, path, max_kb); @@ -3285,8 +3224,8 @@ static int create_recorder(struct buffer_instance *instance, int cpu, } if (fd < 0) die("Failed connecting to client"); - if (instance->name && !is_agent(instance)) - path = get_instance_dir(instance); + if (tracefs_get_instance_name(instance->tracefs) && !is_agent(instance)) + path = tracefs_get_instance_dir(instance->tracefs); else path = tracefs_find_tracing_dir(); recorder = tracecmd_create_buffer_recorder_fd(fd, cpu, flags, path); @@ -3597,9 +3536,11 @@ static void connect_to_agent(struct buffer_instance *instance) unsigned int *ports; int i, *fds = NULL; bool use_fifos = false; + char *name; + name = tracefs_get_instance_name(instance->tracefs); if (!no_fifos) { - nr_fifos = open_guest_fifos(instance->name, &fds); + nr_fifos = open_guest_fifos(name, &fds); use_fifos = nr_fifos > 0; } @@ -3626,7 +3567,7 @@ static void connect_to_agent(struct buffer_instance *instance) if (nr_cpus != nr_fifos) { warning("number of FIFOs (%d) for guest %s differs " "from number of virtual CPUs (%d)", - nr_fifos, instance->name, nr_cpus); + nr_fifos, name, nr_cpus); nr_cpus = nr_cpus < nr_fifos ? nr_cpus : nr_fifos; } free(ports); @@ -3652,7 +3593,8 @@ static void setup_guest(struct buffer_instance *instance) int fd; /* Create a place to store the guest meta data */ - file = get_guest_file(output_file, instance->name); + file = get_guest_file(output_file, + tracefs_get_instance_name(instance->tracefs)); if (!file) die("Failed to allocate memory"); @@ -3828,7 +3770,8 @@ add_buffer_stat(struct tracecmd_output *handle, struct buffer_instance *instance int i; trace_seq_init(&s); - trace_seq_printf(&s, "\nBuffer: %s\n\n", instance->name); + trace_seq_printf(&s, "\nBuffer: %s\n\n", + tracefs_get_instance_name(instance->tracefs)); tracecmd_add_option(handle, TRACECMD_OPTION_CPUSTAT, s.len+1, s.buffer); trace_seq_destroy(&s); @@ -3894,7 +3837,8 @@ static void print_stat(struct buffer_instance *instance) return; if (!is_top_instance(instance)) - printf("\nBuffer: %s\n\n", instance->name); + printf("\nBuffer: %s\n\n", + tracefs_get_instance_name(instance->tracefs)); for (cpu = 0; cpu < instance->cpu_count; cpu++) trace_seq_do_printf(&instance->s_print[cpu]); @@ -3934,7 +3878,8 @@ static void write_guest_file(struct buffer_instance *instance) char **temp_files; int i, fd; - file = get_guest_file(output_file, instance->name); + file = get_guest_file(output_file, + tracefs_get_instance_name(instance->tracefs)); if (!file) die("Failed to allocate memory"); @@ -4050,7 +3995,7 @@ static void record_data(struct common_record_context *ctx) continue; buffer_options[i++] = tracecmd_add_buffer_option(handle, - instance->name, + tracefs_get_instance_name(instance->tracefs), cpus); add_buffer_stat(handle, instance); } @@ -4097,7 +4042,7 @@ static int write_func_file(struct buffer_instance *instance, if (!*list) return 0; - path = get_instance_file(instance, file); + path = tracefs_get_instance_file(instance->tracefs, file); fd = open(path, O_WRONLY | O_TRUNC); if (fd < 0) @@ -4141,7 +4086,7 @@ static int functions_filtered(struct buffer_instance *instance) char *path; int fd; - path = get_instance_file(instance, "set_ftrace_filter"); + path = tracefs_get_instance_file(instance->tracefs, "set_ftrace_filter"); fd = open(path, O_RDONLY); tracefs_put_tracing_file(path); if (fd < 0) { @@ -4149,7 +4094,7 @@ static int functions_filtered(struct buffer_instance *instance) warning("Can not set set_ftrace_filter"); else warning("Can not set set_ftrace_filter for %s", - instance->name); + tracefs_get_instance_name(instance->tracefs)); return 0; } @@ -4309,45 +4254,9 @@ static unsigned long long find_time_stamp(struct tep_handle *pevent) return ts; } -static char *read_instance_file(struct buffer_instance *instance, char *file, int *psize) -{ - char buffer[BUFSIZ]; - char *path; - char *buf; - int size = 0; - int fd; - int r; - - path = get_instance_file(instance, file); - fd = open(path, O_RDONLY); - tracefs_put_tracing_file(path); - if (fd < 0) { - warning("%s not found, --date ignored", file); - return NULL; - } - do { - r = read(fd, buffer, BUFSIZ); - if (r <= 0) - continue; - if (size) - buf = realloc(buf, size+r+1); - else - buf = malloc(r+1); - if (!buf) - die("Failed to allocate instance file buffer"); - memcpy(buf+size, buffer, r); - size += r; - } while (r); - - buf[size] = '\0'; - if (psize) - *psize = size; - return buf; -} - static char *read_file(char *file, int *psize) { - return read_instance_file(&top_instance, file, psize); + return tracefs_read_instance_file(top_instance.tracefs, file, psize); } /* @@ -4480,7 +4389,7 @@ static void set_buffer_size_instance(struct buffer_instance *instance) snprintf(buf, BUFSIZ, "%d", buffer_size); - path = get_instance_file(instance, "buffer_size_kb"); + path = tracefs_get_instance_file(instance->tracefs, "buffer_size_kb"); fd = open(path, O_WRONLY); if (fd < 0) { warning("can't open %s", path); @@ -4541,7 +4450,7 @@ static void clear_instance_triggers(struct buffer_instance *instance) enum event_iter_type type; enum event_process processed = PROCESSED_NONE; - path = get_instance_file(instance, "events"); + path = tracefs_get_instance_file(instance->tracefs, "events"); if (!path) die("malloc"); @@ -4602,7 +4511,7 @@ static void clear_instance_filters(struct buffer_instance *instance) enum event_iter_type type; enum event_process processed = PROCESSED_NONE; - path = get_instance_file(instance, "events"); + path = tracefs_get_instance_file(instance->tracefs, "events"); if (!path) die("malloc"); @@ -4638,7 +4547,8 @@ static void reset_clock(void) struct buffer_instance *instance; for_all_instances(instance) - write_instance_file(instance, "trace_clock", "local", "clock"); + tracefs_write_instance_file(instance->tracefs, + "trace_clock", "local", "clock"); } static void reset_cpu_mask(void) @@ -4657,7 +4567,8 @@ static void reset_cpu_mask(void) strcat(buf, ",ffffffff"); for_all_instances(instance) - write_instance_file(instance, "tracing_cpumask", buf, "cpumask"); + tracefs_write_instance_file(instance->tracefs, + "tracing_cpumask", buf, "cpumask"); } static void reset_event_pid(void) @@ -4686,7 +4597,7 @@ static void clear_func_filters(void) for_all_instances(instance) { for (i = 0; files[i]; i++) { - path = get_instance_file(instance, files[i]); + path = tracefs_get_instance_file(instance->tracefs, files[i]); clear_func_filter(path); tracefs_put_tracing_file(path); } @@ -4696,32 +4607,20 @@ static void clear_func_filters(void) static void make_instances(void) { struct buffer_instance *instance; - struct stat st; - char *path; - int ret; for_each_instance(instance) { if (is_guest(instance)) continue; - - path = get_instance_dir(instance); - ret = stat(path, &st); - if (ret < 0) { - ret = mkdir(path, 0777); - if (ret < 0) - die("mkdir %s", path); - } else + if (tracefs_make_instance(instance->tracefs) > 0) { /* Don't delete instances that already exist */ instance->flags |= BUFFER_FL_KEEP; - tracefs_put_tracing_file(path); + } } } void tracecmd_remove_instances(void) { struct buffer_instance *instance; - char *path; - int ret; for_each_instance(instance) { /* Only delete what we created */ @@ -4731,11 +4630,7 @@ void tracecmd_remove_instances(void) close(instance->tracing_on_fd); instance->tracing_on_fd = 0; } - path = get_instance_dir(instance); - ret = rmdir(path); - if (ret < 0) - die("rmdir %s", path); - tracefs_put_tracing_file(path); + tracefs_remove_instance(instance->tracefs); } } @@ -5029,7 +4924,8 @@ static int test_stacktrace_trigger(struct buffer_instance *instance) int ret = 0; int fd; - path = get_instance_file(instance, "events/sched/sched_switch/trigger"); + path = tracefs_get_instance_file(instance->tracefs, + "events/sched/sched_switch/trigger"); clear_trigger(path); @@ -5211,6 +5107,15 @@ void update_first_instance(struct buffer_instance *instance, int topt) first_instance = buffer_instances; } +void init_top_instance(void) +{ + if (!top_instance.tracefs) + top_instance.tracefs = tracefs_alloc_instance(NULL); + top_instance.cpu_count = count_cpus(); + top_instance.flags = BUFFER_FL_KEEP; + init_instance(&top_instance); +} + enum { OPT_user = 243, OPT_procmap = 244, @@ -5235,7 +5140,7 @@ void trace_stop(int argc, char **argv) int topt = 0; struct buffer_instance *instance = &top_instance; - init_instance(instance); + init_top_instance(); for (;;) { int c; @@ -5276,7 +5181,7 @@ void trace_restart(int argc, char **argv) int topt = 0; struct buffer_instance *instance = &top_instance; - init_instance(instance); + init_top_instance(); for (;;) { int c; @@ -5318,7 +5223,7 @@ void trace_reset(int argc, char **argv) int topt = 0; struct buffer_instance *instance = &top_instance; - init_instance(instance); + init_top_instance(); /* if last arg is -a, then -b and -d apply to all instances */ int last_specified_all = 0; @@ -5403,9 +5308,8 @@ static void init_common_record_context(struct common_record_context *ctx, memset(ctx, 0, sizeof(*ctx)); ctx->instance = &top_instance; ctx->curr_cmd = curr_cmd; - init_instance(ctx->instance); local_cpu_count = count_cpus(); - ctx->instance->cpu_count = local_cpu_count; + init_top_instance(); } #define IS_EXTRACT(ctx) ((ctx)->curr_cmd == CMD_extract) diff --git a/tracecmd/trace-show.c b/tracecmd/trace-show.c index 391d329..a6f2102 100644 --- a/tracecmd/trace-show.c +++ b/tracecmd/trace-show.c @@ -52,6 +52,8 @@ void trace_show(int argc, char **argv) {NULL, 0, NULL, 0} }; + init_top_instance(); + while ((c = getopt_long(argc-1, argv+1, "B:c:fsp", long_options, &option_index)) >= 0) { switch (c) { diff --git a/tracecmd/trace-stat.c b/tracecmd/trace-stat.c index 7a1d9bb..948118c 100644 --- a/tracecmd/trace-stat.c +++ b/tracecmd/trace-stat.c @@ -31,7 +31,7 @@ static int get_instance_file_fd(struct buffer_instance *instance, char *path; int fd; - path = get_instance_file(instance, file); + path = tracefs_get_instance_file(instance->tracefs, file); fd = open(path, O_RDONLY); tracefs_put_tracing_file(path); @@ -348,7 +348,7 @@ static void report_events(struct buffer_instance *instance) free(str); - path = get_instance_file(instance, "events"); + path = tracefs_get_instance_file(instance->tracefs, "events"); if (!path) die("malloc"); @@ -437,7 +437,7 @@ static void report_event_filters(struct buffer_instance *instance) enum event_iter_type type; enum event_process processed = PROCESSED_NONE; - path = get_instance_file(instance, "events"); + path = tracefs_get_instance_file(instance->tracefs, "events"); if (!path) die("malloc"); @@ -510,7 +510,7 @@ static void report_event_triggers(struct buffer_instance *instance) enum event_iter_type type; enum event_process processed = PROCESSED_NONE; - path = get_instance_file(instance, "events"); + path = tracefs_get_instance_file(instance->tracefs, "events"); if (!path) die("malloc"); @@ -599,7 +599,7 @@ static void report_graph_funcs(struct buffer_instance *instance) { char *path; - path = get_instance_file(instance, "set_graph_function"); + path = tracefs_get_instance_file(instance->tracefs, "set_graph_function"); if (!path) die("malloc"); @@ -607,7 +607,7 @@ static void report_graph_funcs(struct buffer_instance *instance) tracefs_put_tracing_file(path); - path = get_instance_file(instance, "set_graph_notrace"); + path = tracefs_get_instance_file(instance->tracefs, "set_graph_notrace"); if (!path) die("malloc"); @@ -620,7 +620,7 @@ static void report_ftrace_filters(struct buffer_instance *instance) { char *path; - path = get_instance_file(instance, "set_ftrace_filter"); + path = tracefs_get_instance_file(instance->tracefs, "set_ftrace_filter"); if (!path) die("malloc"); @@ -628,7 +628,7 @@ static void report_ftrace_filters(struct buffer_instance *instance) tracefs_put_tracing_file(path); - path = get_instance_file(instance, "set_ftrace_notrace"); + path = tracefs_get_instance_file(instance->tracefs, "set_ftrace_notrace"); if (!path) die("malloc"); @@ -858,7 +858,8 @@ static void stat_instance(struct buffer_instance *instance) if (instance != &top_instance) { if (instance != first_instance) printf("---------------\n"); - printf("Instance: %s\n", instance->name); + printf("Instance: %s\n", + tracefs_get_instance_name(instance->tracefs)); } report_plugin(instance); @@ -883,6 +884,8 @@ void trace_stat (int argc, char **argv) int status; int c; + init_top_instance(); + for (;;) { c = getopt(argc-1, argv+1, "tB:"); if (c == -1) From patchwork Mon Jan 6 15:40:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 11319551 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 810FB921 for ; Mon, 6 Jan 2020 15:41:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 414012075A for ; Mon, 6 Jan 2020 15:41:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UufyeBCR" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726477AbgAFPlL (ORCPT ); Mon, 6 Jan 2020 10:41:11 -0500 Received: from mail-lj1-f169.google.com ([209.85.208.169]:35054 "EHLO mail-lj1-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726494AbgAFPlK (ORCPT ); Mon, 6 Jan 2020 10:41:10 -0500 Received: by mail-lj1-f169.google.com with SMTP id j1so43973280lja.2 for ; Mon, 06 Jan 2020 07:41:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=HxtLpCcGe7c7M9OL0jezQrOdH914hxPx+vEqAakZN8k=; b=UufyeBCRnQ7xrT9eVbe+mqc59gn6vUkKlfaBbAWBFiNfQCW1yvRH7w/44RR8eGAszt 3Cwigsk8dEX5xi11fkP0KCbscfvW9+s3QS/Y19gAkLiA8OJHJzr+D0MLblrfoiEvVZNk Wl9l2liwVEqkg6WtCAGqGwgyIS58mubffv44ysJOFQ287ZCKE7SmV589uZEjOnrn33dC X+jr6MDd7nhYeOrHV3LQYnVL5mjdbwwCuH7xHPEOZO4R47bLgd76YpH/j/FSecZBfyjD YW8VW3A4YSksMG9VU4L3f+ORBJ+wAZARMo0thrW2c8MNjLH0wmuvnvmQhRpXAGgTa/5v w+7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HxtLpCcGe7c7M9OL0jezQrOdH914hxPx+vEqAakZN8k=; b=DruMs930hLPss46XyrIJv9KK2+p3+1M3un+zzuCT4bb0ONOWCqgMsUWIeInDdhVrCT J2udUEWvY50SdsNnZbgoU6f7lsHMZ+pKy+q7kszd1uk3s0Y95P3vPI7xJTP/3z9cr5IJ CRW/9NrdT2ux0ka1nqRuc0EaMFfFcElGrrH8UWIyPxwQh8L/RiFldhE7/+rHdKyviuL6 LeLU2HGPw+bEX66AUXa5OJkzUZpKlaQiSGobaYic1fkO6ErhLnfAn0jnhf8VXuuolw2Y 1OGnMR35jI8G8fSW/aZ36r561jz0rPivSPigMrR63A19lsWpiOI8KbKHwud6SbeWsfDH rw/w== X-Gm-Message-State: APjAAAWPSUjIxqcpPmFkUwIHgOW69a3A1oq9O1uqbxOB5s1JiRr52Gut 1yg/B6LT55z5vNdk0r95/W8= X-Google-Smtp-Source: APXvYqy7jJ97Bf62O2f8K6Er1LV4H/Lq3pc9NMun/C6nZbMyyx3Z846N0Udt1YcXVc3YMPXkq7rdww== X-Received: by 2002:a2e:818e:: with SMTP id e14mr58437675ljg.2.1578325266649; Mon, 06 Jan 2020 07:41:06 -0800 (PST) Received: from oberon.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id u25sm29257677lfk.46.2020.01.06.07.41.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jan 2020 07:41:05 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 4/5] trace-cmd,kernel-shark: New libtracefs APIs for ftrace events and systems Date: Mon, 6 Jan 2020 17:40:57 +0200 Message-Id: <20200106154058.60660-5-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200106154058.60660-1-tz.stoyanov@gmail.com> References: <20200106154058.60660-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org The functionality related to ftrace events and systems is moved from trace-cmd application and libtracecmd to libtracefs. The following libtracecmd APIs are removed: tracecmd_read_page_record(); tracecmd_event_systems(); tracecmd_system_events(); tracecmd_local_plugins(); tracecmd_add_list(); tracecmd_free_list(); The following new library APIs are introduced: tracefs_read_page_record(); tracefs_event_systems(); tracefs_system_events(); tracefs_local_plugins(); tracefs_iterate_raw_events(); Signed-off-by: Tzvetomir Stoyanov (VMware) --- include/trace-cmd/trace-cmd.h | 8 - include/tracefs/tracefs.h | 15 + kernel-shark/src/KsCaptureDialog.cpp | 2 +- lib/trace-cmd/trace-input.c | 95 ------ lib/trace-cmd/trace-util.c | 265 --------------- lib/tracefs/Makefile | 1 + lib/tracefs/tracefs-events.c | 476 +++++++++++++++++++++++++++ tracecmd/trace-record.c | 2 +- 8 files changed, 494 insertions(+), 370 deletions(-) create mode 100644 lib/tracefs/tracefs-events.c diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 66736ae..30bb144 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -24,15 +24,10 @@ void tracecmd_parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigne extern int tracecmd_disable_sys_plugins; extern int tracecmd_disable_plugins; -char **tracecmd_event_systems(const char *tracing_dir); -char **tracecmd_system_events(const char *tracing_dir, const char *system); struct tep_handle *tracecmd_local_events(const char *tracing_dir); int tracecmd_fill_local_events(const char *tracing_dir, struct tep_handle *pevent, int *parsing_failures); -char **tracecmd_local_plugins(const char *tracing_dir); -char **tracecmd_add_list(char **list, const char *name, int len); -void tracecmd_free_list(char **list); int *tracecmd_add_id(int *list, int id, int len); enum { @@ -143,9 +138,6 @@ void tracecmd_print_stats(struct tracecmd_input *handle); void tracecmd_print_uname(struct tracecmd_input *handle); void tracecmd_print_version(struct tracecmd_input *handle); -struct tep_record * -tracecmd_read_page_record(struct tep_handle *pevent, void *page, int size, - struct tep_record *last_record); struct tep_record * tracecmd_peek_data(struct tracecmd_input *handle, int cpu); diff --git a/include/tracefs/tracefs.h b/include/tracefs/tracefs.h index 6b27ff7..c66250c 100644 --- a/include/tracefs/tracefs.h +++ b/include/tracefs/tracefs.h @@ -34,4 +34,19 @@ int tracefs_write_instance_file(struct tracefs_instance *instance, char *tracefs_read_instance_file(struct tracefs_instance *instance, char *file, int *psize); +/* events */ +struct tep_record * +tracefs_read_page_record(struct tep_handle *tep, void *page, int size, + struct tep_record *last_record); +char **tracefs_event_systems(const char *tracing_dir); +char **tracefs_system_events(const char *tracing_dir, const char *system); +int tracefs_iterate_raw_events(struct tep_handle *tep, + struct tracefs_instance *instance, + int (*callback)(struct tep_event *, + struct tep_record *, + int, void *), + void *callback_context); + +char **tracefs_local_plugins(const char *tracing_dir); + #endif /* _TRACE_FS_H */ diff --git a/kernel-shark/src/KsCaptureDialog.cpp b/kernel-shark/src/KsCaptureDialog.cpp index 548b6fb..49c8755 100644 --- a/kernel-shark/src/KsCaptureDialog.cpp +++ b/kernel-shark/src/KsCaptureDialog.cpp @@ -204,7 +204,7 @@ QStringList KsCaptureControl::_getPlugins() QStringList pluginList; char **all_plugins; - all_plugins = tracecmd_local_plugins(tracefs_get_tracing_dir()); + all_plugins = tracefs_local_plugins(tracefs_get_tracing_dir()); if (!all_plugins) return pluginList; diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c index 3b187e3..67c7236 100644 --- a/lib/trace-cmd/trace-input.c +++ b/lib/trace-cmd/trace-input.c @@ -1663,101 +1663,6 @@ tracecmd_translate_data(struct tracecmd_input *handle, return record; } -/** - * tracecmd_read_page_record - read a record off of a page - * @pevent: pevent used to parse the page - * @page: the page to read - * @size: the size of the page - * @last_record: last record read from this page. - * - * If a ring buffer page is available, and the need to parse it - * without having a handle, then this function can be used. - * - * The @pevent needs to be initialized to have the page header information - * already available. - * - * The @last_record is used to know where to read the next record from. - * If @last_record is NULL, the first record on the page will be read. - * - * Returns: - * A newly allocated record that must be freed with free_record() if - * a record is found. Otherwise NULL is returned if the record is bad - * or no more records exist. - */ -struct tep_record * -tracecmd_read_page_record(struct tep_handle *pevent, void *page, int size, - struct tep_record *last_record) -{ - unsigned long long ts; - struct kbuffer *kbuf; - struct tep_record *record = NULL; - enum kbuffer_long_size long_size; - enum kbuffer_endian endian; - void *ptr; - - if (tep_is_file_bigendian(pevent)) - endian = KBUFFER_ENDIAN_BIG; - else - endian = KBUFFER_ENDIAN_LITTLE; - - if (tep_get_header_page_size(pevent) == 8) - long_size = KBUFFER_LSIZE_8; - else - long_size = KBUFFER_LSIZE_4; - - kbuf = kbuffer_alloc(long_size, endian); - if (!kbuf) - return NULL; - - kbuffer_load_subbuffer(kbuf, page); - if (kbuffer_subbuffer_size(kbuf) > size) { - warning("tracecmd_read_page_record: page_size > size"); - goto out_free; - } - - if (last_record) { - if (last_record->data < page || last_record->data >= (page + size)) { - warning("tracecmd_read_page_record: bad last record (size=%u)", - last_record->size); - goto out_free; - } - - ptr = kbuffer_read_event(kbuf, &ts); - while (ptr < last_record->data) { - ptr = kbuffer_next_event(kbuf, NULL); - if (!ptr) - break; - if (ptr == last_record->data) - break; - } - if (ptr != last_record->data) { - warning("tracecmd_read_page_record: could not find last_record"); - goto out_free; - } - ptr = kbuffer_next_event(kbuf, &ts); - } else - ptr = kbuffer_read_event(kbuf, &ts); - - if (!ptr) - goto out_free; - - record = malloc(sizeof(*record)); - if (!record) - return NULL; - memset(record, 0, sizeof(*record)); - - record->ts = ts; - record->size = kbuffer_event_size(kbuf); - record->record_size = kbuffer_curr_size(kbuf); - record->cpu = 0; - record->data = ptr; - record->ref_count = 1; - - out_free: - kbuffer_free(kbuf); - return record; -} - /** * tracecmd_peek_data - return the record at the current location. * @handle: input handle for the trace.dat file diff --git a/lib/trace-cmd/trace-util.c b/lib/trace-cmd/trace-util.c index 1394469..1554e88 100644 --- a/lib/trace-cmd/trace-util.c +++ b/lib/trace-cmd/trace-util.c @@ -153,56 +153,6 @@ static char *append_file(const char *dir, const char *name) return ret < 0 ? NULL : file; } -/** - * tracecmd_add_list - add an new string to a string list. - * @list: list to add the string to (may be NULL) - * @name: the string to add - * @len: current length of list of strings. - * - * The typical usage is: - * - * systems = tracecmd_add_list(systems, name, len++); - * - * Returns the new allocated list with an allocated name added. - * The list will end with NULL. - */ -char **tracecmd_add_list(char **list, const char *name, int len) -{ - if (!list) - list = malloc(sizeof(*list) * 2); - else - list = realloc(list, sizeof(*list) * (len + 2)); - if (!list) - return NULL; - - list[len] = strdup(name); - if (!list[len]) - return NULL; - - list[len + 1] = NULL; - - return list; -} - -/** - * tracecmd_free_list - free a list created with tracecmd_add_list. - * @list: The list to free. - * - * Frees the list as well as the names within the list. - */ -void tracecmd_free_list(char **list) -{ - int i; - - if (!list) - return; - - for (i = 0; list[i]; i++) - free(list[i]); - - free(list); -} - /** * tracecmd_add_id - add an int to the event id list * @list: list to add the id to @@ -233,160 +183,6 @@ int *tracecmd_add_id(int *list, int id, int len) return list; } -/** - * tracecmd_event_systems - return list of systems for tracing - * @tracing_dir: directory holding the "events" directory - * - * Returns an allocated list of system names. Both the names and - * the list must be freed with free(). - * The list returned ends with a "NULL" pointer. - */ -char **tracecmd_event_systems(const char *tracing_dir) -{ - struct dirent *dent; - char **systems = NULL; - char *events_dir; - struct stat st; - DIR *dir; - int len = 0; - int ret; - - if (!tracing_dir) - return NULL; - - events_dir = append_file(tracing_dir, "events"); - if (!events_dir) - return NULL; - - /* - * Search all the directories in the events directory, - * and collect the ones that have the "enable" file. - */ - ret = stat(events_dir, &st); - if (ret < 0 || !S_ISDIR(st.st_mode)) - goto out_free; - - dir = opendir(events_dir); - if (!dir) - goto out_free; - - while ((dent = readdir(dir))) { - const char *name = dent->d_name; - char *enable; - char *sys; - - if (strcmp(name, ".") == 0 || - strcmp(name, "..") == 0) - continue; - - sys = append_file(events_dir, name); - ret = stat(sys, &st); - if (ret < 0 || !S_ISDIR(st.st_mode)) { - free(sys); - continue; - } - - enable = append_file(sys, "enable"); - - ret = stat(enable, &st); - if (ret >= 0) - systems = tracecmd_add_list(systems, name, len++); - - free(enable); - free(sys); - } - - closedir(dir); - - out_free: - free(events_dir); - return systems; -} - -/** - * tracecmd_system_events - return list of events for system - * @tracing_dir: directory holding the "events" directory - * @system: the system to return the events for - * - * Returns an allocated list of event names. Both the names and - * the list must be freed with free(). - * The list returned ends with a "NULL" pointer. - */ -char **tracecmd_system_events(const char *tracing_dir, const char *system) -{ - struct dirent *dent; - char **events = NULL; - char *events_dir; - char *system_dir; - struct stat st; - DIR *dir; - int len = 0; - int ret; - - if (!tracing_dir || !system) - return NULL; - - events_dir = append_file(tracing_dir, "events"); - if (!events_dir) - return NULL; - - /* - * Search all the directories in the systems directory, - * and collect the ones that have the "enable" file. - */ - ret = stat(events_dir, &st); - if (ret < 0 || !S_ISDIR(st.st_mode)) - goto out_free; - - system_dir = append_file(events_dir, system); - if (!system_dir) - goto out_free; - - ret = stat(system_dir, &st); - if (ret < 0 || !S_ISDIR(st.st_mode)) - goto out_free_sys; - - dir = opendir(system_dir); - if (!dir) - goto out_free_sys; - - while ((dent = readdir(dir))) { - const char *name = dent->d_name; - char *enable; - char *event; - - if (strcmp(name, ".") == 0 || - strcmp(name, "..") == 0) - continue; - - event = append_file(system_dir, name); - ret = stat(event, &st); - if (ret < 0 || !S_ISDIR(st.st_mode)) { - free(event); - continue; - } - - enable = append_file(event, "enable"); - - ret = stat(enable, &st); - if (ret >= 0) - events = tracecmd_add_list(events, name, len++); - - free(enable); - free(event); - } - - closedir(dir); - - out_free_sys: - free(system_dir); - - out_free: - free(events_dir); - - return events; -} - static int read_file(const char *file, char **buffer) { char *buf; @@ -604,67 +400,6 @@ int tracecmd_fill_local_events(const char *tracing_dir, return ret; } -/** - * tracecmd_local_plugins - returns an array of available tracer plugins - * @tracing_dir: The directory that contains the tracing directory - * - * Returns an allocate list of plugins. The array ends with NULL. - * Both the plugin names and array must be freed with free(). - */ -char **tracecmd_local_plugins(const char *tracing_dir) -{ - char *available_tracers; - struct stat st; - char **plugins = NULL; - char *buf; - char *str, *saveptr; - char *plugin; - int slen; - int len; - int ret; - - if (!tracing_dir) - return NULL; - - available_tracers = append_file(tracing_dir, "available_tracers"); - if (!available_tracers) - return NULL; - - ret = stat(available_tracers, &st); - if (ret < 0) - goto out_free; - - len = read_file(available_tracers, &buf); - if (len < 0) - goto out_free; - - len = 0; - for (str = buf; ; str = NULL) { - plugin = strtok_r(str, " ", &saveptr); - if (!plugin) - break; - if (!(slen = strlen(plugin))) - continue; - - /* chop off any newlines */ - if (plugin[slen - 1] == '\n') - plugin[slen - 1] = '\0'; - - /* Skip the non tracers */ - if (strcmp(plugin, "nop") == 0 || - strcmp(plugin, "none") == 0) - continue; - - plugins = tracecmd_add_list(plugins, plugin, len++); - } - free(buf); - - out_free: - free(available_tracers); - - return plugins; -} - struct add_plugin_data { int ret; int index; diff --git a/lib/tracefs/Makefile b/lib/tracefs/Makefile index 4030272..5763e06 100644 --- a/lib/tracefs/Makefile +++ b/lib/tracefs/Makefile @@ -9,6 +9,7 @@ DEFAULT_TARGET = $(bdir)/libtracefs.a OBJS = OBJS += tracefs-utils.o OBJS += tracefs-instance.o +OBJS += tracefs-events.o OBJS := $(OBJS:%.o=$(bdir)/%.o) DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) diff --git a/lib/tracefs/tracefs-events.c b/lib/tracefs/tracefs-events.c new file mode 100644 index 0000000..5d40f06 --- /dev/null +++ b/lib/tracefs/tracefs-events.c @@ -0,0 +1,476 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt + * + * Updates: + * Copyright (C) 2019, VMware, Tzvetomir Stoyanov + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include "kbuffer.h" +#include "tracefs.h" +#include "tracefs-local.h" + +/** + * tracefs_read_page_record - read a record off of a page + * @tep: tep used to parse the page + * @page: the page to read + * @size: the size of the page + * @last_record: last record read from this page + * + * If a ring buffer page is available, and the need to parse it + * without having a handle, then this function can be used + * + * The @tep needs to be initialized to have the page header information + * already available. + * + * The @last_record is used to know where to read the next record from + * If @last_record is NULL, the first record on the page will be read + * + * Returns: + * A newly allocated record that must be freed with free_record() if + * a record is found. Otherwise NULL is returned if the record is bad + * or no more records exist + */ +struct tep_record * +tracefs_read_page_record(struct tep_handle *tep, void *page, int size, + struct tep_record *last_record) +{ + unsigned long long ts; + struct kbuffer *kbuf; + struct tep_record *record = NULL; + enum kbuffer_long_size long_size; + enum kbuffer_endian endian; + void *ptr; + + if (tep_is_file_bigendian(tep)) + endian = KBUFFER_ENDIAN_BIG; + else + endian = KBUFFER_ENDIAN_LITTLE; + + if (tep_get_header_page_size(tep) == 8) + long_size = KBUFFER_LSIZE_8; + else + long_size = KBUFFER_LSIZE_4; + + kbuf = kbuffer_alloc(long_size, endian); + if (!kbuf) + return NULL; + + kbuffer_load_subbuffer(kbuf, page); + if (kbuffer_subbuffer_size(kbuf) > size) { + warning("%s: page_size > size", __func__); + goto out_free; + } + + if (last_record) { + if (last_record->data < page || last_record->data >= (page + size)) { + warning("%s: bad last record (size=%u)", + __func__, last_record->size); + goto out_free; + } + + ptr = kbuffer_read_event(kbuf, &ts); + while (ptr < last_record->data) { + ptr = kbuffer_next_event(kbuf, NULL); + if (!ptr) + break; + if (ptr == last_record->data) + break; + } + if (ptr != last_record->data) { + warning("$s: could not find last_record", __func__); + goto out_free; + } + ptr = kbuffer_next_event(kbuf, &ts); + } else + ptr = kbuffer_read_event(kbuf, &ts); + + if (!ptr) + goto out_free; + + record = malloc(sizeof(*record)); + if (!record) + return NULL; + memset(record, 0, sizeof(*record)); + + record->ts = ts; + record->size = kbuffer_event_size(kbuf); + record->record_size = kbuffer_curr_size(kbuf); + record->cpu = 0; + record->data = ptr; + record->ref_count = 1; + + out_free: + kbuffer_free(kbuf); + return record; +} + +static void free_record(struct tep_record *record) +{ + if (!record) + return; + + if (record->ref_count > 0) + record->ref_count--; + if (record->ref_count) + return; + + free(record); +} + +static int +get_events_in_page(struct tep_handle *tep, void *page, + int size, int cpu, + int (*callback)(struct tep_event *, + struct tep_record *, + int, void *), + void *callback_context) +{ + struct tep_record *last_record = NULL; + struct tep_event *event = NULL; + struct tep_record *record; + int id, cnt = 0; + + if (size <= 0) + return 0; + + while (true) { + event = NULL; + record = tracefs_read_page_record(tep, page, size, last_record); + if (!record) + break; + free_record(last_record); + id = tep_data_type(tep, record); + event = tep_find_event(tep, id); + if (event && callback) { + if (callback(event, record, cpu, callback_context)) + break; + } + last_record = record; + } + free_record(last_record); + + return cnt; +} + +/* + * tracefs_iterate_raw_events - Iterate through events in trace_pipe_raw + * per CPU trace files + * @tep: a handle to the trace event parser context + * @instance: ftrace instance, can be NULL for the top instance + * @callback: A user function, called for each record from the file + * @callback_context: A custom context, passed to the user callback function + * + * If the @callback returns non-zero, the iteration stops - in that case all + * records from the current page will be lost from future reads + * + * Returns -1 in case of an error, or 0 otherwise + */ +int tracefs_iterate_raw_events(struct tep_handle *tep, + struct tracefs_instance *instance, + int (*callback)(struct tep_event *, + struct tep_record *, + int, void *), + void *callback_context) +{ + unsigned int p_size; + struct dirent *dent; + char file[PATH_MAX]; + void *page = NULL; + struct stat st; + char *path; + DIR *dir; + int ret; + int cpu; + int fd; + int r; + + p_size = getpagesize(); + path = tracefs_get_instance_file(instance, "per_cpu"); + if (!path) + return -1; + dir = opendir(path); + if (!dir) { + ret = -1; + goto error; + } + page = malloc(p_size); + if (!page) { + ret = -1; + goto error; + } + while ((dent = readdir(dir))) { + const char *name = dent->d_name; + + if (strlen(name) < 4 || strncmp(name, "cpu", 3) != 0) + continue; + cpu = atoi(name + 3); + sprintf(file, "%s/%s", path, name); + ret = stat(file, &st); + if (ret < 0 || !S_ISDIR(st.st_mode)) + continue; + + sprintf(file, "%s/%s/trace_pipe_raw", path, name); + fd = open(file, O_RDONLY | O_NONBLOCK); + if (fd < 0) + continue; + do { + r = read(fd, page, p_size); + if (r > 0) + get_events_in_page(tep, page, r, cpu, + callback, callback_context); + } while (r > 0); + close(fd); + } + ret = 0; + +error: + if (dir) + closedir(dir); + free(page); + tracefs_put_tracing_file(path); + return ret; +} + +static char **add_list_string(char **list, const char *name, int len) +{ + if (!list) + list = malloc(sizeof(*list) * 2); + else + list = realloc(list, sizeof(*list) * (len + 2)); + if (!list) + return NULL; + + list[len] = strdup(name); + if (!list[len]) + return NULL; + + list[len + 1] = NULL; + + return list; +} + +static char *append_file(const char *dir, const char *name) +{ + char *file; + int ret; + + ret = asprintf(&file, "%s/%s", dir, name); + + return ret < 0 ? NULL : file; +} + +/** + * tracefs_event_systems - return list of systems for tracing + * @tracing_dir: directory holding the "events" directory + * if NULL, top tracing directory is used + * + * Returns an allocated list of system names. Both the names and + * the list must be freed with free() + * The list returned ends with a "NULL" pointer + */ +char **tracefs_event_systems(const char *tracing_dir) +{ + struct dirent *dent; + char **systems = NULL; + char *events_dir; + struct stat st; + DIR *dir; + int len = 0; + int ret; + + if (!tracing_dir) + tracing_dir = tracefs_get_tracing_dir(); + + if (!tracing_dir) + return NULL; + + events_dir = append_file(tracing_dir, "events"); + if (!events_dir) + return NULL; + + /* + * Search all the directories in the events directory, + * and collect the ones that have the "enable" file. + */ + ret = stat(events_dir, &st); + if (ret < 0 || !S_ISDIR(st.st_mode)) + goto out_free; + + dir = opendir(events_dir); + if (!dir) + goto out_free; + + while ((dent = readdir(dir))) { + const char *name = dent->d_name; + char *enable; + char *sys; + + if (strcmp(name, ".") == 0 || + strcmp(name, "..") == 0) + continue; + + sys = append_file(events_dir, name); + ret = stat(sys, &st); + if (ret < 0 || !S_ISDIR(st.st_mode)) { + free(sys); + continue; + } + + enable = append_file(sys, "enable"); + + ret = stat(enable, &st); + if (ret >= 0) + systems = add_list_string(systems, name, len++); + + free(enable); + free(sys); + } + + closedir(dir); + + out_free: + free(events_dir); + return systems; +} + +/** + * tracefs_system_events - return list of events for system + * @tracing_dir: directory holding the "events" directory + * @system: the system to return the events for + * + * Returns an allocated list of event names. Both the names and + * the list must be freed with free() + * The list returned ends with a "NULL" pointer + */ +char **tracefs_system_events(const char *tracing_dir, const char *system) +{ + struct dirent *dent; + char **events = NULL; + char *system_dir = NULL; + struct stat st; + DIR *dir; + int len = 0; + int ret; + + if (!tracing_dir) + tracing_dir = tracefs_get_tracing_dir(); + + if (!tracing_dir || !system) + return NULL; + + asprintf(&system_dir, "%s/events/%s", tracing_dir, system); + if (!system_dir) + return NULL; + + ret = stat(system_dir, &st); + if (ret < 0 || !S_ISDIR(st.st_mode)) + goto out_free; + + dir = opendir(system_dir); + if (!dir) + goto out_free; + + while ((dent = readdir(dir))) { + const char *name = dent->d_name; + char *enable; + char *event; + + if (strcmp(name, ".") == 0 || + strcmp(name, "..") == 0) + continue; + + event = append_file(system_dir, name); + ret = stat(event, &st); + if (ret < 0 || !S_ISDIR(st.st_mode)) { + free(event); + continue; + } + + enable = append_file(event, "enable"); + + ret = stat(enable, &st); + if (ret >= 0) + events = add_list_string(events, name, len++); + + free(enable); + free(event); + } + + closedir(dir); + + out_free: + free(system_dir); + + return events; +} + +/** + * tracefs_local_plugins - returns an array of available tracer plugins + * @tracing_dir: The directory that contains the tracing directory + * + * Returns an allocate list of plugins. The array ends with NULL + * Both the plugin names and array must be freed with free() + */ +char **tracefs_local_plugins(const char *tracing_dir) +{ + char *available_tracers; + struct stat st; + char **plugins = NULL; + char *buf; + char *str, *saveptr; + char *plugin; + int slen; + int len; + int ret; + + if (!tracing_dir) + return NULL; + + available_tracers = append_file(tracing_dir, "available_tracers"); + if (!available_tracers) + return NULL; + + ret = stat(available_tracers, &st); + if (ret < 0) + goto out_free; + + len = str_read_file(available_tracers, &buf); + if (len < 0) + goto out_free; + + len = 0; + for (str = buf; ; str = NULL) { + plugin = strtok_r(str, " ", &saveptr); + if (!plugin) + break; + slen = strlen(plugin); + if (!slen) + continue; + + /* chop off any newlines */ + if (plugin[slen - 1] == '\n') + plugin[slen - 1] = '\0'; + + /* Skip the non tracers */ + if (strcmp(plugin, "nop") == 0 || + strcmp(plugin, "none") == 0) + continue; + + plugins = add_list_string(plugins, plugin, len++); + } + free(buf); + + out_free: + free(available_tracers); + + return plugins; +} diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 62f67d5..1d91e87 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -4178,7 +4178,7 @@ find_ts_in_page(struct tep_handle *pevent, void *page, int size) return 0; while (!ts) { - record = tracecmd_read_page_record(pevent, page, size, + record = tracefs_read_page_record(pevent, page, size, last_record); if (!record) break; From patchwork Mon Jan 6 15:40:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 11319553 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AB6A314BD for ; Mon, 6 Jan 2020 15:41:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8ABC520848 for ; Mon, 6 Jan 2020 15:41:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="VUGAdhJH" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726494AbgAFPlL (ORCPT ); Mon, 6 Jan 2020 10:41:11 -0500 Received: from mail-lj1-f194.google.com ([209.85.208.194]:45914 "EHLO mail-lj1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726296AbgAFPlL (ORCPT ); Mon, 6 Jan 2020 10:41:11 -0500 Received: by mail-lj1-f194.google.com with SMTP id j26so51328505ljc.12 for ; Mon, 06 Jan 2020 07:41:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ZmuTKjyjRQWO5Fipht30ZbMXPmsW+J8mNdn7ecMTx4A=; b=VUGAdhJH7FrEFBCkaQjC2slK+eYHVdRUec28WmsYGXb9T6MHDYZia0BSxawE4pnLIc l3+WM8BAeXPZ5puv4MQuhMZpyzOWapAXIsn271jrOnwQEW1s7xB2v6E7p4/ezCtwsPKS zgJnq0N20timUWUkpiZS019K9SznhpC06/FjY1RrkNI3tYbMzm5hrNUlORNCCijCo7qU QBo0M3XhSFHA9+UZlgeQ31ZnS8lvKk8pYA9ctt+6GoBQSeZdBq3/hjn4VlGlLjg0d+LF W8h5ytnlyFNxf7EDdBbCL6DxZyQdkqIUSaNJgrY6mO8KqGduFYJvY/y6Fwhwh8aiRyLG bwBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZmuTKjyjRQWO5Fipht30ZbMXPmsW+J8mNdn7ecMTx4A=; b=GAIfRtIDEZIjjmw0yEYa/CwKHH8VakPjy030zTdRN4yRLuqbf05nHhoDGlCuRC45EO VlkKLw04FR4MD/xqhZs1hfPtrQCq6/jCWSiR8F5wJ5di0QzBG7g91wPKWanvH1gfA0vp Hsc0Ko0yEQX8/iRHFXvP1LR9piY22aWmE4IL/PxcmwPjJq4fn65QsgFgspRYaooVqjtX UZ1GHrcLuq0yzagN++j0O9ljTxhsd/53e9DwlEPuSonApltYFV2RgY1p/W1MQe2uF/Jv 7gfPnVSqUn0Vmd9JEIEFV76ddSrLA460wp2XK/hmdwdMFShh3xY5w6XxxfcnBhHxwWIS v7yw== X-Gm-Message-State: APjAAAVI2QuJ7OuPJV5MPQdpMZDpL7BvwagU/0c1FGlnJobU+hEIS9gW m75Z4u4DRqVbNFy6pAh+ulo= X-Google-Smtp-Source: APXvYqw4agIDXR8AFfx9TSwpa058ckbVnSiBzn9LjGp466EiZ7JdKxwrVeD2pxSzvlWTF5nrr1UfPw== X-Received: by 2002:a05:651c:2c7:: with SMTP id f7mr8374002ljo.125.1578325268091; Mon, 06 Jan 2020 07:41:08 -0800 (PST) Received: from oberon.eng.vmware.com ([146.247.46.5]) by smtp.gmail.com with ESMTPSA id u25sm29257677lfk.46.2020.01.06.07.41.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jan 2020 07:41:07 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v2 5/5] trace-cmd,kernel-shark: New libtracefs APIs for loading ftrace events Date: Mon, 6 Jan 2020 17:40:58 +0200 Message-Id: <20200106154058.60660-6-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200106154058.60660-1-tz.stoyanov@gmail.com> References: <20200106154058.60660-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Sender: linux-trace-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org The functionality related to loading local ftrace events to a pet handler is moved from libtracecmd to libtracefs. The following libtracecmd APIs are removed: tracecmd_local_events(); tracecmd_fill_local_events(); The following new library APIs are introduced: tracefs_local_events(); tracefs_fill_local_events(); The APIs are reimplemented to reuse functionality from tracefs_event_systems() and tracefs_system_events() Signed-off-by: Tzvetomir Stoyanov (VMware) --- include/trace-cmd/trace-cmd.h | 4 - include/tracefs/tracefs.h | 4 + kernel-shark/src/KsCaptureDialog.cpp | 2 +- lib/trace-cmd/trace-util.c | 228 --------------------------- lib/tracefs/tracefs-events.c | 185 ++++++++++++++++++++++ tracecmd/trace-check-events.c | 2 +- 6 files changed, 191 insertions(+), 234 deletions(-) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index 30bb144..da5bd2d 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -24,10 +24,6 @@ void tracecmd_parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigne extern int tracecmd_disable_sys_plugins; extern int tracecmd_disable_plugins; -struct tep_handle *tracecmd_local_events(const char *tracing_dir); -int tracecmd_fill_local_events(const char *tracing_dir, - struct tep_handle *pevent, int *parsing_failures); - int *tracecmd_add_id(int *list, int id, int len); enum { diff --git a/include/tracefs/tracefs.h b/include/tracefs/tracefs.h index c66250c..998671b 100644 --- a/include/tracefs/tracefs.h +++ b/include/tracefs/tracefs.h @@ -49,4 +49,8 @@ int tracefs_iterate_raw_events(struct tep_handle *tep, char **tracefs_local_plugins(const char *tracing_dir); +struct tep_handle *tracefs_local_events(const char *tracing_dir); +int tracefs_fill_local_events(const char *tracing_dir, + struct tep_handle *tep, int *parsing_failures); + #endif /* _TRACE_FS_H */ diff --git a/kernel-shark/src/KsCaptureDialog.cpp b/kernel-shark/src/KsCaptureDialog.cpp index 49c8755..409eb0e 100644 --- a/kernel-shark/src/KsCaptureDialog.cpp +++ b/kernel-shark/src/KsCaptureDialog.cpp @@ -26,7 +26,7 @@ extern "C" { static inline tep_handle *local_events() { - return tracecmd_local_events(tracefs_get_tracing_dir()); + return tracefs_local_events(tracefs_get_tracing_dir()); } /** diff --git a/lib/trace-cmd/trace-util.c b/lib/trace-cmd/trace-util.c index 1554e88..795e83d 100644 --- a/lib/trace-cmd/trace-util.c +++ b/lib/trace-cmd/trace-util.c @@ -142,17 +142,6 @@ void tracecmd_parse_ftrace_printk(struct tep_handle *pevent, } } -/* FIXME: append_file() is duplicated and could be consolidated */ -static char *append_file(const char *dir, const char *name) -{ - char *file; - int ret; - - ret = asprintf(&file, "%s/%s", dir, name); - - return ret < 0 ? NULL : file; -} - /** * tracecmd_add_id - add an int to the event id list * @list: list to add the id to @@ -183,223 +172,6 @@ int *tracecmd_add_id(int *list, int id, int len) return list; } -static int read_file(const char *file, char **buffer) -{ - char *buf; - int len = 0; - int fd; - int r; - - fd = open(file, O_RDONLY); - if (fd < 0) - return -1; - - buf = malloc(BUFSIZ + 1); - if (!buf) { - len = -1; - goto out; - } - - while ((r = read(fd, buf + len, BUFSIZ)) > 0) { - len += r; - buf = realloc(buf, len + BUFSIZ + 1); - if (!buf) { - len = -1; - goto out; - } - } - - *buffer = buf; - buf[len] = 0; - out: - close(fd); - - return len; -} - -static int load_events(struct tep_handle *pevent, const char *system, - const char *sys_dir) -{ - struct dirent *dent; - struct stat st; - DIR *dir; - int len = 0; - int ret = 0, failure = 0; - - ret = stat(sys_dir, &st); - if (ret < 0 || !S_ISDIR(st.st_mode)) - return EINVAL; - - dir = opendir(sys_dir); - if (!dir) - return errno; - - while ((dent = readdir(dir))) { - const char *name = dent->d_name; - char *event; - char *format; - char *buf; - - if (strcmp(name, ".") == 0 || - strcmp(name, "..") == 0) - continue; - - event = append_file(sys_dir, name); - ret = stat(event, &st); - if (ret < 0 || !S_ISDIR(st.st_mode)) - goto free_event; - - format = append_file(event, "format"); - ret = stat(format, &st); - if (ret < 0) - goto free_format; - - len = read_file(format, &buf); - if (len < 0) - goto free_format; - - ret = tep_parse_event(pevent, buf, len, system); - free(buf); - free_format: - free(format); - free_event: - free(event); - if (ret) - failure = ret; - } - - closedir(dir); - return failure; -} - -static int read_header(struct tep_handle *pevent, const char *events_dir) -{ - struct stat st; - char *header; - char *buf; - int len; - int ret = -1; - - header = append_file(events_dir, "header_page"); - - ret = stat(header, &st); - if (ret < 0) - goto out; - - len = read_file(header, &buf); - if (len < 0) - goto out; - - tep_parse_header_page(pevent, buf, len, sizeof(long)); - - free(buf); - - ret = 0; - out: - free(header); - return ret; -} - -/** - * tracecmd_local_events - create a pevent from the events on system - * @tracing_dir: The directory that contains the events. - * - * Returns a pevent structure that contains the pevents local to - * the system. - */ -struct tep_handle *tracecmd_local_events(const char *tracing_dir) -{ - struct tep_handle *pevent = NULL; - - pevent = tep_alloc(); - if (!pevent) - return NULL; - - if (tracecmd_fill_local_events(tracing_dir, pevent, NULL)) { - tep_free(pevent); - pevent = NULL; - } - - return pevent; -} - -/** - * tracecmd_fill_local_events - Fill a pevent with the events on system - * @tracing_dir: The directory that contains the events. - * @pevent: Allocated pevent which will be filled - * @parsing_failures: return number of failures while parsing the event files - * - * Returns whether the operation succeeded - */ -int tracecmd_fill_local_events(const char *tracing_dir, - struct tep_handle *pevent, int *parsing_failures) -{ - struct dirent *dent; - char *events_dir; - struct stat st; - DIR *dir; - int ret; - - if (!tracing_dir) - return -1; - if (parsing_failures) - *parsing_failures = 0; - - events_dir = append_file(tracing_dir, "events"); - if (!events_dir) - return -1; - - ret = stat(events_dir, &st); - if (ret < 0 || !S_ISDIR(st.st_mode)) { - ret = -1; - goto out_free; - } - - dir = opendir(events_dir); - if (!dir) { - ret = -1; - goto out_free; - } - - ret = read_header(pevent, events_dir); - if (ret < 0) { - ret = -1; - goto out_free; - } - - while ((dent = readdir(dir))) { - const char *name = dent->d_name; - char *sys; - - if (strcmp(name, ".") == 0 || - strcmp(name, "..") == 0) - continue; - - sys = append_file(events_dir, name); - ret = stat(sys, &st); - if (ret < 0 || !S_ISDIR(st.st_mode)) { - free(sys); - continue; - } - - ret = load_events(pevent, name, sys); - - free(sys); - - if (ret && parsing_failures) - (*parsing_failures)++; - } - - closedir(dir); - /* always succeed because parsing failures are not critical */ - ret = 0; - - out_free: - free(events_dir); - - return ret; -} - struct add_plugin_data { int ret; int index; diff --git a/lib/tracefs/tracefs-events.c b/lib/tracefs/tracefs-events.c index 5d40f06..805db86 100644 --- a/lib/tracefs/tracefs-events.c +++ b/lib/tracefs/tracefs-events.c @@ -474,3 +474,188 @@ char **tracefs_local_plugins(const char *tracing_dir) return plugins; } + +static int load_events(struct tep_handle *tep, + const char *tracing_dir, const char *system) +{ + int ret = 0, failure = 0; + char **events = NULL; + struct stat st; + int len = 0; + int i; + + events = tracefs_system_events(tracing_dir, system); + if (!events) + return -ENOENT; + + for (i = 0; events[i]; i++) { + char *format; + char *buf; + + ret = asprintf(&format, "%s/events/%s/%s/format", + tracing_dir, system, events[i]); + if (ret < 0) { + failure = -ENOMEM; + break; + } + + ret = stat(format, &st); + if (ret < 0) + goto next_event; + + len = str_read_file(format, &buf); + if (len < 0) + goto next_event; + + ret = tep_parse_event(tep, buf, len, system); + free(buf); +next_event: + free(format); + if (ret) + failure = ret; + } + + if (events) { + for (i = 0; events[i]; i++) + free(events[i]); + free(events); + } + return failure; +} + +static int read_header(struct tep_handle *tep, const char *tracing_dir) +{ + struct stat st; + char *header; + char *buf; + int len; + int ret = -1; + + header = append_file(tracing_dir, "events/header_page"); + + ret = stat(header, &st); + if (ret < 0) + goto out; + + len = str_read_file(header, &buf); + if (len < 0) + goto out; + + tep_parse_header_page(tep, buf, len, sizeof(long)); + + free(buf); + + ret = 0; + out: + free(header); + return ret; +} + +static bool contains(const char *name, const char * const *names) +{ + if (!names) + return false; + for (; *names; names++) + if (strcmp(name, *names) == 0) + return true; + return false; +} + +static int tracecmd_fill_local_events_system(const char *tracing_dir, + struct tep_handle *tep, + const char * const *sys_names, + int *parsing_failures) +{ + char **systems = NULL; + int ret; + int i; + + if (!tracing_dir) + tracing_dir = tracefs_get_tracing_dir(); + if (!tracing_dir) + return -1; + + systems = tracefs_event_systems(tracing_dir); + if (!systems) + return -1; + + ret = read_header(tep, tracing_dir); + if (ret < 0) { + ret = -1; + goto out; + } + + if (parsing_failures) + *parsing_failures = 0; + + for (i = 0; systems[i]; i++) { + if (sys_names && !contains(systems[i], sys_names)) + continue; + ret = load_events(tep, tracing_dir, systems[i]); + if (ret && parsing_failures) + (*parsing_failures)++; + } + /* always succeed because parsing failures are not critical */ + ret = 0; +out: + if (systems) { + for (i = 0; systems[i]; i++) + free(systems[i]); + free(systems); + } + return ret; +} + +/** + * tracecmd_local_events_system - create a tep from the events of the specified subsystem. + * + * @tracing_dir: The directory that contains the events. + * @sys_name: Array of system names, to load the events from. + * The last element from the array must be NULL + * + * Returns a tep structure that contains the tep local to + * the system. + */ +struct tep_handle *tracecmd_local_events_system(const char *tracing_dir, + const char * const *sys_names) +{ + struct tep_handle *tep = NULL; + + tep = tep_alloc(); + if (!tep) + return NULL; + + if (tracecmd_fill_local_events_system(tracing_dir, tep, sys_names, NULL)) { + tep_free(tep); + tep = NULL; + } + + return tep; +} + +/** + * tracefs_local_events - create a tep from the events on system + * @tracing_dir: The directory that contains the events. + * + * Returns a tep structure that contains the teps local to + * the system. + */ +struct tep_handle *tracefs_local_events(const char *tracing_dir) +{ + return tracecmd_local_events_system(tracing_dir, NULL); +} + +/** + * tracefs_fill_local_events - Fill a tep with the events on system + * @tracing_dir: The directory that contains the events. + * @tep: Allocated tep handler which will be filled + * @parsing_failures: return number of failures while parsing the event files + * + * Returns whether the operation succeeded + */ +int tracefs_fill_local_events(const char *tracing_dir, + struct tep_handle *tep, int *parsing_failures) +{ + return tracecmd_fill_local_events_system(tracing_dir, tep, + NULL, parsing_failures); +} diff --git a/tracecmd/trace-check-events.c b/tracecmd/trace-check-events.c index a8ee60a..d37af67 100644 --- a/tracecmd/trace-check-events.c +++ b/tracecmd/trace-check-events.c @@ -50,7 +50,7 @@ void trace_check_events(int argc, char **argv) tep_set_flag(pevent, TEP_DISABLE_SYS_PLUGINS); list = tep_load_plugins(pevent); - ret = tracecmd_fill_local_events(tracing, pevent, &parsing_failures); + ret = tracefs_fill_local_events(tracing, pevent, &parsing_failures); if (ret || parsing_failures) ret = EINVAL; tep_unload_plugins(list, pevent);