diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-02-17 21:26:26 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-02-17 21:26:26 -0500 |
commit | ea645651cdc0ab38fddeb9f81b13eccc9a22d98d (patch) | |
tree | 3e5684793fd898451179738fdbddec0b4b3994a0 /trace-cmd.c | |
parent | 3095089b3c0e95adda29ddcde8840e784d2f8ea5 (diff) |
trace-cmd: Implement trace-cmd record function filtering
Now with "trace-cmd record -l func -g func -n func" you can add function
filtering to the trace.
Since -F and -f are taken, -l is used as "limit functions".
-l func ; writes func into set_ftrace_filter
-n func ; writes func into set_ftrace_notrace
-g func ; writes func into set_graph_function
You can specify more than one function on the command line.
trace-cmd record -p function -l sys_write -l sys_read
The above will set set_ftrace_filter to both sys_write and sys_read.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'trace-cmd.c')
-rw-r--r-- | trace-cmd.c | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/trace-cmd.c b/trace-cmd.c index d91e212..2b246df 100644 --- a/trace-cmd.c +++ b/trace-cmd.c | |||
@@ -59,6 +59,15 @@ static int *pids; | |||
59 | 59 | ||
60 | static int filter_task; | 60 | static int filter_task; |
61 | 61 | ||
62 | struct func_list { | ||
63 | struct func_list *next; | ||
64 | const char *func; | ||
65 | }; | ||
66 | |||
67 | static struct func_list *filter_funcs; | ||
68 | static struct func_list *notrace_funcs; | ||
69 | static struct func_list *graph_funcs; | ||
70 | |||
62 | struct event_list { | 71 | struct event_list { |
63 | struct event_list *next; | 72 | struct event_list *next; |
64 | const char *event; | 73 | const char *event; |
@@ -997,6 +1006,48 @@ static int trace_empty(void) | |||
997 | return ret; | 1006 | return ret; |
998 | } | 1007 | } |
999 | 1008 | ||
1009 | static void write_func_file(const char *file, struct func_list **list) | ||
1010 | { | ||
1011 | struct func_list *item; | ||
1012 | char *path; | ||
1013 | int fd; | ||
1014 | |||
1015 | path = get_tracing_file(file); | ||
1016 | |||
1017 | fd = open(path, O_WRONLY | O_TRUNC); | ||
1018 | if (fd < 0) | ||
1019 | goto free; | ||
1020 | |||
1021 | while (*list) { | ||
1022 | item = *list; | ||
1023 | *list = item->next; | ||
1024 | write(fd, item->func, strlen(item->func)); | ||
1025 | write(fd, " ", 1); | ||
1026 | free(item); | ||
1027 | } | ||
1028 | close(fd); | ||
1029 | |||
1030 | free: | ||
1031 | put_tracing_file(path); | ||
1032 | } | ||
1033 | |||
1034 | static void set_funcs(void) | ||
1035 | { | ||
1036 | write_func_file("set_ftrace_filter", &filter_funcs); | ||
1037 | write_func_file("set_ftrace_notrace", ¬race_funcs); | ||
1038 | write_func_file("set_graph_function", &graph_funcs); | ||
1039 | } | ||
1040 | |||
1041 | static void add_func(struct func_list **list, const char *func) | ||
1042 | { | ||
1043 | struct func_list *item; | ||
1044 | |||
1045 | item = malloc_or_die(sizeof(*item)); | ||
1046 | item->func = func; | ||
1047 | item->next = *list; | ||
1048 | *list = item; | ||
1049 | } | ||
1050 | |||
1000 | void usage(char **argv) | 1051 | void usage(char **argv) |
1001 | { | 1052 | { |
1002 | char *arg = argv[0]; | 1053 | char *arg = argv[0]; |
@@ -1009,11 +1060,15 @@ void usage(char **argv) | |||
1009 | printf("\n" | 1060 | printf("\n" |
1010 | "%s version %s\n\n" | 1061 | "%s version %s\n\n" |
1011 | "usage:\n" | 1062 | "usage:\n" |
1012 | " %s record [-v][-e event [-f filter]][-p plugin][-F][-d][-o file][-s usecs][-O option ] [command ...]\n" | 1063 | " %s record [-v][-e event [-f filter]][-p plugin][-F][-d][-o file] \\\n" |
1064 | " [-s usecs][-O option ][-l func][-g func][-n func][command ...]\n" | ||
1013 | " -e run command with event enabled\n" | 1065 | " -e run command with event enabled\n" |
1014 | " -f filter for previous -e event\n" | 1066 | " -f filter for previous -e event\n" |
1015 | " -p run command with plugin enabled\n" | 1067 | " -p run command with plugin enabled\n" |
1016 | " -F filter only on the given process\n" | 1068 | " -F filter only on the given process\n" |
1069 | " -l filter function name\n" | ||
1070 | " -g set graph function\n" | ||
1071 | " -n do not trace function\n" | ||
1017 | " -v will negate all -e after it (disable those events)\n" | 1072 | " -v will negate all -e after it (disable those events)\n" |
1018 | " -d disable function tracer when running\n" | 1073 | " -d disable function tracer when running\n" |
1019 | " -o data output file [default trace.dat]\n" | 1074 | " -o data output file [default trace.dat]\n" |
@@ -1105,7 +1160,7 @@ int main (int argc, char **argv) | |||
1105 | (strcmp(argv[1], "start") == 0) || | 1160 | (strcmp(argv[1], "start") == 0) || |
1106 | ((extract = strcmp(argv[1], "extract") == 0))) { | 1161 | ((extract = strcmp(argv[1], "extract") == 0))) { |
1107 | 1162 | ||
1108 | while ((c = getopt(argc-1, argv+1, "+he:f:Fp:do:O:s:v")) >= 0) { | 1163 | while ((c = getopt(argc-1, argv+1, "+he:f:Fp:do:O:s:vg:l:n:")) >= 0) { |
1109 | switch (c) { | 1164 | switch (c) { |
1110 | case 'h': | 1165 | case 'h': |
1111 | usage(argv); | 1166 | usage(argv); |
@@ -1150,6 +1205,15 @@ int main (int argc, char **argv) | |||
1150 | usage(argv); | 1205 | usage(argv); |
1151 | neg_event = 1; | 1206 | neg_event = 1; |
1152 | break; | 1207 | break; |
1208 | case 'l': | ||
1209 | add_func(&filter_funcs, optarg); | ||
1210 | break; | ||
1211 | case 'n': | ||
1212 | add_func(¬race_funcs, optarg); | ||
1213 | break; | ||
1214 | case 'g': | ||
1215 | add_func(&graph_funcs, optarg); | ||
1216 | break; | ||
1153 | case 'p': | 1217 | case 'p': |
1154 | if (plugin) | 1218 | if (plugin) |
1155 | die("only one plugin allowed"); | 1219 | die("only one plugin allowed"); |
@@ -1254,6 +1318,7 @@ int main (int argc, char **argv) | |||
1254 | if (!extract) { | 1318 | if (!extract) { |
1255 | fset = set_ftrace(!disable); | 1319 | fset = set_ftrace(!disable); |
1256 | disable_all(); | 1320 | disable_all(); |
1321 | set_funcs(); | ||
1257 | 1322 | ||
1258 | if (events) | 1323 | if (events) |
1259 | enable_events(); | 1324 | enable_events(); |