|
@@ -1067,7 +1067,7 @@ enum {
|
|
|
* 0 otherwise.
|
|
|
*/
|
|
|
static int
|
|
|
-ftrace_setup_glob(unsigned char *buff, int len, char **search, int *not)
|
|
|
+ftrace_setup_glob(char *buff, int len, char **search, int *not)
|
|
|
{
|
|
|
int type = MATCH_FULL;
|
|
|
int i;
|
|
@@ -1100,14 +1100,11 @@ ftrace_setup_glob(unsigned char *buff, int len, char **search, int *not)
|
|
|
return type;
|
|
|
}
|
|
|
|
|
|
-static int
|
|
|
-ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
|
|
|
+static int ftrace_match(char *str, char *regex, int len, int type)
|
|
|
{
|
|
|
- char str[KSYM_SYMBOL_LEN];
|
|
|
int matched = 0;
|
|
|
char *ptr;
|
|
|
|
|
|
- kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
|
|
|
switch (type) {
|
|
|
case MATCH_FULL:
|
|
|
if (strcmp(str, regex) == 0)
|
|
@@ -1131,6 +1128,15 @@ ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
|
|
|
return matched;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type)
|
|
|
+{
|
|
|
+ char str[KSYM_SYMBOL_LEN];
|
|
|
+
|
|
|
+ kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
|
|
|
+ return ftrace_match(str, regex, len, type);
|
|
|
+}
|
|
|
+
|
|
|
static void ftrace_match_records(char *buff, int len, int enable)
|
|
|
{
|
|
|
char *search;
|
|
@@ -1165,6 +1171,100 @@ static void ftrace_match_records(char *buff, int len, int enable)
|
|
|
spin_unlock(&ftrace_lock);
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+ftrace_match_module_record(struct dyn_ftrace *rec, char *mod,
|
|
|
+ char *regex, int len, int type)
|
|
|
+{
|
|
|
+ char str[KSYM_SYMBOL_LEN];
|
|
|
+ char *modname;
|
|
|
+
|
|
|
+ kallsyms_lookup(rec->ip, NULL, NULL, &modname, str);
|
|
|
+
|
|
|
+ if (!modname || strcmp(modname, mod))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* blank search means to match all funcs in the mod */
|
|
|
+ if (len)
|
|
|
+ return ftrace_match(str, regex, len, type);
|
|
|
+ else
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+static void ftrace_match_module_records(char *buff, char *mod, int enable)
|
|
|
+{
|
|
|
+ char *search = buff;
|
|
|
+ struct ftrace_page *pg;
|
|
|
+ struct dyn_ftrace *rec;
|
|
|
+ int type = MATCH_FULL;
|
|
|
+ unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
|
|
|
+ unsigned search_len = 0;
|
|
|
+ int not = 0;
|
|
|
+
|
|
|
+ /* blank or '*' mean the same */
|
|
|
+ if (strcmp(buff, "*") == 0)
|
|
|
+ buff[0] = 0;
|
|
|
+
|
|
|
+ /* handle the case of 'dont filter this module' */
|
|
|
+ if (strcmp(buff, "!") == 0 || strcmp(buff, "!*") == 0) {
|
|
|
+ buff[0] = 0;
|
|
|
+ not = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (strlen(buff)) {
|
|
|
+ type = ftrace_setup_glob(buff, strlen(buff), &search, ¬);
|
|
|
+ search_len = strlen(search);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* should not be called from interrupt context */
|
|
|
+ spin_lock(&ftrace_lock);
|
|
|
+ if (enable)
|
|
|
+ ftrace_filtered = 1;
|
|
|
+
|
|
|
+ do_for_each_ftrace_rec(pg, rec) {
|
|
|
+
|
|
|
+ if (rec->flags & FTRACE_FL_FAILED)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (ftrace_match_module_record(rec, mod,
|
|
|
+ search, search_len, type)) {
|
|
|
+ if (not)
|
|
|
+ rec->flags &= ~flag;
|
|
|
+ else
|
|
|
+ rec->flags |= flag;
|
|
|
+ }
|
|
|
+
|
|
|
+ } while_for_each_ftrace_rec();
|
|
|
+ spin_unlock(&ftrace_lock);
|
|
|
+}
|
|
|
+
|
|
|
+static int ftrace_process_regex(char *buff, int len, int enable)
|
|
|
+{
|
|
|
+ char *func, *mod, *command, *next = buff;
|
|
|
+
|
|
|
+ func = strsep(&next, ":");
|
|
|
+
|
|
|
+ if (!next) {
|
|
|
+ ftrace_match_records(func, len, enable);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* command fonud */
|
|
|
+
|
|
|
+ command = strsep(&next, ":");
|
|
|
+
|
|
|
+ if (strcmp(command, "mod") == 0) {
|
|
|
+ /* only match modules */
|
|
|
+ if (!next)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ mod = strsep(&next, ":");
|
|
|
+ ftrace_match_module_records(func, mod, enable);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -EINVAL;
|
|
|
+}
|
|
|
+
|
|
|
static ssize_t
|
|
|
ftrace_regex_write(struct file *file, const char __user *ubuf,
|
|
|
size_t cnt, loff_t *ppos, int enable)
|
|
@@ -1232,7 +1332,10 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
|
|
|
if (isspace(ch)) {
|
|
|
iter->filtered++;
|
|
|
iter->buffer[iter->buffer_idx] = 0;
|
|
|
- ftrace_match_records(iter->buffer, iter->buffer_idx, enable);
|
|
|
+ ret = ftrace_process_regex(iter->buffer,
|
|
|
+ iter->buffer_idx, enable);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
iter->buffer_idx = 0;
|
|
|
} else
|
|
|
iter->flags |= FTRACE_ITER_CONT;
|