On 9/1/13 4:48 AM, Jiri Olsa wrote:
Backporting plugin support for traceevent lib.

It would be worthwhile to not where the code is ported from -- repository and as of commit id.

David



It's now possible to use following interface
to load plugins for 'struct pevent' object:

struct plugin_list*
traceevent_load_plugins(struct pevent *pevent)
   - loads plusing for 'struct pevent' object and returns
     loaded plugins list

void traceevent_unload_plugins(struct plugin_list *plugin_list);
   - unload plugin list

Adding -ldl dependency for perf which is needed
due to plugins support.

Signed-off-by: Jiri Olsa <jo...@redhat.com>
Cc: Corey Ashford <cjash...@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweis...@gmail.com>
Cc: Ingo Molnar <mi...@elte.hu>
Cc: Namhyung Kim <namhy...@kernel.org>
Cc: Paul Mackerras <pau...@samba.org>
Cc: Peter Zijlstra <a.p.zijls...@chello.nl>
Cc: Arnaldo Carvalho de Melo <a...@redhat.com>
Cc: Steven Rostedt <rost...@goodmis.org>
Cc: David Ahern <dsah...@gmail.com>
---
  tools/lib/traceevent/Makefile       |   2 +-
  tools/lib/traceevent/event-parse.h  |   5 +
  tools/lib/traceevent/event-plugin.c | 202 ++++++++++++++++++++++++++++++++++++
  tools/perf/config/Makefile          |   2 +-
  4 files changed, 209 insertions(+), 2 deletions(-)
  create mode 100644 tools/lib/traceevent/event-plugin.c

diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index ca6cb77..539f3e5 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -180,7 +180,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 event-plugin.o trace-seq.o parse-filter.o 
parse-utils.o
  PEVENT_LIB_OBJS += kbuffer-parse.o

  ALL_OBJS = $(PEVENT_LIB_OBJS)
diff --git a/tools/lib/traceevent/event-parse.h 
b/tools/lib/traceevent/event-parse.h
index c37b202..8273c6e 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -374,6 +374,11 @@ enum pevent_errno {
  };
  #undef _PE

+struct plugin_list;
+
+struct plugin_list *traceevent_load_plugins(struct pevent *pevent);
+void traceevent_unload_plugins(struct plugin_list *plugin_list);
+
  struct cmdline;
  struct cmdline_list;
  struct func_map;
diff --git a/tools/lib/traceevent/event-plugin.c 
b/tools/lib/traceevent/event-plugin.c
new file mode 100644
index 0000000..d272d87
--- /dev/null
+++ b/tools/lib/traceevent/event-plugin.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srost...@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,  see <http://www.gnu.org/licenses>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <string.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "event-parse.h"
+#include "event-utils.h"
+
+#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
+
+struct plugin_list {
+       struct plugin_list      *next;
+       char                    *name;
+       void                    *handle;
+};
+
+static void
+load_plugin(struct pevent *pevent, const char *path,
+           const char *file, void *data)
+{
+       struct plugin_list **plugin_list = data;
+       pevent_plugin_load_func func;
+       struct plugin_list *list;
+       const char *alias;
+       char *plugin;
+       void *handle;
+
+       plugin = malloc_or_die(strlen(path) + strlen(file) + 2);
+
+       strcpy(plugin, path);
+       strcat(plugin, "/");
+       strcat(plugin, file);
+
+       handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL);
+       if (!handle) {
+               warning("could not load plugin '%s'\n%s\n",
+                       plugin, dlerror());
+               goto out_free;
+       }
+
+       alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
+       if (!alias)
+               alias = file;
+
+       func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
+       if (!func) {
+               warning("could not find func '%s' in plugin '%s'\n%s\n",
+                       PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
+               goto out_free;
+       }
+
+       list = malloc_or_die(sizeof(*list));
+       list->next = *plugin_list;
+       list->handle = handle;
+       list->name = plugin;
+       *plugin_list = list;
+
+       pr_stat("registering plugin: %s", plugin);
+       func(pevent);
+       return;
+
+ out_free:
+       free(plugin);
+}
+
+static void
+load_plugins_dir(struct pevent *pevent, const char *suffix,
+                const char *path,
+                void (*load_plugin)(struct pevent *pevent,
+                                    const char *path,
+                                    const char *name,
+                                    void *data),
+                void *data)
+{
+       struct dirent *dent;
+       struct stat st;
+       DIR *dir;
+       int ret;
+
+       ret = stat(path, &st);
+       if (ret < 0)
+               return;
+
+       if (!S_ISDIR(st.st_mode))
+               return;
+
+       dir = opendir(path);
+       if (!dir)
+               return;
+
+       while ((dent = readdir(dir))) {
+               const char *name = dent->d_name;
+
+               if (strcmp(name, ".") == 0 ||
+                   strcmp(name, "..") == 0)
+                       continue;
+
+               /* Only load plugins that end in suffix */
+               if (strcmp(name + (strlen(name) - strlen(suffix)), suffix) != 0)
+                       continue;
+
+               load_plugin(pevent, path, name, data);
+       }
+
+       closedir(dir);
+}
+
+static void
+load_plugins(struct pevent *pevent, const char *suffix,
+            void (*load_plugin)(struct pevent *pevent,
+                                const char *path,
+                                const char *name,
+                                void *data),
+            void *data)
+{
+       char *home;
+       char *path;
+       char *envdir;
+
+       /*
+        * If a system plugin directory was defined,
+        * check that first.
+        */
+#ifdef PLUGIN_DIR
+       load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data);
+#endif
+
+       /*
+        * Next let the environment-set plugin directory
+        * override the system defaults.
+        */
+       envdir = getenv("TRACEEVENT_PLUGIN_DIR");
+       if (envdir)
+               load_plugins_dir(pevent, suffix, envdir, load_plugin, data);
+
+       /*
+        * Now let the home directory override the environment
+        * or system defaults.
+        */
+       home = getenv("HOME");
+       if (!home)
+               return;
+
+       path = malloc_or_die(strlen(home) + strlen(LOCAL_PLUGIN_DIR) + 2);
+
+       strcpy(path, home);
+       strcat(path, "/");
+       strcat(path, LOCAL_PLUGIN_DIR);
+
+       load_plugins_dir(pevent, suffix, path, load_plugin, data);
+
+       free(path);
+}
+
+struct plugin_list*
+traceevent_load_plugins(struct pevent *pevent)
+{
+       struct plugin_list *list = NULL;
+
+       load_plugins(pevent, ".so", load_plugin, &list);
+       return list;
+}
+
+void
+traceevent_unload_plugins(struct plugin_list *plugin_list)
+{
+       pevent_plugin_unload_func func;
+       struct plugin_list *list;
+
+       while (plugin_list) {
+               list = plugin_list;
+               plugin_list = list->next;
+               func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
+               if (func)
+                       func();
+               dlclose(list->handle);
+               free(list->name);
+               free(list);
+       }
+}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 214e17e..f6d720d 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -87,7 +87,7 @@ CFLAGS += -Wall
  CFLAGS += -Wextra
  CFLAGS += -std=gnu99

-EXTLIBS = -lelf -lpthread -lrt -lm
+EXTLIBS = -lelf -lpthread -lrt -lm -ldl

  ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror 
-fstack-protector-all,-fstack-protector-all),y)
    CFLAGS += -fstack-protector-all


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to