aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2008-05-22 11:46:33 -0400
committerThomas Gleixner <tglx@linutronix.de>2008-05-26 16:51:37 -0400
commit41c52c0db9607e59f90da7da5309489fa06e887f (patch)
treeb0b1f282c087c53dfd4081da5a8a35cdc5ea5ebb /kernel
parentda89a7a2536c46e76a1a4351a70a8b8417e5fed1 (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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/ftrace.c170
1 files changed, 130 insertions, 40 deletions
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
171static DEFINE_SPINLOCK(ftrace_shutdown_lock); 171static DEFINE_SPINLOCK(ftrace_shutdown_lock);
172static DEFINE_MUTEX(ftraced_lock); 172static DEFINE_MUTEX(ftraced_lock);
173static DEFINE_MUTEX(ftrace_filter_lock); 173static DEFINE_MUTEX(ftrace_regex_lock);
174 174
175struct ftrace_page { 175struct 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)
721enum { 731enum {
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
850static void ftrace_filter_reset(void) 863static 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
872static int 887static int
873ftrace_filter_open(struct inode *inode, struct file *file) 888ftrace_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
924static int
925ftrace_filter_open(struct inode *inode, struct file *file)
926{
927 return ftrace_regex_open(inode, file, 1);
928}
929
930static int
931ftrace_notrace_open(struct inode *inode, struct file *file)
932{
933 return ftrace_regex_open(inode, file, 0);
934}
935
908static ssize_t 936static ssize_t
909ftrace_filter_read(struct file *file, char __user *ubuf, 937ftrace_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
918static loff_t 946static loff_t
919ftrace_filter_lseek(struct file *file, loff_t offset, int origin) 947ftrace_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
938static void 966static void
939ftrace_match(unsigned char *buff, int len) 967ftrace_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
1007static ssize_t 1037static ssize_t
1008ftrace_filter_write(struct file *file, const char __user *ubuf, 1038ftrace_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
1119static ssize_t
1120ftrace_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
1126static ssize_t
1127ftrace_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
1133static void
1134ftrace_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 */
1099void ftrace_set_filter(unsigned char *buf, int len, int reset) 1156void 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 */
1171void ftrace_set_notrace(unsigned char *buf, int len, int reset)
1172{
1173 ftrace_set_regex(buf, len, reset, 0);
1110} 1174}
1111 1175
1112static int 1176static int
1113ftrace_filter_release(struct inode *inode, struct file *file) 1177ftrace_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
1208static int
1209ftrace_filter_release(struct inode *inode, struct file *file)
1210{
1211 return ftrace_regex_release(inode, file, 1);
1212}
1213
1214static int
1215ftrace_notrace_release(struct inode *inode, struct file *file)
1216{
1217 return ftrace_regex_release(inode, file, 0);
1218}
1219
1144static struct file_operations ftrace_avail_fops = { 1220static 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
1151static struct file_operations ftrace_filter_fops = { 1227static 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
1235static 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