aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-01-29 23:27:34 -0500
committerSteven Rostedt <rostedt@goodmis.org>2010-02-01 22:29:29 -0500
commit65b7fed7c15c602afe6d1e5d17b9ca1665aec9a5 (patch)
treeec89fdd9977bc1f84396dfc269d1b7a260624aa6
parent088b2483d397179b5d5e0b3bbd1c8e15b409f14b (diff)
trace-cmd: Add filtering of events
Add the option "-f filter" to come after an event, to enable a filter. trace-cmd record -e sched_switch -f next_pid==2314 Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--trace-cmd.c109
1 files changed, 100 insertions, 9 deletions
diff --git a/trace-cmd.c b/trace-cmd.c
index a82d8ce..5e394a6 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -60,6 +60,7 @@ static int *pids;
60struct event_list { 60struct event_list {
61 struct event_list *next; 61 struct event_list *next;
62 const char *event; 62 const char *event;
63 char *filter;
63 int neg; 64 int neg;
64}; 65};
65 66
@@ -389,10 +390,35 @@ static void old_enable_events(const char *name)
389 return; 390 return;
390} 391}
391 392
392static int enable_glob(const char *name) 393static void write_filter(const char *file, const char *filter)
394{
395 char buf[BUFSIZ];
396 int fd;
397 int ret;
398
399 fd = open(file, O_WRONLY);
400 if (fd < 0)
401 die("opening to '%s'", file);
402 ret = write(fd, filter, strlen(filter));
403 close(fd);
404 if (ret < 0) {
405 /* filter failed */
406 fd = open(file, O_RDONLY);
407 if (fd < 0)
408 die("writing to '%s'", file);
409 /* the filter has the error */
410 while ((ret = read(fd, buf, BUFSIZ)) > 0)
411 fprintf(stderr, "%.*s", ret, buf);
412 die("Failed filter of %s\n", file);
413 close(fd);
414 }
415}
416
417static int enable_glob(const char *name, const char *filter)
393{ 418{
394 glob_t globbuf; 419 glob_t globbuf;
395 FILE *fp; 420 FILE *fp;
421 char *filter_file;
396 char *path; 422 char *path;
397 char *str; 423 char *str;
398 int len; 424 int len;
@@ -416,6 +442,19 @@ static int enable_glob(const char *name)
416 for (i = 0; i < globbuf.gl_pathc; i++) { 442 for (i = 0; i < globbuf.gl_pathc; i++) {
417 path = globbuf.gl_pathv[i]; 443 path = globbuf.gl_pathv[i];
418 444
445 filter_file = strdup(path);
446 if (!filter_file)
447 die("Allocating memory");
448
449 /* s/enable/filter/ */
450 memcpy(filter_file + strlen(filter_file) - 6,
451 "filter", 6);
452 if (filter)
453 write_filter(filter_file, filter);
454 else
455 write_filter(filter_file, "0");
456 free(filter_file);
457
419 fp = fopen(path, "w"); 458 fp = fopen(path, "w");
420 if (!fp) 459 if (!fp)
421 die("writing to '%s'", path); 460 die("writing to '%s'", path);
@@ -430,7 +469,30 @@ static int enable_glob(const char *name)
430 return count; 469 return count;
431} 470}
432 471
433static void enable_event(const char *name) 472static void filter_all_systems(const char *filter)
473{
474 glob_t globbuf;
475 char *path;
476 int ret;
477 int i;
478
479 path = get_tracing_file("events/*/filter");
480
481 globbuf.gl_offs = 0;
482 ret = glob(path, 0, NULL, &globbuf);
483 put_tracing_file(path);
484 if (ret < 0)
485 die("No filters found");
486
487 for (i = 0; i < globbuf.gl_pathc; i++) {
488 path = globbuf.gl_pathv[i];
489
490 write_filter(path, filter);
491 }
492 globfree(&globbuf);
493}
494
495static void enable_event(const char *name, const char *filter)
434{ 496{
435 struct stat st; 497 struct stat st;
436 FILE *fp; 498 FILE *fp;
@@ -456,6 +518,11 @@ static void enable_event(const char *name)
456 /* We allow the user to use "all" to enable all events */ 518 /* We allow the user to use "all" to enable all events */
457 519
458 if (strcmp(name, "all") == 0) { 520 if (strcmp(name, "all") == 0) {
521 if (filter)
522 filter_all_systems(filter);
523 else
524 filter_all_systems("0");
525
459 fp = fopen(path, "w"); 526 fp = fopen(path, "w");
460 if (!fp) 527 if (!fp)
461 die("writing to '%s'", path); 528 die("writing to '%s'", path);
@@ -477,7 +544,7 @@ static void enable_event(const char *name)
477 str[len] = 0; 544 str[len] = 0;
478 ptr++; 545 ptr++;
479 if (!strlen(ptr) || strcmp(ptr, "*") == 0) { 546 if (!strlen(ptr) || strcmp(ptr, "*") == 0) {
480 ret = enable_glob(str); 547 ret = enable_glob(str, filter);
481 free(str); 548 free(str);
482 put_tracing_file(path); 549 put_tracing_file(path);
483 if (!ret) 550 if (!ret)
@@ -487,7 +554,7 @@ static void enable_event(const char *name)
487 554
488 str[len] = '/'; 555 str[len] = '/';
489 556
490 ret = enable_glob(str); 557 ret = enable_glob(str, filter);
491 free(str); 558 free(str);
492 if (!ret) 559 if (!ret)
493 die("No events enabled with %s", name); 560 die("No events enabled with %s", name);
@@ -495,12 +562,12 @@ static void enable_event(const char *name)
495 } 562 }
496 563
497 /* No ':' so enable all matching systems and events */ 564 /* No ':' so enable all matching systems and events */
498 ret = enable_glob(name); 565 ret = enable_glob(name, filter);
499 566
500 len = strlen(name) + strlen("*/") + 1; 567 len = strlen(name) + strlen("*/") + 1;
501 str = malloc_or_die(len); 568 str = malloc_or_die(len);
502 snprintf(str, len, "*/%s", name); 569 snprintf(str, len, "*/%s", name);
503 ret2 = enable_glob(str); 570 ret2 = enable_glob(str, filter);
504 free(str); 571 free(str);
505 572
506 if (!ret && !ret2) 573 if (!ret && !ret2)
@@ -636,7 +703,7 @@ static void enable_events(void)
636 703
637 for (event = event_selection; event; event = event->next) { 704 for (event = event_selection; event; event = event->next) {
638 if (!event->neg) 705 if (!event->neg)
639 enable_event(event->event); 706 enable_event(event->event, event->filter);
640 } 707 }
641 708
642 /* Now disable any events */ 709 /* Now disable any events */
@@ -822,8 +889,9 @@ void usage(char **argv)
822 printf("\n" 889 printf("\n"
823 "%s version %s\n\n" 890 "%s version %s\n\n"
824 "usage:\n" 891 "usage:\n"
825 " %s record [-v][-e event][-p plugin][-d][-o file][-s usecs][-O option ] [command ...]\n" 892 " %s record [-v][-e event [-f filter]][-p plugin][-d][-o file][-s usecs][-O option ] [command ...]\n"
826 " -e run command with event enabled\n" 893 " -e run command with event enabled\n"
894 " -f filter for previous -e event\n"
827 " -p run command with plugin enabled\n" 895 " -p run command with plugin enabled\n"
828 " -v will negate all -e after it (disable those events)\n" 896 " -v will negate all -e after it (disable those events)\n"
829 " -d disable function tracer when running\n" 897 " -d disable function tracer when running\n"
@@ -883,6 +951,7 @@ int main (int argc, char **argv)
883 const char *output = NULL; 951 const char *output = NULL;
884 const char *option; 952 const char *option;
885 struct event_list *event; 953 struct event_list *event;
954 struct event_list *last_event;
886 struct trace_seq s; 955 struct trace_seq s;
887 int disable = 0; 956 int disable = 0;
888 int plug = 0; 957 int plug = 0;
@@ -912,7 +981,7 @@ int main (int argc, char **argv)
912 (strcmp(argv[1], "start") == 0) || 981 (strcmp(argv[1], "start") == 0) ||
913 ((extract = strcmp(argv[1], "extract") == 0))) { 982 ((extract = strcmp(argv[1], "extract") == 0))) {
914 983
915 while ((c = getopt(argc-1, argv+1, "+he:p:do:O:s:v")) >= 0) { 984 while ((c = getopt(argc-1, argv+1, "+he:f:p:do:O:s:v")) >= 0) {
916 switch (c) { 985 switch (c) {
917 case 'h': 986 case 'h':
918 usage(argv); 987 usage(argv);
@@ -926,7 +995,29 @@ int main (int argc, char **argv)
926 event->next = event_selection; 995 event->next = event_selection;
927 event->neg = neg_event; 996 event->neg = neg_event;
928 event_selection = event; 997 event_selection = event;
998 event->filter = NULL;
999 last_event = event;
929 break; 1000 break;
1001 case 'f':
1002 if (!last_event)
1003 die("filter must come after event");
1004 if (last_event->filter) {
1005 last_event->filter =
1006 realloc(last_event->filter,
1007 strlen(last_event->filter) +
1008 strlen("&&()") +
1009 strlen(optarg) + 1);
1010 strcat(last_event->filter, "&&(");
1011 strcat(last_event->filter, optarg);
1012 strcat(last_event->filter, ")");
1013 } else {
1014 last_event->filter =
1015 malloc_or_die(strlen(optarg) +
1016 strlen("()") + 1);
1017 sprintf(last_event->filter, "(%s)", optarg);
1018 }
1019 break;
1020
930 case 'v': 1021 case 'v':
931 if (extract) 1022 if (extract)
932 usage(argv); 1023 usage(argv);