From: David Ahern <dsahern@gmail.com>
To: rostedt@goodmis.org, acme@ghostprotocols.net,
linux-kernel@vger.kernel.org, weisbec@gmail.com
Cc: namhyung.kim@lge.com, mingo@kernel.org, peterz@infradead.org,
David Ahern <dsahern@gmail.com>
Subject: [RFC PATCH 1/2] libtraceevent: Add support for tracecmd plugins
Date: Thu, 14 Jun 2012 11:35:32 -0600 [thread overview]
Message-ID: <1339695333-64591-2-git-send-email-dsahern@gmail.com> (raw)
In-Reply-To: <1339695333-64591-1-git-send-email-dsahern@gmail.com>
Plugin code pulled from trace-cmd repository as of 9a5cd1c1,
cherry-picked the plugin loading functions from trace-util.c
and declarations in trace-cmd.h
Signed-off-by: David Ahern <dsahern@gmail.com>
---
tools/lib/traceevent/Makefile | 2 +-
tools/lib/traceevent/tracecmd-plugins.c | 280 +++++++++++++++++++++++++++++++
tools/lib/traceevent/tracecmd-plugins.h | 34 ++++
3 files changed, 315 insertions(+), 1 deletion(-)
create mode 100644 tools/lib/traceevent/tracecmd-plugins.c
create mode 100644 tools/lib/traceevent/tracecmd-plugins.h
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 3d69aa9..b1833ff 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -188,7 +188,7 @@ $(obj)/%.o: $(src)/%.c
%.o: $(src)/%.c
$(Q)$(call do_compile)
-PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o
+PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o tracecmd-plugins.o
ALL_OBJS = $(PEVENT_LIB_OBJS)
diff --git a/tools/lib/traceevent/tracecmd-plugins.c b/tools/lib/traceevent/tracecmd-plugins.c
new file mode 100644
index 0000000..24b004a
--- /dev/null
+++ b/tools/lib/traceevent/tracecmd-plugins.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <errno.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "tracecmd-plugins.h"
+
+#define LOCAL_PLUGIN_DIR ".trace-cmd/plugins"
+
+int tracecmd_disable_sys_plugins;
+int tracecmd_disable_plugins;
+
+
+static struct trace_plugin_options {
+ struct trace_plugin_options *next;
+ char *plugin;
+ char *option;
+ char *value;
+} *trace_plugin_options;
+
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
+#ifndef MAX_PATH
+# define MAX_PATH 1024
+#endif
+
+static struct plugin_list {
+ struct plugin_list *next;
+ char *name;
+ void *handle;
+};
+
+static void update_option(const char *file, struct plugin_option *option)
+{
+ struct trace_plugin_options *op;
+ char *plugin;
+
+ if (option->plugin_alias) {
+ plugin = strdup(option->plugin_alias);
+ if (!plugin)
+ die("malloc");
+ } else {
+ char *p;
+ plugin = strdup(file);
+ if (!plugin)
+ die("malloc");
+ p = strstr(plugin, ".");
+ if (p)
+ *p = '\0';
+ }
+
+ /* first look for named options */
+ for (op = trace_plugin_options; op; op = op->next) {
+ if (!op->plugin)
+ continue;
+ if (strcmp(op->plugin, plugin) != 0)
+ continue;
+ if (strcmp(op->option, option->name) != 0)
+ continue;
+
+ option->value = op->value;
+ option->set = 1;
+ goto out;
+ }
+
+ /* first look for unnamed options */
+ for (op = trace_plugin_options; op; op = op->next) {
+ if (op->plugin)
+ continue;
+ if (strcmp(op->option, option->name) != 0)
+ continue;
+
+ option->value = op->value;
+ option->set = 1;
+ break;
+ }
+
+ out:
+ free(plugin);
+}
+
+static void load_plugin(struct pevent *pevent, const char *path,
+ const char *file, void *data)
+{
+ struct plugin_list **plugin_list = data;
+ pevent_plugin_load_func func;
+ struct plugin_list *list;
+ struct plugin_option *options;
+ const char *alias;
+ char *plugin;
+ void *handle;
+
+ plugin = malloc_or_die(strlen(path) + strlen(file) + 2);
+
+ strcpy(plugin, path);
+ strcat(plugin, "/");
+ strcat(plugin, file);
+
+ handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
+ if (!handle) {
+ warning("cound not load plugin '%s'\n%s\n",
+ plugin, dlerror());
+ goto out_free;
+ }
+
+ alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
+ if (!alias)
+ alias = file;
+
+ options = dlsym(handle, PEVENT_PLUGIN_OPTIONS_NAME);
+ if (options) {
+ while (options->name) {
+ update_option(alias, options);
+ options++;
+ }
+ }
+
+ func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
+ if (!func) {
+ warning("cound not find func '%s' in plugin '%s'\n%s\n",
+ PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
+ goto out_free;
+ }
+
+ list = malloc_or_die(sizeof(*list));
+ list->next = *plugin_list;
+ list->handle = handle;
+ list->name = plugin;
+ *plugin_list = list;
+
+ pr_stat("registering plugin: %s", plugin);
+ func(pevent);
+ return;
+
+ out_free:
+ free(plugin);
+}
+
+static void
+trace_util_load_plugins_dir(struct pevent *pevent, const char *suffix,
+ const char *path,
+ void (*load_plugin)(struct pevent *pevent,
+ const char *path,
+ const char *name,
+ void *data),
+ void *data)
+{
+ struct dirent *dent;
+ struct stat st;
+ DIR *dir;
+ int ret;
+
+ ret = stat(path, &st);
+ if (ret < 0)
+ return;
+
+ if (!S_ISDIR(st.st_mode))
+ return;
+
+ dir = opendir(path);
+ if (!dir)
+ return;
+
+ while ((dent = readdir(dir))) {
+ const char *name = dent->d_name;
+
+ if (strcmp(name, ".") == 0 ||
+ strcmp(name, "..") == 0)
+ continue;
+
+ /* Only load plugins that end in suffix */
+ if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
+ continue;
+
+ load_plugin(pevent, path, name, data);
+ }
+
+ closedir(dir);
+
+ return;
+}
+
+void trace_util_load_plugins(struct pevent *pevent, const char *suffix,
+ void (*load_plugin)(struct pevent *pevent,
+ const char *path,
+ const char *name,
+ void *data),
+ void *data)
+{
+ char *home;
+ char *path;
+ char *envdir;
+
+ if (tracecmd_disable_plugins)
+ return;
+
+/* If a system plugin directory was defined, check that first */
+#ifdef PLUGIN_DIR
+ if (!tracecmd_disable_sys_plugins)
+ trace_util_load_plugins_dir(pevent, suffix, PLUGIN_DIR,
+ load_plugin, data);
+#endif
+
+ /* Next let the environment-set plugin directory override the system defaults */
+ envdir = getenv("TRACE_CMD_PLUGIN_DIR");
+ if (envdir)
+ trace_util_load_plugins_dir(pevent, suffix, envdir, load_plugin, data);
+
+ /* Now let the home directory override the environment or system defaults */
+ home = getenv("HOME");
+
+ if (!home)
+ return;
+
+ path = malloc_or_die(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2);
+
+ strcpy(path, home);
+ strcat(path, "/");
+ strcat(path, LOCAL_PLUGIN_DIR);
+
+ trace_util_load_plugins_dir(pevent, suffix, path, load_plugin, data);
+
+ free(path);
+}
+
+struct plugin_list *tracecmd_load_plugins(struct pevent *pevent)
+{
+ struct plugin_list *list = NULL;
+
+ trace_util_load_plugins(pevent, ".so", load_plugin, &list);
+
+ return list;
+}
+
+void tracecmd_unload_plugins(struct plugin_list *plugin_list)
+{
+ pevent_plugin_unload_func func;
+ struct plugin_list *list;
+
+ while (plugin_list) {
+ list = plugin_list;
+ plugin_list = list->next;
+ func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
+ if (func)
+ func();
+ dlclose(list->handle);
+ free(list->name);
+ free(list);
+ }
+}
diff --git a/tools/lib/traceevent/tracecmd-plugins.h b/tools/lib/traceevent/tracecmd-plugins.h
new file mode 100644
index 0000000..1a65d50
--- /dev/null
+++ b/tools/lib/traceevent/tracecmd-plugins.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License (not later!)
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#ifndef _TRACECMD__PLUGINS_H
+#define _TRACECMD__PLUGINS_H
+
+#include <stdlib.h>
+#include "event-parse.h"
+
+extern int tracecmd_disable_sys_plugins;
+extern int tracecmd_disable_plugins;
+
+struct plugin_list;
+struct plugin_list *tracecmd_load_plugins(struct pevent *pevent);
+void tracecmd_unload_plugins(struct plugin_list *list);
+
+#endif /* _TRACECMD__PLUGINS_H */
--
1.7.10.1
next prev parent reply other threads:[~2012-06-14 17:35 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-14 17:35 [RFC PATCH 0/2] libtraceevent/perf: Add support for trace-cmd plugins David Ahern
2012-06-14 17:35 ` David Ahern [this message]
2012-06-14 17:35 ` [RFC PATCH 2/2] perf: add " David Ahern
2012-06-18 8:35 ` [RFC PATCH 0/2] libtraceevent/perf: Add " Namhyung Kim
2012-06-18 14:21 ` Steven Rostedt
2012-06-18 14:35 ` David Ahern
2012-06-18 14:38 ` David Ahern
2012-06-19 0:45 ` Namhyung Kim
2012-06-19 1:03 ` Steven Rostedt
2012-06-19 1:11 ` Namhyung Kim
2012-06-19 1:26 ` Steven Rostedt
2012-06-19 1:40 ` Namhyung Kim
2012-06-19 2:16 ` Steven Rostedt
2012-06-19 5:41 ` Namhyung Kim
2012-06-19 11:54 ` Steven Rostedt
2012-06-19 14:39 ` Namhyung Kim
2012-06-19 14:44 ` Steven Rostedt
2012-06-19 1:14 ` David Ahern
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1339695333-64591-2-git-send-email-dsahern@gmail.com \
--to=dsahern@gmail.com \
--cc=acme@ghostprotocols.net \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=namhyung.kim@lge.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=weisbec@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.