mirror of
https://github.com/torvalds/linux
synced 2024-09-22 20:37:18 +00:00
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>
This commit is contained in:
parent
7f24b31b01
commit
9f4801e30a
|
@ -1053,79 +1053,114 @@ enum {
|
||||||
MATCH_END_ONLY,
|
MATCH_END_ONLY,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
/*
|
||||||
ftrace_match_records(unsigned char *buff, int len, int enable)
|
* (static function - no need for kernel doc)
|
||||||
|
*
|
||||||
|
* Pass in a buffer containing a glob and this function will
|
||||||
|
* set search to point to the search part of the buffer and
|
||||||
|
* return the type of search it is (see enum above).
|
||||||
|
* This does modify buff.
|
||||||
|
*
|
||||||
|
* Returns enum type.
|
||||||
|
* search returns the pointer to use for comparison.
|
||||||
|
* not returns 1 if buff started with a '!'
|
||||||
|
* 0 otherwise.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ftrace_setup_glob(unsigned char *buff, int len, char **search, int *not)
|
||||||
{
|
{
|
||||||
char str[KSYM_SYMBOL_LEN];
|
|
||||||
char *search = NULL;
|
|
||||||
struct ftrace_page *pg;
|
|
||||||
struct dyn_ftrace *rec;
|
|
||||||
int type = MATCH_FULL;
|
int type = MATCH_FULL;
|
||||||
unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
|
int i;
|
||||||
unsigned i, match = 0, search_len = 0;
|
|
||||||
int not = 0;
|
|
||||||
|
|
||||||
if (buff[0] == '!') {
|
if (buff[0] == '!') {
|
||||||
not = 1;
|
*not = 1;
|
||||||
buff++;
|
buff++;
|
||||||
len--;
|
len--;
|
||||||
}
|
} else
|
||||||
|
*not = 0;
|
||||||
|
|
||||||
|
*search = buff;
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (buff[i] == '*') {
|
if (buff[i] == '*') {
|
||||||
if (!i) {
|
if (!i) {
|
||||||
search = buff + i + 1;
|
*search = buff + 1;
|
||||||
type = MATCH_END_ONLY;
|
type = MATCH_END_ONLY;
|
||||||
search_len = len - (i + 1);
|
|
||||||
} else {
|
} else {
|
||||||
if (type == MATCH_END_ONLY) {
|
if (type == MATCH_END_ONLY)
|
||||||
type = MATCH_MIDDLE_ONLY;
|
type = MATCH_MIDDLE_ONLY;
|
||||||
} else {
|
else
|
||||||
match = i;
|
|
||||||
type = MATCH_FRONT_ONLY;
|
type = MATCH_FRONT_ONLY;
|
||||||
}
|
|
||||||
buff[i] = 0;
|
buff[i] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ftrace_match_record(struct dyn_ftrace *rec, 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)
|
||||||
|
matched = 1;
|
||||||
|
break;
|
||||||
|
case MATCH_FRONT_ONLY:
|
||||||
|
if (strncmp(str, regex, len) == 0)
|
||||||
|
matched = 1;
|
||||||
|
break;
|
||||||
|
case MATCH_MIDDLE_ONLY:
|
||||||
|
if (strstr(str, regex))
|
||||||
|
matched = 1;
|
||||||
|
break;
|
||||||
|
case MATCH_END_ONLY:
|
||||||
|
ptr = strstr(str, regex);
|
||||||
|
if (ptr && (ptr[len] == 0))
|
||||||
|
matched = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ftrace_match_records(char *buff, int len, int enable)
|
||||||
|
{
|
||||||
|
char *search;
|
||||||
|
struct ftrace_page *pg;
|
||||||
|
struct dyn_ftrace *rec;
|
||||||
|
int type;
|
||||||
|
unsigned long flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
|
||||||
|
unsigned search_len;
|
||||||
|
int not;
|
||||||
|
|
||||||
|
type = ftrace_setup_glob(buff, len, &search, ¬);
|
||||||
|
|
||||||
|
search_len = strlen(search);
|
||||||
|
|
||||||
/* should not be called from interrupt context */
|
/* should not be called from interrupt context */
|
||||||
spin_lock(&ftrace_lock);
|
spin_lock(&ftrace_lock);
|
||||||
if (enable)
|
if (enable)
|
||||||
ftrace_filtered = 1;
|
ftrace_filtered = 1;
|
||||||
do_for_each_ftrace_rec(pg, rec) {
|
do_for_each_ftrace_rec(pg, rec) {
|
||||||
int matched = 0;
|
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
if (rec->flags & FTRACE_FL_FAILED)
|
if (rec->flags & FTRACE_FL_FAILED)
|
||||||
continue;
|
continue;
|
||||||
kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
|
|
||||||
switch (type) {
|
if (ftrace_match_record(rec, search, search_len, type)) {
|
||||||
case MATCH_FULL:
|
|
||||||
if (strcmp(str, buff) == 0)
|
|
||||||
matched = 1;
|
|
||||||
break;
|
|
||||||
case MATCH_FRONT_ONLY:
|
|
||||||
if (memcmp(str, buff, match) == 0)
|
|
||||||
matched = 1;
|
|
||||||
break;
|
|
||||||
case MATCH_MIDDLE_ONLY:
|
|
||||||
if (strstr(str, search))
|
|
||||||
matched = 1;
|
|
||||||
break;
|
|
||||||
case MATCH_END_ONLY:
|
|
||||||
ptr = strstr(str, search);
|
|
||||||
if (ptr && (ptr[search_len] == 0))
|
|
||||||
matched = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (matched) {
|
|
||||||
if (not)
|
if (not)
|
||||||
rec->flags &= ~flag;
|
rec->flags &= ~flag;
|
||||||
else
|
else
|
||||||
rec->flags |= flag;
|
rec->flags |= flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while_for_each_ftrace_rec();
|
} while_for_each_ftrace_rec();
|
||||||
spin_unlock(&ftrace_lock);
|
spin_unlock(&ftrace_lock);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue