aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-02-13 17:08:48 -0500
committerSteven Rostedt <srostedt@redhat.com>2009-02-16 16:55:50 -0500
commit64e7c440618998fd69eee6ab490b042d12248021 (patch)
tree384246f895f2697dd6927b776c67755cc13e901d /kernel/trace/ftrace.c
parent9f4801e30ad291e27284e873696da1ead92d68fa (diff)
ftrace: add module command function filter selection
This patch adds a "command" syntax to the function filtering files: /debugfs/tracing/set_ftrace_filter /debugfs/tracing/set_ftrace_notrace Of the format: <function>:<command>:<parameter> The command is optional, and dependent on the command, so are the parameters. echo do_fork > set_ftrace_filter Will only trace 'do_fork'. echo 'sched_*' > set_ftrace_filter Will only trace functions starting with the letters 'sched_'. echo '*:mod:ext3' > set_ftrace_filter Will trace only the ext3 module functions. echo '*write*:mod:ext3' > set_ftrace_notrace Will prevent the ext3 functions with the letters 'write' in the name from being traced. echo '!*_allocate:mod:ext3' > set_ftrace_filter Will remove the functions in ext3 that end with the letters '_allocate' from the ftrace filter. Although this patch implements the 'command' format, only the 'mod' command is supported. More commands to follow. 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, 109 insertions, 6 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index fcec31323a10..9e60ae423af9 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1067,7 +1067,7 @@ enum {
1067 * 0 otherwise. 1067 * 0 otherwise.
1068 */ 1068 */
1069static int 1069static int
1070ftrace_setup_glob(unsigned char *buff, int len, char **search, int *not) 1070ftrace_setup_glob(char *buff, int len, char **search, int *not)
1071{ 1071{
1072 int type = MATCH_FULL; 1072 int type = MATCH_FULL;
1073 int i; 1073 int i;
@@ -1100,14 +1100,11 @@ ftrace_setup_glob(unsigned char *buff, int len, char **search, int *not)
1100 return type; 1100 return type;
1101} 1101}
1102 1102
1103static int 1103static int ftrace_match(char *str, char *regex, int len, int type)
1104ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
1105{ 1104{
1106 char str[KSYM_SYMBOL_LEN];
1107 int matched = 0; 1105 int matched = 0;
1108 char *ptr; 1106 char *ptr;
1109 1107
1110 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
1111 switch (type) { 1108 switch (type) {
1112 case MATCH_FULL: 1109 case MATCH_FULL:
1113 if (strcmp(str, regex) == 0) 1110 if (strcmp(str, regex) == 0)
@@ -1131,6 +1128,15 @@ ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
1131 return matched; 1128 return matched;
1132} 1129}
1133 1130
1131static int
1132ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
1133{
1134 char str[KSYM_SYMBOL_LEN];
1135
1136 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
1137 return ftrace_match(str, regex, len, type);
1138}
1139
1134static void ftrace_match_records(char *buff, int len, int enable) 1140static void ftrace_match_records(char *buff, int len, int enable)
1135{ 1141{
1136 char *search; 1142 char *search;
@@ -1165,6 +1171,100 @@ static void ftrace_match_records(char *buff, int len, int enable)
1165 spin_unlock(&ftrace_lock); 1171 spin_unlock(&ftrace_lock);
1166} 1172}
1167 1173
1174static int
1175ftrace_match_module_record(struct dyn_ftrace *rec, char *mod,
1176 char *regex, int len, int type)
1177{
1178 char str[KSYM_SYMBOL_LEN];
1179 char *modname;
1180
1181 kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
1182
1183 if (!modname || strcmp(modname, mod))
1184 return 0;
1185
1186 /* blank search means to match all funcs in the mod */
1187 if (len)
1188 return ftrace_match(str, regex, len, type);
1189 else
1190 return 1;
1191}
1192
1193static void ftrace_match_module_records(char *buff, char *mod, int enable)
1194{
1195 char *search = buff;
1196 struct ftrace_page *pg;
1197 struct dyn_ftrace *rec;
1198 int type = MATCH_FULL;
1199 unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
1200 unsigned search_len = 0;
1201 int not = 0;
1202
1203 /* blank or '*' mean the same */
1204 if (strcmp(buff, "*") == 0)
1205 buff[0] = 0;
1206
1207 /* handle the case of 'dont filter this module' */
1208 if (strcmp(buff, "!") == 0 || strcmp(buff, "!*") == 0) {
1209 buff[0] = 0;
1210 not = 1;
1211 }
1212
1213 if (strlen(buff)) {
1214 type = ftrace_setup_glob(buff, strlen(buff), &search, &not);
1215 search_len = strlen(search);
1216 }
1217
1218 /* should not be called from interrupt context */
1219 spin_lock(&ftrace_lock);
1220 if (enable)
1221 ftrace_filtered = 1;
1222
1223 do_for_each_ftrace_rec(pg, rec) {
1224
1225 if (rec->flags & FTRACE_FL_FAILED)
1226 continue;
1227
1228 if (ftrace_match_module_record(rec, mod,
1229 search, search_len, type)) {
1230 if (not)
1231 rec->flags &= ~flag;
1232 else
1233 rec->flags |= flag;
1234 }
1235
1236 } while_for_each_ftrace_rec();
1237 spin_unlock(&ftrace_lock);
1238}
1239
1240static int ftrace_process_regex(char *buff, int len, int enable)
1241{
1242 char *func, *mod, *command, *next = buff;
1243
1244 func = strsep(&next, ":");
1245
1246 if (!next) {
1247 ftrace_match_records(func, len, enable);
1248 return 0;
1249 }
1250
1251 /* command fonud */
1252
1253 command = strsep(&next, ":");
1254
1255 if (strcmp(command, "mod") == 0) {
1256 /* only match modules */
1257 if (!next)
1258 return -EINVAL;
1259
1260 mod = strsep(&next, ":");
1261 ftrace_match_module_records(func, mod, enable);
1262 return 0;
1263 }
1264
1265 return -EINVAL;
1266}
1267
1168static ssize_t 1268static ssize_t
1169ftrace_regex_write(struct file *file, const char __user *ubuf, 1269ftrace_regex_write(struct file *file, const char __user *ubuf,
1170 size_t cnt, loff_t *ppos, int enable) 1270 size_t cnt, loff_t *ppos, int enable)
@@ -1232,7 +1332,10 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
1232 if (isspace(ch)) { 1332 if (isspace(ch)) {
1233 iter->filtered++; 1333 iter->filtered++;
1234 iter->buffer[iter->buffer_idx] = 0; 1334 iter->buffer[iter->buffer_idx] = 0;
1235 ftrace_match_records(iter->buffer, iter->buffer_idx, enable); 1335 ret = ftrace_process_regex(iter->buffer,
1336 iter->buffer_idx, enable);
1337 if (ret)
1338 goto out;
1236 iter->buffer_idx = 0; 1339 iter->buffer_idx = 0;
1237 } else 1340 } else
1238 iter->flags |= FTRACE_ITER_CONT; 1341 iter->flags |= FTRACE_ITER_CONT;