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; |
