aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2014-06-03 18:41:54 -0400
committerSteven Rostedt <rostedt@goodmis.org>2015-03-24 15:21:37 -0400
commite414891c645a21e87ab837d3fc7bf858617868f5 (patch)
treef55867479397437788c8b590d006966a17b4112b
parenta8bdc386a08ea324e09c18a757e4b20ab40b4d6a (diff)
downloadtrace-cmd-e414891c645a21e87ab837d3fc7bf858617868f5.tar.gz
tools lib traceevent: Add options to plugins
The traceevent plugins allows developers to have their events print out information that is more advanced than what can be achieved by the trace event format files. As these plugins are used on the userspace side of the tracing tools, it is only logical that the tools should be able to produce different types of output for the events. The types of events still need to be defined by the plugins thus we need a way to pass information from the tool to the plugin to specify what type of information to be shown. Not only does the information need to be passed by the tool to plugin, but the plugin also requires a way to notify the tool of what options it can provide. This builds the plugin option infrastructure that is taken from trace-cmd that is used to allow plugins to produce different output based on the options specified by the tool. Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Acked-by: Namhyung Kim <namhyung@kernel.org> Link: http://lkml.kernel.org/r/20140603184154.0a4c031c@gandalf.local.home Signed-off-by: Jiri Olsa <jolsa@kernel.org> [ ported to trace-cmd ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--event-parse.h19
-rw-r--r--event-plugin.c196
-rw-r--r--plugin_function.c6
-rw-r--r--trace-cmd.h10
-rw-r--r--trace-ftrace.c6
-rw-r--r--trace-util.c44
6 files changed, 244 insertions, 37 deletions
diff --git a/event-parse.h b/event-parse.h
index 37e93cc5..ce887415 100644
--- a/event-parse.h
+++ b/event-parse.h
@@ -107,8 +107,8 @@ typedef int (*pevent_event_handler_func)(struct trace_seq *s,
typedef int (*pevent_plugin_load_func)(struct pevent *pevent);
typedef int (*pevent_plugin_unload_func)(struct pevent *pevent);
-struct plugin_option {
- struct plugin_option *next;
+struct pevent_plugin_option {
+ struct pevent_plugin_option *next;
void *handle;
char *file;
char *name;
@@ -135,7 +135,7 @@ struct plugin_option {
* PEVENT_PLUGIN_OPTIONS: (optional)
* Plugin options that can be set before loading
*
- * struct plugin_option PEVENT_PLUGIN_OPTIONS[] = {
+ * struct pevent_plugin_option PEVENT_PLUGIN_OPTIONS[] = {
* {
* .name = "option-name",
* .plugin_alias = "overide-file-name", (optional)
@@ -421,8 +421,19 @@ enum pevent_errno {
struct plugin_list;
+#define INVALID_PLUGIN_LIST_OPTION ((char **)((unsigned long)-1))
+
struct plugin_list *traceevent_load_plugins(struct pevent *pevent);
-void traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent);
+void traceevent_unload_plugins(struct plugin_list *plugin_list,
+ struct pevent *pevent);
+char **traceevent_plugin_list_options(void);
+void traceevent_plugin_free_options_list(char **list);
+int traceevent_plugin_add_options(const char *name,
+ struct pevent_plugin_option *options);
+void traceevent_plugin_remove_options(struct pevent_plugin_option *options);
+void traceevent_print_plugins(struct trace_seq *s,
+ const char *prefix, const char *suffix,
+ const struct plugin_list *list);
struct cmdline;
struct cmdline_list;
diff --git a/event-plugin.c b/event-plugin.c
index 0c8bf678..0236bd26 100644
--- a/event-plugin.c
+++ b/event-plugin.c
@@ -18,6 +18,7 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
+#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <stdlib.h>
@@ -30,12 +31,207 @@
#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
+static struct registered_plugin_options {
+ struct registered_plugin_options *next;
+ struct pevent_plugin_option *options;
+} *registered_options;
+
+static struct trace_plugin_options {
+ struct trace_plugin_options *next;
+ char *plugin;
+ char *option;
+ char *value;
+} *trace_plugin_options;
+
struct plugin_list {
struct plugin_list *next;
char *name;
void *handle;
};
+/**
+ * traceevent_plugin_list_options - get list of plugin options
+ *
+ * Returns an array of char strings that list the currently registered
+ * plugin options in the format of <plugin>:<option>. This list can be
+ * used by toggling the option.
+ *
+ * Returns NULL if there's no options registered. On error it returns
+ * INVALID_PLUGIN_LIST_OPTION
+ *
+ * Must be freed with traceevent_plugin_free_options_list().
+ */
+char **traceevent_plugin_list_options(void)
+{
+ struct registered_plugin_options *reg;
+ struct pevent_plugin_option *op;
+ char **list = NULL;
+ char *name;
+ int count = 0;
+
+ for (reg = registered_options; reg; reg = reg->next) {
+ for (op = reg->options; op->name; op++) {
+ char *alias = op->plugin_alias ? op->plugin_alias : op->file;
+ char **temp = list;
+
+ name = malloc(strlen(op->name) + strlen(alias) + 2);
+ if (!name)
+ goto err;
+
+ sprintf(name, "%s:%s", alias, op->name);
+ list = realloc(list, count + 2);
+ if (!list) {
+ list = temp;
+ free(name);
+ goto err;
+ }
+ list[count++] = name;
+ list[count] = NULL;
+ }
+ }
+ return list;
+
+ err:
+ while (--count >= 0)
+ free(list[count]);
+ free(list);
+
+ return INVALID_PLUGIN_LIST_OPTION;
+}
+
+void traceevent_plugin_free_options_list(char **list)
+{
+ int i;
+
+ if (!list)
+ return;
+
+ if (list == INVALID_PLUGIN_LIST_OPTION)
+ return;
+
+ for (i = 0; list[i]; i++)
+ free(list[i]);
+
+ free(list);
+}
+
+static int
+update_option(const char *file, struct pevent_plugin_option *option)
+{
+ struct trace_plugin_options *op;
+ char *plugin;
+
+ if (option->plugin_alias) {
+ plugin = strdup(option->plugin_alias);
+ if (!plugin)
+ return -1;
+ } else {
+ char *p;
+ plugin = strdup(file);
+ if (!plugin)
+ return -1;
+ 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);
+ return 0;
+}
+
+/**
+ * traceevent_plugin_add_options - Add a set of options by a plugin
+ * @name: The name of the plugin adding the options
+ * @options: The set of options being loaded
+ *
+ * Sets the options with the values that have been added by user.
+ */
+int traceevent_plugin_add_options(const char *name,
+ struct pevent_plugin_option *options)
+{
+ struct registered_plugin_options *reg;
+
+ reg = malloc(sizeof(*reg));
+ if (!reg)
+ return -1;
+ reg->next = registered_options;
+ reg->options = options;
+ registered_options = reg;
+
+ while (options->name) {
+ update_option(name, options);
+ options++;
+ }
+ return 0;
+}
+
+/**
+ * traceevent_plugin_remove_options - remove plugin options that were registered
+ * @options: Options to removed that were registered with traceevent_plugin_add_options
+ */
+void traceevent_plugin_remove_options(struct pevent_plugin_option *options)
+{
+ struct registered_plugin_options **last;
+ struct registered_plugin_options *reg;
+
+ for (last = &registered_options; *last; last = &(*last)->next) {
+ if ((*last)->options == options) {
+ reg = *last;
+ *last = reg->next;
+ free(reg);
+ return;
+ }
+ }
+}
+
+/**
+ * traceevent_print_plugins - print out the list of plugins loaded
+ * @s: the trace_seq descripter to write to
+ * @prefix: The prefix string to add before listing the option name
+ * @suffix: The suffix string ot append after the option name
+ * @list: The list of plugins (usually returned by traceevent_load_plugins()
+ *
+ * Writes to the trace_seq @s the list of plugins (files) that is
+ * returned by traceevent_load_plugins(). Use @prefix and @suffix for formating:
+ * @prefix = " ", @suffix = "\n".
+ */
+void traceevent_print_plugins(struct trace_seq *s,
+ const char *prefix, const char *suffix,
+ const struct plugin_list *list)
+{
+ while (list) {
+ trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix);
+ list = list->next;
+ }
+}
+
static void
load_plugin(struct pevent *pevent, const char *path,
const char *file, void *data)
diff --git a/plugin_function.c b/plugin_function.c
index f5e8a08f..02cfd43c 100644
--- a/plugin_function.c
+++ b/plugin_function.c
@@ -32,7 +32,7 @@ static int cpus = -1;
#define STK_BLK 10
-struct plugin_option plugin_options[] =
+struct pevent_plugin_option plugin_options[] =
{
{
.name = "parent",
@@ -52,8 +52,8 @@ struct plugin_option plugin_options[] =
}
};
-static struct plugin_option *ftrace_parent = &plugin_options[0];
-static struct plugin_option *ftrace_indent = &plugin_options[1];
+static struct pevent_plugin_option *ftrace_parent = &plugin_options[0];
+static struct pevent_plugin_option *ftrace_indent = &plugin_options[1];
static void add_child(struct func_stack *stack, const char *child, int pos)
{
diff --git a/trace-cmd.h b/trace-cmd.h
index 62d21cc7..7bce2a56 100644
--- a/trace-cmd.h
+++ b/trace-cmd.h
@@ -264,10 +264,10 @@ void tracecmd_stat_cpu(struct trace_seq *s, int cpu);
long tracecmd_flush_recording(struct tracecmd_recorder *recorder);
/* --- Plugin handling --- */
-extern struct plugin_option trace_ftrace_options[];
+extern struct pevent_plugin_option trace_ftrace_options[];
-void trace_util_add_options(const char *name, struct plugin_option *options);
-void trace_util_remove_options(struct plugin_option *options);
+void trace_util_add_options(const char *name, struct pevent_plugin_option *options);
+void trace_util_remove_options(struct pevent_plugin_option *options);
void trace_util_add_option(const char *name, const char *val);
void trace_util_load_plugins(struct pevent *pevent, const char *suffix,
void (*load_plugin)(struct pevent *pevent,
@@ -275,8 +275,8 @@ void trace_util_load_plugins(struct pevent *pevent, const char *suffix,
const char *name,
void *data),
void *data);
-struct plugin_option *trace_util_read_plugin_options(void);
-void trace_util_free_options(struct plugin_option *options);
+struct pevent_plugin_option *trace_util_read_plugin_options(void);
+void trace_util_free_options(struct pevent_plugin_option *options);
char **trace_util_find_plugin_files(const char *suffix);
void trace_util_free_plugin_files(char **files);
void trace_util_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix,
diff --git a/trace-ftrace.c b/trace-ftrace.c
index 242e499d..bdf11ce4 100644
--- a/trace-ftrace.c
+++ b/trace-ftrace.c
@@ -24,7 +24,7 @@
#include "trace-cmd.h"
-struct plugin_option trace_ftrace_options[] = {
+struct pevent_plugin_option trace_ftrace_options[] = {
{
.name = "tailprint",
.plugin_alias = "fgraph",
@@ -42,8 +42,8 @@ struct plugin_option trace_ftrace_options[] = {
}
};
-static struct plugin_option *fgraph_tail = &trace_ftrace_options[0];
-static struct plugin_option *fgraph_depth = &trace_ftrace_options[1];
+static struct pevent_plugin_option *fgraph_tail = &trace_ftrace_options[0];
+static struct pevent_plugin_option *fgraph_depth = &trace_ftrace_options[1];
static void find_long_size(struct tracecmd_ftrace *finfo)
{
diff --git a/trace-util.c b/trace-util.c
index ae3c5a07..8a81dd0e 100644
--- a/trace-util.c
+++ b/trace-util.c
@@ -42,7 +42,7 @@ int tracecmd_disable_plugins;
static struct registered_plugin_options {
struct registered_plugin_options *next;
- struct plugin_option *options;
+ struct pevent_plugin_option *options;
} *registered_options;
static struct trace_plugin_options {
@@ -79,7 +79,7 @@ struct plugin_list {
char **trace_util_list_plugin_options(void)
{
struct registered_plugin_options *reg;
- struct plugin_option *op;
+ struct pevent_plugin_option *op;
char **list = NULL;
char *name;
int count = 0;
@@ -108,7 +108,7 @@ void trace_util_free_plugin_options_list(char **list)
}
static int process_option(const char *plugin, const char *option, const char *val);
-static void update_option(const char *file, struct plugin_option *option);
+static void update_option(const char *file, struct pevent_plugin_option *option);
/**
* trace_util_add_options - Add a set of options by a plugin
@@ -117,7 +117,7 @@ static void update_option(const char *file, struct plugin_option *option);
*
* Sets the options with the values that have been added by user.
*/
-void trace_util_add_options(const char *name, struct plugin_option *options)
+void trace_util_add_options(const char *name, struct pevent_plugin_option *options)
{
struct registered_plugin_options *reg;
@@ -136,7 +136,7 @@ void trace_util_add_options(const char *name, struct plugin_option *options)
* trace_util_remove_options - remove plugin options that were registered
* @options: Options to removed that were registered with trace_util_add_options
*/
-void trace_util_remove_options(struct plugin_option *options)
+void trace_util_remove_options(struct pevent_plugin_option *options)
{
struct registered_plugin_options **last;
struct registered_plugin_options *reg;
@@ -188,11 +188,11 @@ static void parse_option_name(char **option, char **plugin)
}
}
-static struct plugin_option *
+static struct pevent_plugin_option *
find_registered_option(const char *plugin, const char *option)
{
struct registered_plugin_options *reg;
- struct plugin_option *op;
+ struct pevent_plugin_option *op;
const char *op_plugin;
for (reg = registered_options; reg; reg = reg->next) {
@@ -214,10 +214,10 @@ find_registered_option(const char *plugin, const char *option)
return NULL;
}
-static struct plugin_option *
+static struct pevent_plugin_option *
find_registered_option_parse(const char *name)
{
- struct plugin_option *option;
+ struct pevent_plugin_option *option;
char *option_str;
char *plugin;
@@ -244,7 +244,7 @@ find_registered_option_parse(const char *name)
*/
const char *trace_util_plugin_option_value(const char *name)
{
- struct plugin_option *option;
+ struct pevent_plugin_option *option;
option = find_registered_option_parse(name);
if (!option)
@@ -341,7 +341,7 @@ static void print_op_data(struct trace_seq *s, const char *name,
void trace_util_print_plugin_options(struct trace_seq *s)
{
struct registered_plugin_options *reg;
- struct plugin_option *op;
+ struct pevent_plugin_option *op;
for (reg = registered_options; reg; reg = reg->next) {
if (reg != registered_options)
@@ -478,7 +478,7 @@ static void lower_case(char *str)
*str = tolower(*str);
}
-static int update_option_value(struct plugin_option *op, const char *val)
+static int update_option_value(struct pevent_plugin_option *op, const char *val)
{
char *op_val;
int ret = 1;
@@ -522,7 +522,7 @@ static int update_option_value(struct plugin_option *op, const char *val)
static int process_option(const char *plugin, const char *option, const char *val)
{
- struct plugin_option *op;
+ struct pevent_plugin_option *op;
op = find_registered_option(plugin, option);
if (!op)
@@ -531,7 +531,7 @@ static int process_option(const char *plugin, const char *option, const char *va
return update_option_value(op, val);
}
-static void update_option(const char *file, struct plugin_option *option)
+static void update_option(const char *file, struct pevent_plugin_option *option)
{
struct trace_plugin_options *op;
char *plugin;
@@ -586,7 +586,7 @@ static void load_plugin(struct pevent *pevent, const char *path,
struct plugin_list **plugin_list = data;
pevent_plugin_load_func func;
struct plugin_list *list;
- struct plugin_option *options;
+ struct pevent_plugin_option *options;
const char *alias;
char *plugin;
void *handle;
@@ -1436,14 +1436,14 @@ void trace_util_free_plugin_files(char **files)
}
struct plugin_option_read {
- struct plugin_option *options;
+ struct pevent_plugin_option *options;
};
static void append_option(struct plugin_option_read *options,
- struct plugin_option *option,
+ struct pevent_plugin_option *option,
const char *alias, void *handle)
{
- struct plugin_option *op;
+ struct pevent_plugin_option *op;
while (option->name) {
op = malloc_or_die(sizeof(*op));
@@ -1460,7 +1460,7 @@ static void read_options(struct pevent *pevent, const char *path,
const char *file, void *data)
{
struct plugin_option_read *options = data;
- struct plugin_option *option;
+ struct pevent_plugin_option *option;
const char *alias;
int unload = 0;
char *plugin;
@@ -1498,7 +1498,7 @@ static void read_options(struct pevent *pevent, const char *path,
free(plugin);
}
-struct plugin_option *trace_util_read_plugin_options(void)
+struct pevent_plugin_option *trace_util_read_plugin_options(void)
{
struct plugin_option_read option = {
.options = NULL,
@@ -1511,9 +1511,9 @@ struct plugin_option *trace_util_read_plugin_options(void)
return option.options;
}
-void trace_util_free_options(struct plugin_option *options)
+void trace_util_free_options(struct pevent_plugin_option *options)
{
- struct plugin_option *op;
+ struct pevent_plugin_option *op;
void *last_handle = NULL;
while (options) {