aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-01-17 19:05:10 -0500
committerSteven Rostedt <rostedt@goodmis.org>2011-02-01 21:00:59 -0500
commit749f8c9a993d1feb059cabf35a35b64153bd68ea (patch)
tree4329bf294cd99e16d0e7b95e0b098c389ea42b5d
parente941806a43c2eb46769959e44b3c54f332d4418b (diff)
trace-cmd: Restructure the enable and filtering of events
Use glob to expand the events given on the command line into separate entities on the event_selection list. This will allow easier settings of the filters during execution time. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--trace-cmd.c382
1 files changed, 215 insertions, 167 deletions
diff --git a/trace-cmd.c b/trace-cmd.c
index 9965428..ad3ac91 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -99,6 +99,8 @@ struct event_list {
99 struct event_list *next; 99 struct event_list *next;
100 const char *event; 100 const char *event;
101 char *filter; 101 char *filter;
102 char *filter_file;
103 char *enable_file;
102 int neg; 104 int neg;
103}; 105};
104 106
@@ -521,6 +523,29 @@ static void set_options(void)
521 } 523 }
522} 524}
523 525
526static int use_old_event_method(void)
527{
528 static int old_event_method;
529 static int processed;
530 struct stat st;
531 char *path;
532 int ret;
533
534 if (processed)
535 return old_event_method;
536
537 /* Check if the kernel has the events/enable file */
538 path = tracecmd_get_tracing_file("events/enable");
539 ret = stat(path, &st);
540 tracecmd_put_tracing_file(path);
541 if (ret < 0)
542 old_event_method = 1;
543
544 processed = 1;
545
546 return old_event_method;
547}
548
524static void old_update_events(const char *name, char update) 549static void old_update_events(const char *name, char update)
525{ 550{
526 char *path; 551 char *path;
@@ -554,6 +579,47 @@ static void old_update_events(const char *name, char update)
554 return; 579 return;
555} 580}
556 581
582static void reset_events()
583{
584 glob_t globbuf;
585 char *path;
586 char c;
587 int fd;
588 int i;
589 int ret;
590
591 if (use_old_event_method()) {
592 old_update_events("all", '0');
593 return;
594 }
595
596 c = '0';
597 path = tracecmd_get_tracing_file("events/enable");
598 fd = open(path, O_WRONLY);
599 if (fd < 0)
600 die("opening to '%s'", path);
601 ret = write(fd, &c, 1);
602 close(fd);
603 tracecmd_put_tracing_file(path);
604
605 path = tracecmd_get_tracing_file("events/*/filter");
606 globbuf.gl_offs = 0;
607 ret = glob(path, 0, NULL, &globbuf);
608 tracecmd_put_tracing_file(path);
609 if (ret < 0)
610 return;
611
612 for (i = 0; i < globbuf.gl_pathc; i++) {
613 path = globbuf.gl_pathv[i];
614 fd = open(path, O_WRONLY);
615 if (fd < 0)
616 die("opening to '%s'", path);
617 ret = write(fd, &c, 1);
618 close(fd);
619 }
620 globfree(&globbuf);
621}
622
557static void write_filter(const char *file, const char *filter) 623static void write_filter(const char *file, const char *filter)
558{ 624{
559 char buf[BUFSIZ]; 625 char buf[BUFSIZ];
@@ -578,182 +644,35 @@ static void write_filter(const char *file, const char *filter)
578 } 644 }
579} 645}
580 646
581static int update_glob(const char *name, const char *filter, 647static void
582 int filter_only, char update) 648update_event(struct event_list *event, const char *filter,
649 int filter_only, char update)
583{ 650{
584 glob_t globbuf; 651 const char *name = event->event;
585 FILE *fp; 652 FILE *fp;
586 char *filter_file;
587 char *path; 653 char *path;
588 char *str;
589 int len;
590 int ret; 654 int ret;
591 int i;
592 int count = 0;
593
594 len = strlen(name) + strlen("events//enable") + 1;
595 str = malloc_or_die(len);
596 snprintf(str, len, "events/%s/enable", name);
597 path = tracecmd_get_tracing_file(str);
598 free(str);
599 655
600 globbuf.gl_offs = 0; 656 if (use_old_event_method()) {
601 printf("path = %s\n", path);
602 ret = glob(path, GLOB_ONLYDIR, NULL, &globbuf);
603 tracecmd_put_tracing_file(path);
604 if (ret < 0)
605 return 0;
606
607 for (i = 0; i < globbuf.gl_pathc; i++) {
608 path = globbuf.gl_pathv[i];
609
610 filter_file = strdup(path);
611 if (!filter_file)
612 die("Allocating memory");
613
614 /* s/enable/filter/ */
615 memcpy(filter_file + strlen(filter_file) - 6,
616 "filter", 6);
617 if (filter)
618 write_filter(filter_file, filter);
619 else if (update == '1')
620 write_filter(filter_file, "0");
621 free(filter_file);
622 count++;
623
624 if (filter_only)
625 continue;
626
627 fp = fopen(path, "w");
628 if (!fp)
629 die("writing to '%s'", path);
630 ret = fwrite(&update, 1, 1, fp);
631 fclose(fp);
632 if (ret < 0)
633 die("writing to '%s'", path);
634 }
635 globfree(&globbuf);
636 return count;
637}
638
639static void filter_all_systems(const char *filter)
640{
641 glob_t globbuf;
642 char *path;
643 int ret;
644 int i;
645
646 path = tracecmd_get_tracing_file("events/*/filter");
647
648 globbuf.gl_offs = 0;
649 ret = glob(path, 0, NULL, &globbuf);
650 tracecmd_put_tracing_file(path);
651 if (ret < 0)
652 die("No filters found");
653
654 for (i = 0; i < globbuf.gl_pathc; i++) {
655 path = globbuf.gl_pathv[i];
656
657 write_filter(path, filter);
658 }
659 globfree(&globbuf);
660}
661
662static void update_event(const char *name, const char *filter,
663 int filter_only, char update)
664{
665 struct stat st;
666 FILE *fp;
667 char *path;
668 char *str;
669 char *ptr;
670 int len;
671 int ret;
672 int ret2;
673
674 /* Check if the kernel has the events/enable file */
675 path = tracecmd_get_tracing_file("events/enable");
676 ret = stat(path, &st);
677 if (ret < 0) {
678 if (filter_only)
679 return;
680 tracecmd_put_tracing_file(path);
681 /* old kernel */
682 old_update_events(name, update); 657 old_update_events(name, update);
683 return; 658 return;
684 } 659 }
685 660
686 if (!filter_only) 661 if (filter && event->filter_file)
687 fprintf(stderr, "%s %s\n", 662 write_filter(event->filter_file, filter);
688 update == '1' ? "enable" : "disable", name);
689
690 /* We allow the user to use "all" to enable all events */
691
692 if (strcmp(name, "all") == 0) {
693 if (filter)
694 filter_all_systems(filter);
695 else if (update == '1')
696 filter_all_systems("0");
697
698 if (filter_only) {
699 tracecmd_put_tracing_file(path);
700 return;
701 }
702
703 fp = fopen(path, "w");
704 if (!fp)
705 die("writing to '%s'", path);
706 tracecmd_put_tracing_file(path);
707 ret = fwrite(&update, 1, 1, fp);
708 fclose(fp);
709 if (ret < 0)
710 die("writing to '%s'", path);
711 return;
712 }
713
714 ptr = strchr(name, ':');
715
716 if (ptr) {
717 len = ptr - name;
718 str = strdup(name);
719 if (!str)
720 die("could not allocate memory");
721 str[len] = 0;
722 ptr++;
723 if (!strlen(ptr) || strcmp(ptr, "*") == 0) {
724 ret = update_glob(str, filter, filter_only, update);
725 free(str);
726 tracecmd_put_tracing_file(path);
727 if (!ret)
728 goto fail;
729 return;
730 }
731
732 str[len] = '/';
733 663
734 ret = update_glob(str, filter, filter_only, update); 664 if (filter_only || !event->enable_file)
735 free(str);
736 if (!ret && !ignore_event_not_found)
737 die("No events enabled with %s", name);
738 return; 665 return;
739 }
740
741 /* No ':' so enable all matching systems and events */
742 ret = update_glob(name, filter, filter_only, update);
743
744 len = strlen(name) + strlen("*/") + 1;
745 str = malloc_or_die(len);
746 snprintf(str, len, "*/%s", name);
747 ret2 = update_glob(str, filter, filter_only, update);
748 free(str);
749 666
750 if (!ret && !ret2 && !ignore_event_not_found) 667 path = event->enable_file;
751 goto fail;
752
753 return;
754 fail:
755 die("No events enabled with %s", name);
756 668
669 fp = fopen(path, "w");
670 if (!fp)
671 die("writing to '%s'", path);
672 ret = fwrite(&update, 1, 1, fp);
673 fclose(fp);
674 if (ret < 0)
675 die("writing to '%s'", path);
757} 676}
758 677
759/* 678/*
@@ -855,7 +774,7 @@ static void disable_all(void)
855 disable_tracing(); 774 disable_tracing();
856 775
857 set_plugin("nop"); 776 set_plugin("nop");
858 update_event("all", "0", 0, '0'); 777 reset_events();
859 778
860 /* Force close and reset of ftrace pid file */ 779 /* Force close and reset of ftrace pid file */
861 update_ftrace_pid("", 1); 780 update_ftrace_pid("", 1);
@@ -935,7 +854,7 @@ static void update_pid_event_filters(const char *pid)
935 strcat(event->filter, filter); 854 strcat(event->filter, filter);
936 } else 855 } else
937 event->filter = strdup(filter); 856 event->filter = strdup(filter);
938 update_event(event->event, event->filter, 1, '1'); 857 update_event(event, event->filter, 1, '1');
939 } 858 }
940 } 859 }
941 860
@@ -955,13 +874,138 @@ static void enable_events(void)
955 874
956 for (event = event_selection; event; event = event->next) { 875 for (event = event_selection; event; event = event->next) {
957 if (!event->neg) 876 if (!event->neg)
958 update_event(event->event, event->filter, 0, '1'); 877 update_event(event, event->filter, 0, '1');
959 } 878 }
960 879
961 /* Now disable any events */ 880 /* Now disable any events */
962 for (event = event_selection; event; event = event->next) { 881 for (event = event_selection; event; event = event->next) {
963 if (event->neg) 882 if (event->neg)
964 update_event(event->event, NULL, 0, '0'); 883 update_event(event, NULL, 0, '0');
884 }
885}
886
887static int expand_event_files(const char *file, struct event_list *old_event)
888{
889 struct event_list *save_events = event_selection;
890 struct event_list *event;
891 glob_t globbuf;
892 struct stat st;
893 char *path;
894 char *p;
895 int ret;
896 int i;
897
898 p = malloc_or_die(strlen(file) + strlen("events//filter") + 1);
899 sprintf(p, "events/%s/filter", file);
900
901 path = tracecmd_get_tracing_file(p);
902 printf("%s\n", path);
903
904 globbuf.gl_offs = 0;
905 ret = glob(path, 0, NULL, &globbuf);
906 tracecmd_put_tracing_file(path);
907 free(p);
908
909 if (ret < 0)
910 die("No filters found");
911
912 for (i = 0; i < globbuf.gl_pathc; i++) {
913 path = globbuf.gl_pathv[i];
914
915 event = malloc_or_die(sizeof(*event));
916 *event = *old_event;
917 event->next = event_selection;
918 event_selection = event;
919 if (event->filter || filter_task || filter_pid) {
920 event->filter_file = strdup(path);
921 if (!event->filter_file)
922 die("malloc filter file");
923 }
924 for (p = path + strlen(path) - 1; p > path; p--)
925 if (*p == '/')
926 break;
927 *p = '\0';
928 p = malloc_or_die(strlen(path) + strlen("/enable") + 1);
929 sprintf(p, "%s/enable", path);
930 ret = stat(p, &st);
931 if (ret >= 0)
932 event->enable_file = p;
933 else
934 free(p);
935 }
936 globfree(&globbuf);
937
938 return save_events == event_selection;
939}
940
941static void expand_event(struct event_list *event)
942{
943 const char *name = event->event;
944 char *str;
945 char *ptr;
946 int len;
947 int ret;
948 int ret2;
949
950 /*
951 * We allow the user to use "all" to enable all events.
952 * Expand event_selection to all systems.
953 */
954 if (strcmp(name, "all") == 0) {
955 expand_event_files("*", event);
956 return;
957 }
958
959 ptr = strchr(name, ':');
960
961 if (ptr) {
962 len = ptr - name;
963 str = malloc_or_die(strlen(name) + 1); /* may add '*' */
964 strcpy(str, name);
965 str[len] = '/';
966 ptr++;
967 if (!strlen(ptr)) {
968 str[len + 1] = '*';
969 str[len + 2] = '\0';
970 }
971
972 ret = expand_event_files(str, event);
973 if (!ignore_event_not_found && ret)
974 die("No events enabled with %s", name);
975 free(str);
976 return;
977 }
978
979 /* No ':' so enable all matching systems and events */
980 ret = expand_event_files(name, event);
981
982 len = strlen(name) + strlen("*/") + 1;
983 str = malloc_or_die(len);
984 snprintf(str, len, "*/%s", name);
985 ret2 = expand_event_files(str, event);
986 free(str);
987
988 if (!ignore_event_not_found && ret && ret2)
989 die("No events enabled with %s", name);
990
991 return;
992}
993
994static void expand_event_list(void)
995{
996 struct event_list *compressed_list = event_selection;
997 struct event_list *event;
998
999 if (use_old_event_method())
1000 return;
1001
1002 event_selection = NULL;
1003
1004 while (compressed_list) {
1005 event = compressed_list;
1006 compressed_list = event->next;
1007 expand_event(event);
1008 free(event);
965 } 1009 }
966} 1010}
967 1011
@@ -1465,6 +1509,7 @@ int main (int argc, char **argv)
1465 usage(argv); 1509 usage(argv);
1466 events = 1; 1510 events = 1;
1467 event = malloc_or_die(sizeof(*event)); 1511 event = malloc_or_die(sizeof(*event));
1512 memset(event, 0, sizeof(*event));
1468 event->event = optarg; 1513 event->event = optarg;
1469 event->next = event_selection; 1514 event->next = event_selection;
1470 event->neg = neg_event; 1515 event->neg = neg_event;
@@ -1667,6 +1712,9 @@ int main (int argc, char **argv)
1667 1712
1668 tracing_on_init_val = read_tracing_on(); 1713 tracing_on_init_val = read_tracing_on();
1669 1714
1715 if (event_selection)
1716 expand_event_list();
1717
1670 if (!extract) { 1718 if (!extract) {
1671 fset = set_ftrace(!disable); 1719 fset = set_ftrace(!disable);
1672 disable_all(); 1720 disable_all();