diff options
author | Steven Rostedt <srostedt@redhat.com> | 2011-03-18 15:04:31 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2011-03-18 15:04:31 -0400 |
commit | 3e3c3b167e44d701b338dd83c789752948d9fb87 (patch) | |
tree | 35c667d875863cb9dad0a0f6a6039c4f8b6cf9b5 | |
parent | ce457d3364f1db3b0dbab9b2744d10e6be1d80c2 (diff) |
trace-cmd: Add utility to add options to plugins
Added trace_util_add_option() and trace_util_read_plugin_options();
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | trace-cmd.h | 3 | ||||
-rw-r--r-- | trace-util.c | 183 |
2 files changed, 186 insertions, 0 deletions
diff --git a/trace-cmd.h b/trace-cmd.h index 9063c8c..b8137b5 100644 --- a/trace-cmd.h +++ b/trace-cmd.h | |||
@@ -207,12 +207,15 @@ void tracecmd_stop_recording(struct tracecmd_recorder *recorder); | |||
207 | void tracecmd_stat_cpu(struct trace_seq *s, int cpu); | 207 | void tracecmd_stat_cpu(struct trace_seq *s, int cpu); |
208 | 208 | ||
209 | /* --- Plugin handling --- */ | 209 | /* --- Plugin handling --- */ |
210 | void trace_util_add_option(const char *name, const char *val); | ||
210 | void trace_util_load_plugins(struct pevent *pevent, const char *suffix, | 211 | void trace_util_load_plugins(struct pevent *pevent, const char *suffix, |
211 | void (*load_plugin)(struct pevent *pevent, | 212 | void (*load_plugin)(struct pevent *pevent, |
212 | const char *path, | 213 | const char *path, |
213 | const char *name, | 214 | const char *name, |
214 | void *data), | 215 | void *data), |
215 | void *data); | 216 | void *data); |
217 | struct plugin_option *trace_util_read_plugin_options(void); | ||
218 | void trace_util_free_options(struct plugin_option *options); | ||
216 | 219 | ||
217 | /* --- Hack! --- */ | 220 | /* --- Hack! --- */ |
218 | int tracecmd_blk_hack(struct tracecmd_input *handle); | 221 | int tracecmd_blk_hack(struct tracecmd_input *handle); |
diff --git a/trace-util.c b/trace-util.c index 970e6bc..04cb087 100644 --- a/trace-util.c +++ b/trace-util.c | |||
@@ -40,6 +40,14 @@ | |||
40 | int tracecmd_disable_sys_plugins; | 40 | int tracecmd_disable_sys_plugins; |
41 | int tracecmd_disable_plugins; | 41 | int tracecmd_disable_plugins; |
42 | 42 | ||
43 | |||
44 | static struct trace_plugin_options { | ||
45 | struct trace_plugin_options *next; | ||
46 | char *plugin; | ||
47 | char *option; | ||
48 | char *value; | ||
49 | } *trace_plugin_options; | ||
50 | |||
43 | #define _STR(x) #x | 51 | #define _STR(x) #x |
44 | #define STR(x) _STR(x) | 52 | #define STR(x) _STR(x) |
45 | 53 | ||
@@ -53,6 +61,35 @@ struct plugin_list { | |||
53 | void *handle; | 61 | void *handle; |
54 | }; | 62 | }; |
55 | 63 | ||
64 | void trace_util_add_option(const char *name, const char *val) | ||
65 | { | ||
66 | struct trace_plugin_options *option; | ||
67 | char *p; | ||
68 | |||
69 | option = malloc_or_die(sizeof(*option)); | ||
70 | memset(option, 0, sizeof(*option)); | ||
71 | option->next = trace_plugin_options; | ||
72 | trace_plugin_options = option; | ||
73 | |||
74 | option->option = strdup(name); | ||
75 | if (!option->option) | ||
76 | die("malloc"); | ||
77 | |||
78 | if ((p = strstr(option->option, ":"))) { | ||
79 | option->plugin = option->option; | ||
80 | *p = '\0'; | ||
81 | option->option = strdup(p + 1); | ||
82 | if (!option->option) | ||
83 | die("malloc"); | ||
84 | } | ||
85 | |||
86 | if (val) { | ||
87 | option->value = strdup(val); | ||
88 | if (!option->value) | ||
89 | die("malloc"); | ||
90 | } | ||
91 | } | ||
92 | |||
56 | void parse_cmdlines(struct pevent *pevent, | 93 | void parse_cmdlines(struct pevent *pevent, |
57 | char *file, int size __unused) | 94 | char *file, int size __unused) |
58 | { | 95 | { |
@@ -131,12 +168,63 @@ void parse_ftrace_printk(struct pevent *pevent, | |||
131 | } | 168 | } |
132 | } | 169 | } |
133 | 170 | ||
171 | static void update_option(const char *file, struct plugin_option *option) | ||
172 | { | ||
173 | struct trace_plugin_options *op; | ||
174 | char *plugin; | ||
175 | |||
176 | if (option->plugin_alias) { | ||
177 | plugin = strdup(option->plugin_alias); | ||
178 | if (!plugin) | ||
179 | die("malloc"); | ||
180 | } else { | ||
181 | char *p; | ||
182 | plugin = strdup(file); | ||
183 | if (!plugin) | ||
184 | die("malloc"); | ||
185 | p = strstr(plugin, "."); | ||
186 | if (p) | ||
187 | *p = '\0'; | ||
188 | } | ||
189 | |||
190 | /* first look for named options */ | ||
191 | for (op = trace_plugin_options; op; op = op->next) { | ||
192 | if (!op->plugin) | ||
193 | continue; | ||
194 | if (strcmp(op->plugin, plugin) != 0) | ||
195 | continue; | ||
196 | if (strcmp(op->option, option->name) != 0) | ||
197 | continue; | ||
198 | |||
199 | option->value = op->value; | ||
200 | option->set = 1; | ||
201 | goto out; | ||
202 | } | ||
203 | |||
204 | /* first look for unnamed options */ | ||
205 | for (op = trace_plugin_options; op; op = op->next) { | ||
206 | if (op->plugin) | ||
207 | continue; | ||
208 | if (strcmp(op->option, option->name) != 0) | ||
209 | continue; | ||
210 | |||
211 | option->value = op->value; | ||
212 | option->set = 1; | ||
213 | break; | ||
214 | } | ||
215 | |||
216 | out: | ||
217 | free(plugin); | ||
218 | } | ||
219 | |||
134 | static void load_plugin(struct pevent *pevent, const char *path, | 220 | static void load_plugin(struct pevent *pevent, const char *path, |
135 | const char *file, void *data) | 221 | const char *file, void *data) |
136 | { | 222 | { |
137 | struct plugin_list **plugin_list = data; | 223 | struct plugin_list **plugin_list = data; |
138 | pevent_plugin_load_func func; | 224 | pevent_plugin_load_func func; |
139 | struct plugin_list *list; | 225 | struct plugin_list *list; |
226 | struct plugin_option *options; | ||
227 | const char *alias; | ||
140 | char *plugin; | 228 | char *plugin; |
141 | void *handle; | 229 | void *handle; |
142 | 230 | ||
@@ -153,6 +241,18 @@ static void load_plugin(struct pevent *pevent, const char *path, | |||
153 | goto out_free; | 241 | goto out_free; |
154 | } | 242 | } |
155 | 243 | ||
244 | alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME); | ||
245 | if (!alias) | ||
246 | alias = file; | ||
247 | |||
248 | options = dlsym(handle, PEVENT_PLUGIN_OPTIONS_NAME); | ||
249 | if (options) { | ||
250 | while (options->name) { | ||
251 | update_option(alias, options); | ||
252 | options++; | ||
253 | } | ||
254 | } | ||
255 | |||
156 | func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME); | 256 | func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME); |
157 | if (!func) { | 257 | if (!func) { |
158 | warning("cound not find func '%s' in plugin '%s'\n%s\n", | 258 | warning("cound not find func '%s' in plugin '%s'\n%s\n", |
@@ -805,6 +905,89 @@ void trace_util_load_plugins(struct pevent *pevent, const char *suffix, | |||
805 | free(path); | 905 | free(path); |
806 | } | 906 | } |
807 | 907 | ||
908 | struct plugin_option_read { | ||
909 | struct plugin_option *options; | ||
910 | }; | ||
911 | |||
912 | static void read_options(struct pevent *pevent, const char *path, | ||
913 | const char *file, void *data) | ||
914 | { | ||
915 | struct plugin_option_read *option = data; | ||
916 | struct plugin_option *options; | ||
917 | struct plugin_option *op; | ||
918 | const char *alias; | ||
919 | int unload = 0; | ||
920 | char *plugin; | ||
921 | void *handle; | ||
922 | |||
923 | plugin = malloc_or_die(strlen(path) + strlen(file) + 2); | ||
924 | |||
925 | strcpy(plugin, path); | ||
926 | strcat(plugin, "/"); | ||
927 | strcat(plugin, file); | ||
928 | |||
929 | handle = dlopen(plugin, RTLD_NOW | RTLD_GLOBAL); | ||
930 | if (!handle) { | ||
931 | warning("cound not load plugin '%s'\n%s\n", | ||
932 | plugin, dlerror()); | ||
933 | goto out_free; | ||
934 | } | ||
935 | |||
936 | alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME); | ||
937 | if (!alias) | ||
938 | alias = file; | ||
939 | |||
940 | options = dlsym(handle, PEVENT_PLUGIN_OPTIONS_NAME); | ||
941 | if (!options) { | ||
942 | unload = 1; | ||
943 | goto out_unload; | ||
944 | } | ||
945 | |||
946 | while (options->name) { | ||
947 | op = malloc_or_die(sizeof(*op)); | ||
948 | *op = *options; | ||
949 | op->next = option->options; | ||
950 | option->options = op; | ||
951 | op->file = strdup(alias); | ||
952 | op->handle = handle; | ||
953 | options++; | ||
954 | } | ||
955 | |||
956 | out_unload: | ||
957 | if (unload) | ||
958 | dlclose(handle); | ||
959 | out_free: | ||
960 | free(plugin); | ||
961 | } | ||
962 | |||
963 | struct plugin_option *trace_util_read_plugin_options(void) | ||
964 | { | ||
965 | struct plugin_option_read option = { | ||
966 | .options = NULL, | ||
967 | }; | ||
968 | |||
969 | trace_util_load_plugins(NULL, ".so", read_options, &option); | ||
970 | |||
971 | return option.options; | ||
972 | } | ||
973 | |||
974 | void trace_util_free_options(struct plugin_option *options) | ||
975 | { | ||
976 | struct plugin_option *op; | ||
977 | void *last_handle = NULL; | ||
978 | |||
979 | while (options) { | ||
980 | op = options; | ||
981 | options = op->next; | ||
982 | if (op->handle && op->handle != last_handle) { | ||
983 | last_handle = op->handle; | ||
984 | dlclose(op->handle); | ||
985 | } | ||
986 | free(op->file); | ||
987 | free(op); | ||
988 | } | ||
989 | } | ||
990 | |||
808 | struct plugin_list *tracecmd_load_plugins(struct pevent *pevent) | 991 | struct plugin_list *tracecmd_load_plugins(struct pevent *pevent) |
809 | { | 992 | { |
810 | struct plugin_list *list = NULL; | 993 | struct plugin_list *list = NULL; |