diff options
author | Steven Rostedt <rostedt@goodmis.org> | 2008-05-22 11:46:33 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-26 16:51:37 -0400 |
commit | 41c52c0db9607e59f90da7da5309489fa06e887f (patch) | |
tree | b0b1f282c087c53dfd4081da5a8a35cdc5ea5ebb | |
parent | da89a7a2536c46e76a1a4351a70a8b8417e5fed1 (diff) |
ftrace: set_ftrace_notrace feature
While debugging latencies in the RT kernel, I found that it would be nice
to be able to filter away functions from the trace than just to filter
on functions.
I added a new interface to the debugfs tracing directory called
set_ftrace_notrace
When dynamic frace is enabled, this lets you filter away functions that will
not be recorded in the trace. It is similar to adding 'notrace' to those
functions but by doing it without recompiling the kernel.
Here's how set_ftrace_filter and set_ftrace_notrace interact. Remember, if
set_ftrace_filter is set, it removes all functions from the trace execpt for
those listed in the set_ftrace_filter. set_ftrace_notrace will prevent those
functions from being traced.
If you were to set one function in both set_ftrace_filter and
set_ftrace_notrace and that function was the same, then you would end up
with an empty trace.
the set of functions to trace is:
set_ftrace_filter == empty then
all functions not in set_ftrace_notrace
else
set of the set_ftrace_filter and not in set of set_ftrace_notrace.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | include/linux/ftrace.h | 1 | ||||
-rw-r--r-- | kernel/trace/ftrace.c | 170 |
2 files changed, 131 insertions, 40 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 922e23d0196f..ffbbd54a720e 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
@@ -48,6 +48,7 @@ enum { | |||
48 | FTRACE_FL_FAILED = (1 << 1), | 48 | FTRACE_FL_FAILED = (1 << 1), |
49 | FTRACE_FL_FILTER = (1 << 2), | 49 | FTRACE_FL_FILTER = (1 << 2), |
50 | FTRACE_FL_ENABLED = (1 << 3), | 50 | FTRACE_FL_ENABLED = (1 << 3), |
51 | FTRACE_FL_NOTRACE = (1 << 4), | ||
51 | }; | 52 | }; |
52 | 53 | ||
53 | struct dyn_ftrace { | 54 | struct dyn_ftrace { |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 89bd9a6f52ec..2552454609cf 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -170,7 +170,7 @@ static DEFINE_PER_CPU(int, ftrace_shutdown_disable_cpu); | |||
170 | 170 | ||
171 | static DEFINE_SPINLOCK(ftrace_shutdown_lock); | 171 | static DEFINE_SPINLOCK(ftrace_shutdown_lock); |
172 | static DEFINE_MUTEX(ftraced_lock); | 172 | static DEFINE_MUTEX(ftraced_lock); |
173 | static DEFINE_MUTEX(ftrace_filter_lock); | 173 | static DEFINE_MUTEX(ftrace_regex_lock); |
174 | 174 | ||
175 | struct ftrace_page { | 175 | struct ftrace_page { |
176 | struct ftrace_page *next; | 176 | struct ftrace_page *next; |
@@ -337,13 +337,12 @@ static void | |||
337 | __ftrace_replace_code(struct dyn_ftrace *rec, | 337 | __ftrace_replace_code(struct dyn_ftrace *rec, |
338 | unsigned char *old, unsigned char *new, int enable) | 338 | unsigned char *old, unsigned char *new, int enable) |
339 | { | 339 | { |
340 | unsigned long ip; | 340 | unsigned long ip, fl; |
341 | int failed; | 341 | int failed; |
342 | 342 | ||
343 | ip = rec->ip; | 343 | ip = rec->ip; |
344 | 344 | ||
345 | if (ftrace_filtered && enable) { | 345 | if (ftrace_filtered && enable) { |
346 | unsigned long fl; | ||
347 | /* | 346 | /* |
348 | * If filtering is on: | 347 | * If filtering is on: |
349 | * | 348 | * |
@@ -356,13 +355,16 @@ __ftrace_replace_code(struct dyn_ftrace *rec, | |||
356 | * If this record is not set to be filtered | 355 | * If this record is not set to be filtered |
357 | * and it is not enabled do nothing. | 356 | * and it is not enabled do nothing. |
358 | * | 357 | * |
358 | * If this record is set not to trace then | ||
359 | * do nothing. | ||
360 | * | ||
359 | * If this record is not set to be filtered and | 361 | * If this record is not set to be filtered and |
360 | * it is enabled, disable it. | 362 | * it is enabled, disable it. |
361 | */ | 363 | */ |
362 | fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED); | 364 | fl = rec->flags & (FTRACE_FL_FILTER | FTRACE_FL_ENABLED); |
363 | 365 | ||
364 | if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) || | 366 | if ((fl == (FTRACE_FL_FILTER | FTRACE_FL_ENABLED)) || |
365 | (fl == 0)) | 367 | (fl == 0) || (rec->flags & FTRACE_FL_NOTRACE)) |
366 | return; | 368 | return; |
367 | 369 | ||
368 | /* | 370 | /* |
@@ -380,9 +382,17 @@ __ftrace_replace_code(struct dyn_ftrace *rec, | |||
380 | } | 382 | } |
381 | } else { | 383 | } else { |
382 | 384 | ||
383 | if (enable) | 385 | if (enable) { |
386 | /* | ||
387 | * If this record is set not to trace and is | ||
388 | * not enabled, do nothing. | ||
389 | */ | ||
390 | fl = rec->flags & (FTRACE_FL_NOTRACE | FTRACE_FL_ENABLED); | ||
391 | if (fl == FTRACE_FL_NOTRACE) | ||
392 | return; | ||
393 | |||
384 | new = ftrace_call_replace(ip, FTRACE_ADDR); | 394 | new = ftrace_call_replace(ip, FTRACE_ADDR); |
385 | else | 395 | } else |
386 | old = ftrace_call_replace(ip, FTRACE_ADDR); | 396 | old = ftrace_call_replace(ip, FTRACE_ADDR); |
387 | 397 | ||
388 | if (enable) { | 398 | if (enable) { |
@@ -721,6 +731,7 @@ static int __init ftrace_dyn_table_alloc(void) | |||
721 | enum { | 731 | enum { |
722 | FTRACE_ITER_FILTER = (1 << 0), | 732 | FTRACE_ITER_FILTER = (1 << 0), |
723 | FTRACE_ITER_CONT = (1 << 1), | 733 | FTRACE_ITER_CONT = (1 << 1), |
734 | FTRACE_ITER_NOTRACE = (1 << 2), | ||
724 | }; | 735 | }; |
725 | 736 | ||
726 | #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ | 737 | #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ |
@@ -754,7 +765,9 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
754 | rec = &iter->pg->records[iter->idx++]; | 765 | rec = &iter->pg->records[iter->idx++]; |
755 | if ((rec->flags & FTRACE_FL_FAILED) || | 766 | if ((rec->flags & FTRACE_FL_FAILED) || |
756 | ((iter->flags & FTRACE_ITER_FILTER) && | 767 | ((iter->flags & FTRACE_ITER_FILTER) && |
757 | !(rec->flags & FTRACE_FL_FILTER))) { | 768 | !(rec->flags & FTRACE_FL_FILTER)) || |
769 | ((iter->flags & FTRACE_ITER_NOTRACE) && | ||
770 | !(rec->flags & FTRACE_FL_NOTRACE))) { | ||
758 | rec = NULL; | 771 | rec = NULL; |
759 | goto retry; | 772 | goto retry; |
760 | } | 773 | } |
@@ -847,22 +860,24 @@ int ftrace_avail_release(struct inode *inode, struct file *file) | |||
847 | return 0; | 860 | return 0; |
848 | } | 861 | } |
849 | 862 | ||
850 | static void ftrace_filter_reset(void) | 863 | static void ftrace_filter_reset(int enable) |
851 | { | 864 | { |
852 | struct ftrace_page *pg; | 865 | struct ftrace_page *pg; |
853 | struct dyn_ftrace *rec; | 866 | struct dyn_ftrace *rec; |
867 | unsigned long type = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; | ||
854 | unsigned i; | 868 | unsigned i; |
855 | 869 | ||
856 | /* keep kstop machine from running */ | 870 | /* keep kstop machine from running */ |
857 | preempt_disable(); | 871 | preempt_disable(); |
858 | ftrace_filtered = 0; | 872 | if (enable) |
873 | ftrace_filtered = 0; | ||
859 | pg = ftrace_pages_start; | 874 | pg = ftrace_pages_start; |
860 | while (pg) { | 875 | while (pg) { |
861 | for (i = 0; i < pg->index; i++) { | 876 | for (i = 0; i < pg->index; i++) { |
862 | rec = &pg->records[i]; | 877 | rec = &pg->records[i]; |
863 | if (rec->flags & FTRACE_FL_FAILED) | 878 | if (rec->flags & FTRACE_FL_FAILED) |
864 | continue; | 879 | continue; |
865 | rec->flags &= ~FTRACE_FL_FILTER; | 880 | rec->flags &= ~type; |
866 | } | 881 | } |
867 | pg = pg->next; | 882 | pg = pg->next; |
868 | } | 883 | } |
@@ -870,7 +885,7 @@ static void ftrace_filter_reset(void) | |||
870 | } | 885 | } |
871 | 886 | ||
872 | static int | 887 | static int |
873 | ftrace_filter_open(struct inode *inode, struct file *file) | 888 | ftrace_regex_open(struct inode *inode, struct file *file, int enable) |
874 | { | 889 | { |
875 | struct ftrace_iterator *iter; | 890 | struct ftrace_iterator *iter; |
876 | int ret = 0; | 891 | int ret = 0; |
@@ -882,15 +897,16 @@ ftrace_filter_open(struct inode *inode, struct file *file) | |||
882 | if (!iter) | 897 | if (!iter) |
883 | return -ENOMEM; | 898 | return -ENOMEM; |
884 | 899 | ||
885 | mutex_lock(&ftrace_filter_lock); | 900 | mutex_lock(&ftrace_regex_lock); |
886 | if ((file->f_mode & FMODE_WRITE) && | 901 | if ((file->f_mode & FMODE_WRITE) && |
887 | !(file->f_flags & O_APPEND)) | 902 | !(file->f_flags & O_APPEND)) |
888 | ftrace_filter_reset(); | 903 | ftrace_filter_reset(enable); |
889 | 904 | ||
890 | if (file->f_mode & FMODE_READ) { | 905 | if (file->f_mode & FMODE_READ) { |
891 | iter->pg = ftrace_pages_start; | 906 | iter->pg = ftrace_pages_start; |
892 | iter->pos = -1; | 907 | iter->pos = -1; |
893 | iter->flags = FTRACE_ITER_FILTER; | 908 | iter->flags = enable ? FTRACE_ITER_FILTER : |
909 | FTRACE_ITER_NOTRACE; | ||
894 | 910 | ||
895 | ret = seq_open(file, &show_ftrace_seq_ops); | 911 | ret = seq_open(file, &show_ftrace_seq_ops); |
896 | if (!ret) { | 912 | if (!ret) { |
@@ -900,13 +916,25 @@ ftrace_filter_open(struct inode *inode, struct file *file) | |||
900 | kfree(iter); | 916 | kfree(iter); |
901 | } else | 917 | } else |
902 | file->private_data = iter; | 918 | file->private_data = iter; |
903 | mutex_unlock(&ftrace_filter_lock); | 919 | mutex_unlock(&ftrace_regex_lock); |
904 | 920 | ||
905 | return ret; | 921 | return ret; |
906 | } | 922 | } |
907 | 923 | ||
924 | static int | ||
925 | ftrace_filter_open(struct inode *inode, struct file *file) | ||
926 | { | ||
927 | return ftrace_regex_open(inode, file, 1); | ||
928 | } | ||
929 | |||
930 | static int | ||
931 | ftrace_notrace_open(struct inode *inode, struct file *file) | ||
932 | { | ||
933 | return ftrace_regex_open(inode, file, 0); | ||
934 | } | ||
935 | |||
908 | static ssize_t | 936 | static ssize_t |
909 | ftrace_filter_read(struct file *file, char __user *ubuf, | 937 | ftrace_regex_read(struct file *file, char __user *ubuf, |
910 | size_t cnt, loff_t *ppos) | 938 | size_t cnt, loff_t *ppos) |
911 | { | 939 | { |
912 | if (file->f_mode & FMODE_READ) | 940 | if (file->f_mode & FMODE_READ) |
@@ -916,7 +944,7 @@ ftrace_filter_read(struct file *file, char __user *ubuf, | |||
916 | } | 944 | } |
917 | 945 | ||
918 | static loff_t | 946 | static loff_t |
919 | ftrace_filter_lseek(struct file *file, loff_t offset, int origin) | 947 | ftrace_regex_lseek(struct file *file, loff_t offset, int origin) |
920 | { | 948 | { |
921 | loff_t ret; | 949 | loff_t ret; |
922 | 950 | ||
@@ -936,13 +964,14 @@ enum { | |||
936 | }; | 964 | }; |
937 | 965 | ||
938 | static void | 966 | static void |
939 | ftrace_match(unsigned char *buff, int len) | 967 | ftrace_match(unsigned char *buff, int len, int enable) |
940 | { | 968 | { |
941 | char str[KSYM_SYMBOL_LEN]; | 969 | char str[KSYM_SYMBOL_LEN]; |
942 | char *search = NULL; | 970 | char *search = NULL; |
943 | struct ftrace_page *pg; | 971 | struct ftrace_page *pg; |
944 | struct dyn_ftrace *rec; | 972 | struct dyn_ftrace *rec; |
945 | int type = MATCH_FULL; | 973 | int type = MATCH_FULL; |
974 | unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; | ||
946 | unsigned i, match = 0, search_len = 0; | 975 | unsigned i, match = 0, search_len = 0; |
947 | 976 | ||
948 | for (i = 0; i < len; i++) { | 977 | for (i = 0; i < len; i++) { |
@@ -966,7 +995,8 @@ ftrace_match(unsigned char *buff, int len) | |||
966 | 995 | ||
967 | /* keep kstop machine from running */ | 996 | /* keep kstop machine from running */ |
968 | preempt_disable(); | 997 | preempt_disable(); |
969 | ftrace_filtered = 1; | 998 | if (enable) |
999 | ftrace_filtered = 1; | ||
970 | pg = ftrace_pages_start; | 1000 | pg = ftrace_pages_start; |
971 | while (pg) { | 1001 | while (pg) { |
972 | for (i = 0; i < pg->index; i++) { | 1002 | for (i = 0; i < pg->index; i++) { |
@@ -997,7 +1027,7 @@ ftrace_match(unsigned char *buff, int len) | |||
997 | break; | 1027 | break; |
998 | } | 1028 | } |
999 | if (matched) | 1029 | if (matched) |
1000 | rec->flags |= FTRACE_FL_FILTER; | 1030 | rec->flags |= flag; |
1001 | } | 1031 | } |
1002 | pg = pg->next; | 1032 | pg = pg->next; |
1003 | } | 1033 | } |
@@ -1005,8 +1035,8 @@ ftrace_match(unsigned char *buff, int len) | |||
1005 | } | 1035 | } |
1006 | 1036 | ||
1007 | static ssize_t | 1037 | static ssize_t |
1008 | ftrace_filter_write(struct file *file, const char __user *ubuf, | 1038 | ftrace_regex_write(struct file *file, const char __user *ubuf, |
1009 | size_t cnt, loff_t *ppos) | 1039 | size_t cnt, loff_t *ppos, int enable) |
1010 | { | 1040 | { |
1011 | struct ftrace_iterator *iter; | 1041 | struct ftrace_iterator *iter; |
1012 | char ch; | 1042 | char ch; |
@@ -1016,7 +1046,7 @@ ftrace_filter_write(struct file *file, const char __user *ubuf, | |||
1016 | if (!cnt || cnt < 0) | 1046 | if (!cnt || cnt < 0) |
1017 | return 0; | 1047 | return 0; |
1018 | 1048 | ||
1019 | mutex_lock(&ftrace_filter_lock); | 1049 | mutex_lock(&ftrace_regex_lock); |
1020 | 1050 | ||
1021 | if (file->f_mode & FMODE_READ) { | 1051 | if (file->f_mode & FMODE_READ) { |
1022 | struct seq_file *m = file->private_data; | 1052 | struct seq_file *m = file->private_data; |
@@ -1045,7 +1075,6 @@ ftrace_filter_write(struct file *file, const char __user *ubuf, | |||
1045 | cnt--; | 1075 | cnt--; |
1046 | } | 1076 | } |
1047 | 1077 | ||
1048 | |||
1049 | if (isspace(ch)) { | 1078 | if (isspace(ch)) { |
1050 | file->f_pos += read; | 1079 | file->f_pos += read; |
1051 | ret = read; | 1080 | ret = read; |
@@ -1072,7 +1101,7 @@ ftrace_filter_write(struct file *file, const char __user *ubuf, | |||
1072 | if (isspace(ch)) { | 1101 | if (isspace(ch)) { |
1073 | iter->filtered++; | 1102 | iter->filtered++; |
1074 | iter->buffer[iter->buffer_idx] = 0; | 1103 | iter->buffer[iter->buffer_idx] = 0; |
1075 | ftrace_match(iter->buffer, iter->buffer_idx); | 1104 | ftrace_match(iter->buffer, iter->buffer_idx, enable); |
1076 | iter->buffer_idx = 0; | 1105 | iter->buffer_idx = 0; |
1077 | } else | 1106 | } else |
1078 | iter->flags |= FTRACE_ITER_CONT; | 1107 | iter->flags |= FTRACE_ITER_CONT; |
@@ -1082,11 +1111,39 @@ ftrace_filter_write(struct file *file, const char __user *ubuf, | |||
1082 | 1111 | ||
1083 | ret = read; | 1112 | ret = read; |
1084 | out: | 1113 | out: |
1085 | mutex_unlock(&ftrace_filter_lock); | 1114 | mutex_unlock(&ftrace_regex_lock); |
1086 | 1115 | ||
1087 | return ret; | 1116 | return ret; |
1088 | } | 1117 | } |
1089 | 1118 | ||
1119 | static ssize_t | ||
1120 | ftrace_filter_write(struct file *file, const char __user *ubuf, | ||
1121 | size_t cnt, loff_t *ppos) | ||
1122 | { | ||
1123 | return ftrace_regex_write(file, ubuf, cnt, ppos, 1); | ||
1124 | } | ||
1125 | |||
1126 | static ssize_t | ||
1127 | ftrace_notrace_write(struct file *file, const char __user *ubuf, | ||
1128 | size_t cnt, loff_t *ppos) | ||
1129 | { | ||
1130 | return ftrace_regex_write(file, ubuf, cnt, ppos, 0); | ||
1131 | } | ||
1132 | |||
1133 | static void | ||
1134 | ftrace_set_regex(unsigned char *buf, int len, int reset, int enable) | ||
1135 | { | ||
1136 | if (unlikely(ftrace_disabled)) | ||
1137 | return; | ||
1138 | |||
1139 | mutex_lock(&ftrace_regex_lock); | ||
1140 | if (reset) | ||
1141 | ftrace_filter_reset(enable); | ||
1142 | if (buf) | ||
1143 | ftrace_match(buf, len, enable); | ||
1144 | mutex_unlock(&ftrace_regex_lock); | ||
1145 | } | ||
1146 | |||
1090 | /** | 1147 | /** |
1091 | * ftrace_set_filter - set a function to filter on in ftrace | 1148 | * ftrace_set_filter - set a function to filter on in ftrace |
1092 | * @buf - the string that holds the function filter text. | 1149 | * @buf - the string that holds the function filter text. |
@@ -1098,24 +1155,31 @@ ftrace_filter_write(struct file *file, const char __user *ubuf, | |||
1098 | */ | 1155 | */ |
1099 | void ftrace_set_filter(unsigned char *buf, int len, int reset) | 1156 | void ftrace_set_filter(unsigned char *buf, int len, int reset) |
1100 | { | 1157 | { |
1101 | if (unlikely(ftrace_disabled)) | 1158 | ftrace_set_regex(buf, len, reset, 1); |
1102 | return; | 1159 | } |
1103 | 1160 | ||
1104 | mutex_lock(&ftrace_filter_lock); | 1161 | /** |
1105 | if (reset) | 1162 | * ftrace_set_notrace - set a function to not trace in ftrace |
1106 | ftrace_filter_reset(); | 1163 | * @buf - the string that holds the function notrace text. |
1107 | if (buf) | 1164 | * @len - the length of the string. |
1108 | ftrace_match(buf, len); | 1165 | * @reset - non zero to reset all filters before applying this filter. |
1109 | mutex_unlock(&ftrace_filter_lock); | 1166 | * |
1167 | * Notrace Filters denote which functions should not be enabled when tracing | ||
1168 | * is enabled. If @buf is NULL and reset is set, all functions will be enabled | ||
1169 | * for tracing. | ||
1170 | */ | ||
1171 | void ftrace_set_notrace(unsigned char *buf, int len, int reset) | ||
1172 | { | ||
1173 | ftrace_set_regex(buf, len, reset, 0); | ||
1110 | } | 1174 | } |
1111 | 1175 | ||
1112 | static int | 1176 | static int |
1113 | ftrace_filter_release(struct inode *inode, struct file *file) | 1177 | ftrace_regex_release(struct inode *inode, struct file *file, int enable) |
1114 | { | 1178 | { |
1115 | struct seq_file *m = (struct seq_file *)file->private_data; | 1179 | struct seq_file *m = (struct seq_file *)file->private_data; |
1116 | struct ftrace_iterator *iter; | 1180 | struct ftrace_iterator *iter; |
1117 | 1181 | ||
1118 | mutex_lock(&ftrace_filter_lock); | 1182 | mutex_lock(&ftrace_regex_lock); |
1119 | if (file->f_mode & FMODE_READ) { | 1183 | if (file->f_mode & FMODE_READ) { |
1120 | iter = m->private; | 1184 | iter = m->private; |
1121 | 1185 | ||
@@ -1126,7 +1190,7 @@ ftrace_filter_release(struct inode *inode, struct file *file) | |||
1126 | if (iter->buffer_idx) { | 1190 | if (iter->buffer_idx) { |
1127 | iter->filtered++; | 1191 | iter->filtered++; |
1128 | iter->buffer[iter->buffer_idx] = 0; | 1192 | iter->buffer[iter->buffer_idx] = 0; |
1129 | ftrace_match(iter->buffer, iter->buffer_idx); | 1193 | ftrace_match(iter->buffer, iter->buffer_idx, enable); |
1130 | } | 1194 | } |
1131 | 1195 | ||
1132 | mutex_lock(&ftrace_sysctl_lock); | 1196 | mutex_lock(&ftrace_sysctl_lock); |
@@ -1137,10 +1201,22 @@ ftrace_filter_release(struct inode *inode, struct file *file) | |||
1137 | mutex_unlock(&ftrace_sysctl_lock); | 1201 | mutex_unlock(&ftrace_sysctl_lock); |
1138 | 1202 | ||
1139 | kfree(iter); | 1203 | kfree(iter); |
1140 | mutex_unlock(&ftrace_filter_lock); | 1204 | mutex_unlock(&ftrace_regex_lock); |
1141 | return 0; | 1205 | return 0; |
1142 | } | 1206 | } |
1143 | 1207 | ||
1208 | static int | ||
1209 | ftrace_filter_release(struct inode *inode, struct file *file) | ||
1210 | { | ||
1211 | return ftrace_regex_release(inode, file, 1); | ||
1212 | } | ||
1213 | |||
1214 | static int | ||
1215 | ftrace_notrace_release(struct inode *inode, struct file *file) | ||
1216 | { | ||
1217 | return ftrace_regex_release(inode, file, 0); | ||
1218 | } | ||
1219 | |||
1144 | static struct file_operations ftrace_avail_fops = { | 1220 | static struct file_operations ftrace_avail_fops = { |
1145 | .open = ftrace_avail_open, | 1221 | .open = ftrace_avail_open, |
1146 | .read = seq_read, | 1222 | .read = seq_read, |
@@ -1150,12 +1226,20 @@ static struct file_operations ftrace_avail_fops = { | |||
1150 | 1226 | ||
1151 | static struct file_operations ftrace_filter_fops = { | 1227 | static struct file_operations ftrace_filter_fops = { |
1152 | .open = ftrace_filter_open, | 1228 | .open = ftrace_filter_open, |
1153 | .read = ftrace_filter_read, | 1229 | .read = ftrace_regex_read, |
1154 | .write = ftrace_filter_write, | 1230 | .write = ftrace_filter_write, |
1155 | .llseek = ftrace_filter_lseek, | 1231 | .llseek = ftrace_regex_lseek, |
1156 | .release = ftrace_filter_release, | 1232 | .release = ftrace_filter_release, |
1157 | }; | 1233 | }; |
1158 | 1234 | ||
1235 | static struct file_operations ftrace_notrace_fops = { | ||
1236 | .open = ftrace_notrace_open, | ||
1237 | .read = ftrace_regex_read, | ||
1238 | .write = ftrace_notrace_write, | ||
1239 | .llseek = ftrace_regex_lseek, | ||
1240 | .release = ftrace_notrace_release, | ||
1241 | }; | ||
1242 | |||
1159 | /** | 1243 | /** |
1160 | * ftrace_force_update - force an update to all recording ftrace functions | 1244 | * ftrace_force_update - force an update to all recording ftrace functions |
1161 | * | 1245 | * |
@@ -1239,6 +1323,12 @@ static __init int ftrace_init_debugfs(void) | |||
1239 | if (!entry) | 1323 | if (!entry) |
1240 | pr_warning("Could not create debugfs " | 1324 | pr_warning("Could not create debugfs " |
1241 | "'set_ftrace_filter' entry\n"); | 1325 | "'set_ftrace_filter' entry\n"); |
1326 | |||
1327 | entry = debugfs_create_file("set_ftrace_notrace", 0644, d_tracer, | ||
1328 | NULL, &ftrace_notrace_fops); | ||
1329 | if (!entry) | ||
1330 | pr_warning("Could not create debugfs " | ||
1331 | "'set_ftrace_notrace' entry\n"); | ||
1242 | return 0; | 1332 | return 0; |
1243 | } | 1333 | } |
1244 | 1334 | ||