aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-02-13 15:56:43 -0500
committerSteven Rostedt <srostedt@redhat.com>2009-02-16 16:49:57 -0500
commit9f4801e30ad291e27284e873696da1ead92d68fa (patch)
tree2a374e89f4f4ecb13cbcf8f914076539e9096517 /kernel/trace/ftrace.c
parent7f24b31b01a271b62346d9df084b029e48612163 (diff)
ftrace: break up ftrace_match_records into smaller components
Impact: clean up ftrace_match_records does a lot of things that other features can use. This patch breaks up ftrace_match_records and pulls out ftrace_setup_glob and ftrace_match_record. ftrace_setup_glob prepares a simple glob expression for use with ftrace_match_record. ftrace_match_record compares a single record with a glob type. Breaking this up will allow for more features to run on individual records. Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c115
1 files changed, 75 insertions, 40 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index f397d7adb62e..fcec31323a10 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1053,79 +1053,114 @@ enum {
1053 MATCH_END_ONLY, 1053 MATCH_END_ONLY,
1054}; 1054};
1055 1055
1056static void 1056/*
1057ftrace_match_records(unsigned char *buff, int len, int enable) 1057 * (static function - no need for kernel doc)
1058 *
1059 * Pass in a buffer containing a glob and this function will
1060 * set search to point to the search part of the buffer and
1061 * return the type of search it is (see enum above).
1062 * This does modify buff.
1063 *
1064 * Returns enum type.
1065 * search returns the pointer to use for comparison.
1066 * not returns 1 if buff started with a '!'
1067 * 0 otherwise.
1068 */
1069static int
1070ftrace_setup_glob(unsigned char *buff, int len, char **search, int *not)
1058{ 1071{
1059 char str[KSYM_SYMBOL_LEN];
1060 char *search = NULL;
1061 struct ftrace_page *pg;
1062 struct dyn_ftrace *rec;
1063 int type = MATCH_FULL; 1072 int type = MATCH_FULL;
1064 unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; 1073 int i;
1065 unsigned i, match = 0, search_len = 0;
1066 int not = 0;
1067 1074
1068 if (buff[0] == '!') { 1075 if (buff[0] == '!') {
1069 not = 1; 1076 *not = 1;
1070 buff++; 1077 buff++;
1071 len--; 1078 len--;
1072 } 1079 } else
1080 *not = 0;
1081
1082 *search = buff;
1073 1083
1074 for (i = 0; i < len; i++) { 1084 for (i = 0; i < len; i++) {
1075 if (buff[i] == '*') { 1085 if (buff[i] == '*') {
1076 if (!i) { 1086 if (!i) {
1077 search = buff + i + 1; 1087 *search = buff + 1;
1078 type = MATCH_END_ONLY; 1088 type = MATCH_END_ONLY;
1079 search_len = len - (i + 1);
1080 } else { 1089 } else {
1081 if (type == MATCH_END_ONLY) { 1090 if (type == MATCH_END_ONLY)
1082 type = MATCH_MIDDLE_ONLY; 1091 type = MATCH_MIDDLE_ONLY;
1083 } else { 1092 else
1084 match = i;
1085 type = MATCH_FRONT_ONLY; 1093 type = MATCH_FRONT_ONLY;
1086 }
1087 buff[i] = 0; 1094 buff[i] = 0;
1088 break; 1095 break;
1089 } 1096 }
1090 } 1097 }
1091 } 1098 }
1092 1099
1100 return type;
1101}
1102
1103static int
1104ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
1105{
1106 char str[KSYM_SYMBOL_LEN];
1107 int matched = 0;
1108 char *ptr;
1109
1110 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
1111 switch (type) {
1112 case MATCH_FULL:
1113 if (strcmp(str, regex) == 0)
1114 matched = 1;
1115 break;
1116 case MATCH_FRONT_ONLY:
1117 if (strncmp(str, regex, len) == 0)
1118 matched = 1;
1119 break;
1120 case MATCH_MIDDLE_ONLY:
1121 if (strstr(str, regex))
1122 matched = 1;
1123 break;
1124 case MATCH_END_ONLY:
1125 ptr = strstr(str, regex);
1126 if (ptr && (ptr[len] == 0))
1127 matched = 1;
1128 break;
1129 }
1130
1131 return matched;
1132}
1133
1134static void ftrace_match_records(char *buff, int len, int enable)
1135{
1136 char *search;
1137 struct ftrace_page *pg;
1138 struct dyn_ftrace *rec;
1139 int type;
1140 unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
1141 unsigned search_len;
1142 int not;
1143
1144 type = ftrace_setup_glob(buff, len, &search, &not);
1145
1146 search_len = strlen(search);
1147
1093 /* should not be called from interrupt context */ 1148 /* should not be called from interrupt context */
1094 spin_lock(&ftrace_lock); 1149 spin_lock(&ftrace_lock);
1095 if (enable) 1150 if (enable)
1096 ftrace_filtered = 1; 1151 ftrace_filtered = 1;
1097 do_for_each_ftrace_rec(pg, rec) { 1152 do_for_each_ftrace_rec(pg, rec) {
1098 int matched = 0;
1099 char *ptr;
1100 1153
1101 if (rec->flags & FTRACE_FL_FAILED) 1154 if (rec->flags & FTRACE_FL_FAILED)
1102 continue; 1155 continue;
1103 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); 1156
1104 switch (type) { 1157 if (ftrace_match_record(rec, search, search_len, type)) {
1105 case MATCH_FULL:
1106 if (strcmp(str, buff) == 0)
1107 matched = 1;
1108 break;
1109 case MATCH_FRONT_ONLY:
1110 if (memcmp(str, buff, match) == 0)
1111 matched = 1;
1112 break;
1113 case MATCH_MIDDLE_ONLY:
1114 if (strstr(str, search))
1115 matched = 1;
1116 break;
1117 case MATCH_END_ONLY:
1118 ptr = strstr(str, search);
1119 if (ptr && (ptr[search_len] == 0))
1120 matched = 1;
1121 break;
1122 }
1123 if (matched) {
1124 if (not) 1158 if (not)
1125 rec->flags &= ~flag; 1159 rec->flags &= ~flag;
1126 else 1160 else
1127 rec->flags |= flag; 1161 rec->flags |= flag;
1128 } 1162 }
1163
1129 } while_for_each_ftrace_rec(); 1164 } while_for_each_ftrace_rec();
1130 spin_unlock(&ftrace_lock); 1165 spin_unlock(&ftrace_lock);
1131} 1166}