aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/lib/traceevent/event-parse.h16
-rw-r--r--tools/lib/traceevent/event-plugin.c196
2 files changed, 209 insertions, 3 deletions
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index a68ec3d8289f..56e0e6c12411 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -107,8 +107,8 @@ typedef int (*pevent_event_handler_func)(struct trace_seq *s,
107typedef int (*pevent_plugin_load_func)(struct pevent *pevent); 107typedef int (*pevent_plugin_load_func)(struct pevent *pevent);
108typedef int (*pevent_plugin_unload_func)(struct pevent *pevent); 108typedef int (*pevent_plugin_unload_func)(struct pevent *pevent);
109 109
110struct plugin_option { 110struct pevent_plugin_option {
111 struct plugin_option *next; 111 struct pevent_plugin_option *next;
112 void *handle; 112 void *handle;
113 char *file; 113 char *file;
114 char *name; 114 char *name;
@@ -135,7 +135,7 @@ struct plugin_option {
135 * PEVENT_PLUGIN_OPTIONS: (optional) 135 * PEVENT_PLUGIN_OPTIONS: (optional)
136 * Plugin options that can be set before loading 136 * Plugin options that can be set before loading
137 * 137 *
138 * struct plugin_option PEVENT_PLUGIN_OPTIONS[] = { 138 * struct pevent_plugin_option PEVENT_PLUGIN_OPTIONS[] = {
139 * { 139 * {
140 * .name = "option-name", 140 * .name = "option-name",
141 * .plugin_alias = "overide-file-name", (optional) 141 * .plugin_alias = "overide-file-name", (optional)
@@ -412,9 +412,19 @@ enum pevent_errno {
412 412
413struct plugin_list; 413struct plugin_list;
414 414
415#define INVALID_PLUGIN_LIST_OPTION ((char **)((unsigned long)-1))
416
415struct plugin_list *traceevent_load_plugins(struct pevent *pevent); 417struct plugin_list *traceevent_load_plugins(struct pevent *pevent);
416void traceevent_unload_plugins(struct plugin_list *plugin_list, 418void traceevent_unload_plugins(struct plugin_list *plugin_list,
417 struct pevent *pevent); 419 struct pevent *pevent);
420char **traceevent_plugin_list_options(void);
421void traceevent_plugin_free_options_list(char **list);
422int traceevent_plugin_add_options(const char *name,
423 struct pevent_plugin_option *options);
424void traceevent_plugin_remove_options(struct pevent_plugin_option *options);
425void traceevent_print_plugins(struct trace_seq *s,
426 const char *prefix, const char *suffix,
427 const struct plugin_list *list);
418 428
419struct cmdline; 429struct cmdline;
420struct cmdline_list; 430struct cmdline_list;
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
index 317466bd1a37..136162c03af1 100644
--- a/tools/lib/traceevent/event-plugin.c
+++ b/tools/lib/traceevent/event-plugin.c
@@ -18,6 +18,7 @@
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */ 19 */
20 20
21#include <stdio.h>
21#include <string.h> 22#include <string.h>
22#include <dlfcn.h> 23#include <dlfcn.h>
23#include <stdlib.h> 24#include <stdlib.h>
@@ -30,12 +31,207 @@
30 31
31#define LOCAL_PLUGIN_DIR ".traceevent/plugins" 32#define LOCAL_PLUGIN_DIR ".traceevent/plugins"
32 33
34static struct registered_plugin_options {
35 struct registered_plugin_options *next;
36 struct pevent_plugin_option *options;
37} *registered_options;
38
39static struct trace_plugin_options {
40 struct trace_plugin_options *next;
41 char *plugin;
42 char *option;
43 char *value;
44} *trace_plugin_options;
45
33struct plugin_list { 46struct plugin_list {
34 struct plugin_list *next; 47 struct plugin_list *next;
35 char *name; 48 char *name;
36 void *handle; 49 void *handle;
37}; 50};
38 51
52/**
53 * traceevent_plugin_list_options - get list of plugin options
54 *
55 * Returns an array of char strings that list the currently registered
56 * plugin options in the format of <plugin>:<option>. This list can be
57 * used by toggling the option.
58 *
59 * Returns NULL if there's no options registered. On error it returns
60 * INVALID_PLUGIN_LIST_OPTION
61 *
62 * Must be freed with traceevent_plugin_free_options_list().
63 */
64char **traceevent_plugin_list_options(void)
65{
66 struct registered_plugin_options *reg;
67 struct pevent_plugin_option *op;
68 char **list = NULL;
69 char *name;
70 int count = 0;
71
72 for (reg = registered_options; reg; reg = reg->next) {
73 for (op = reg->options; op->name; op++) {
74 char *alias = op->plugin_alias ? op->plugin_alias : op->file;
75 char **temp = list;
76
77 name = malloc(strlen(op->name) + strlen(alias) + 2);
78 if (!name)
79 goto err;
80
81 sprintf(name, "%s:%s", alias, op->name);
82 list = realloc(list, count + 2);
83 if (!list) {
84 list = temp;
85 free(name);
86 goto err;
87 }
88 list[count++] = name;
89 list[count] = NULL;
90 }
91 }
92 return list;
93
94 err:
95 while (--count >= 0)
96 free(list[count]);
97 free(list);
98
99 return INVALID_PLUGIN_LIST_OPTION;
100}
101
102void traceevent_plugin_free_options_list(char **list)
103{
104 int i;
105
106 if (!list)
107 return;
108
109 if (list == INVALID_PLUGIN_LIST_OPTION)
110 return;
111
112 for (i = 0; list[i]; i++)
113 free(list[i]);
114
115 free(list);
116}
117
118static int
119update_option(const char *file, struct pevent_plugin_option *option)
120{
121 struct trace_plugin_options *op;
122 char *plugin;
123
124 if (option->plugin_alias) {
125 plugin = strdup(option->plugin_alias);
126 if (!plugin)
127 return -1;
128 } else {
129 char *p;
130 plugin = strdup(file);
131 if (!plugin)
132 return -1;
133 p = strstr(plugin, ".");
134 if (p)
135 *p = '\0';
136 }
137
138 /* first look for named options */
139 for (op = trace_plugin_options; op; op = op->next) {
140 if (!op->plugin)
141 continue;
142 if (strcmp(op->plugin, plugin) != 0)
143 continue;
144 if (strcmp(op->option, option->name) != 0)
145 continue;
146
147 option->value = op->value;
148 option->set ^= 1;
149 goto out;
150 }
151
152 /* first look for unnamed options */
153 for (op = trace_plugin_options; op; op = op->next) {
154 if (op->plugin)
155 continue;
156 if (strcmp(op->option, option->name) != 0)
157 continue;
158
159 option->value = op->value;
160 option->set ^= 1;
161 break;
162 }
163
164 out:
165 free(plugin);
166 return 0;
167}
168
169/**
170 * traceevent_plugin_add_options - Add a set of options by a plugin
171 * @name: The name of the plugin adding the options
172 * @options: The set of options being loaded
173 *
174 * Sets the options with the values that have been added by user.
175 */
176int traceevent_plugin_add_options(const char *name,
177 struct pevent_plugin_option *options)
178{
179 struct registered_plugin_options *reg;
180
181 reg = malloc(sizeof(*reg));
182 if (!reg)
183 return -1;
184 reg->next = registered_options;
185 reg->options = options;
186 registered_options = reg;
187
188 while (options->name) {
189 update_option(name, options);
190 options++;
191 }
192 return 0;
193}
194
195/**
196 * traceevent_plugin_remove_options - remove plugin options that were registered
197 * @options: Options to removed that were registered with traceevent_plugin_add_options
198 */
199void traceevent_plugin_remove_options(struct pevent_plugin_option *options)
200{
201 struct registered_plugin_options **last;
202 struct registered_plugin_options *reg;
203
204 for (last = &registered_options; *last; last = &(*last)->next) {
205 if ((*last)->options == options) {
206 reg = *last;
207 *last = reg->next;
208 free(reg);
209 return;
210 }
211 }
212}
213
214/**
215 * traceevent_print_plugins - print out the list of plugins loaded
216 * @s: the trace_seq descripter to write to
217 * @prefix: The prefix string to add before listing the option name
218 * @suffix: The suffix string ot append after the option name
219 * @list: The list of plugins (usually returned by traceevent_load_plugins()
220 *
221 * Writes to the trace_seq @s the list of plugins (files) that is
222 * returned by traceevent_load_plugins(). Use @prefix and @suffix for formating:
223 * @prefix = " ", @suffix = "\n".
224 */
225void traceevent_print_plugins(struct trace_seq *s,
226 const char *prefix, const char *suffix,
227 const struct plugin_list *list)
228{
229 while (list) {
230 trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix);
231 list = list->next;
232 }
233}
234
39static void 235static void
40load_plugin(struct pevent *pevent, const char *path, 236load_plugin(struct pevent *pevent, const char *path,
41 const char *file, void *data) 237 const char *file, void *data)