diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-02-19 15:13:12 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-20 05:36:24 -0500 |
commit | f9349a8f978929a0c71d2c42ae299f7d462c239d (patch) | |
tree | e5d010a27078993709fd286f358122886cbbc3bc | |
parent | 64b36ca7f408e0bd45487c8c28f168f11f3b6dcd (diff) |
tracing/function-graph-tracer: make set_graph_function file support ftrace regex
Impact: trace only functions matching a pattern
The set_graph_function file let one to trace only one or several
chosen functions and follow all their code flow.
Currently, only a constant function name is allowed so this patch
allows the ftrace_regex functions:
- matches all functions that end with "name":
echo *name > set_graph_function
- matches all functions that begin with "name":
echo name* > set_graph_function
- matches all functions that contains "name":
echo *name* > set_graph_function
Example:
echo mutex* > set_graph_function
0) | mutex_lock_nested() {
0) 0.563 us | __might_sleep();
0) 2.072 us | }
0) | mutex_unlock() {
0) 1.036 us | __mutex_unlock_slowpath();
0) 2.433 us | }
0) | mutex_unlock() {
0) 0.691 us | __mutex_unlock_slowpath();
0) 1.787 us | }
0) | mutex_lock_interruptible_nested() {
0) 0.548 us | __might_sleep();
0) 1.945 us | }
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | kernel/trace/ftrace.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 7dd5a2bef9cd..cf59f4c54745 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -1895,6 +1895,10 @@ static void *g_start(struct seq_file *m, loff_t *pos) | |||
1895 | 1895 | ||
1896 | mutex_lock(&graph_lock); | 1896 | mutex_lock(&graph_lock); |
1897 | 1897 | ||
1898 | /* Nothing, tell g_show to print all functions are enabled */ | ||
1899 | if (!ftrace_graph_count && !*pos) | ||
1900 | return (void *)1; | ||
1901 | |||
1898 | p = g_next(m, p, pos); | 1902 | p = g_next(m, p, pos); |
1899 | 1903 | ||
1900 | return p; | 1904 | return p; |
@@ -1913,6 +1917,11 @@ static int g_show(struct seq_file *m, void *v) | |||
1913 | if (!ptr) | 1917 | if (!ptr) |
1914 | return 0; | 1918 | return 0; |
1915 | 1919 | ||
1920 | if (ptr == (unsigned long *)1) { | ||
1921 | seq_printf(m, "#### all functions enabled ####\n"); | ||
1922 | return 0; | ||
1923 | } | ||
1924 | |||
1916 | kallsyms_lookup(*ptr, NULL, NULL, NULL, str); | 1925 | kallsyms_lookup(*ptr, NULL, NULL, NULL, str); |
1917 | 1926 | ||
1918 | seq_printf(m, "%s\n", str); | 1927 | seq_printf(m, "%s\n", str); |
@@ -1966,38 +1975,51 @@ ftrace_graph_read(struct file *file, char __user *ubuf, | |||
1966 | } | 1975 | } |
1967 | 1976 | ||
1968 | static int | 1977 | static int |
1969 | ftrace_set_func(unsigned long *array, int idx, char *buffer) | 1978 | ftrace_set_func(unsigned long *array, int *idx, char *buffer) |
1970 | { | 1979 | { |
1971 | char str[KSYM_SYMBOL_LEN]; | ||
1972 | struct dyn_ftrace *rec; | 1980 | struct dyn_ftrace *rec; |
1973 | struct ftrace_page *pg; | 1981 | struct ftrace_page *pg; |
1982 | int search_len; | ||
1974 | int found = 0; | 1983 | int found = 0; |
1975 | int j; | 1984 | int type, not; |
1985 | char *search; | ||
1986 | bool exists; | ||
1987 | int i; | ||
1976 | 1988 | ||
1977 | if (ftrace_disabled) | 1989 | if (ftrace_disabled) |
1978 | return -ENODEV; | 1990 | return -ENODEV; |
1979 | 1991 | ||
1992 | /* decode regex */ | ||
1993 | type = ftrace_setup_glob(buffer, strlen(buffer), &search, ¬); | ||
1994 | if (not) | ||
1995 | return -EINVAL; | ||
1996 | |||
1997 | search_len = strlen(search); | ||
1998 | |||
1980 | mutex_lock(&ftrace_lock); | 1999 | mutex_lock(&ftrace_lock); |
1981 | do_for_each_ftrace_rec(pg, rec) { | 2000 | do_for_each_ftrace_rec(pg, rec) { |
1982 | 2001 | ||
2002 | if (*idx >= FTRACE_GRAPH_MAX_FUNCS) | ||
2003 | break; | ||
2004 | |||
1983 | if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE)) | 2005 | if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE)) |
1984 | continue; | 2006 | continue; |
1985 | 2007 | ||
1986 | kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); | 2008 | if (ftrace_match_record(rec, search, search_len, type)) { |
1987 | if (strcmp(str, buffer) == 0) { | 2009 | /* ensure it is not already in the array */ |
1988 | /* Return 1 if we add it to the array */ | 2010 | exists = false; |
1989 | found = 1; | 2011 | for (i = 0; i < *idx; i++) |
1990 | for (j = 0; j < idx; j++) | 2012 | if (array[i] == rec->ip) { |
1991 | if (array[j] == rec->ip) { | 2013 | exists = true; |
1992 | found = 0; | ||
1993 | break; | 2014 | break; |
1994 | } | 2015 | } |
1995 | if (found) | 2016 | if (!exists) { |
1996 | array[idx] = rec->ip; | 2017 | array[(*idx)++] = rec->ip; |
1997 | goto out; | 2018 | found = 1; |
2019 | } | ||
1998 | } | 2020 | } |
1999 | } while_for_each_ftrace_rec(); | 2021 | } while_for_each_ftrace_rec(); |
2000 | out: | 2022 | |
2001 | mutex_unlock(&ftrace_lock); | 2023 | mutex_unlock(&ftrace_lock); |
2002 | 2024 | ||
2003 | return found ? 0 : -EINVAL; | 2025 | return found ? 0 : -EINVAL; |
@@ -2066,13 +2088,11 @@ ftrace_graph_write(struct file *file, const char __user *ubuf, | |||
2066 | } | 2088 | } |
2067 | buffer[index] = 0; | 2089 | buffer[index] = 0; |
2068 | 2090 | ||
2069 | /* we allow only one at a time */ | 2091 | /* we allow only one expression at a time */ |
2070 | ret = ftrace_set_func(array, ftrace_graph_count, buffer); | 2092 | ret = ftrace_set_func(array, &ftrace_graph_count, buffer); |
2071 | if (ret) | 2093 | if (ret) |
2072 | goto out; | 2094 | goto out; |
2073 | 2095 | ||
2074 | ftrace_graph_count++; | ||
2075 | |||
2076 | file->f_pos += read; | 2096 | file->f_pos += read; |
2077 | 2097 | ||
2078 | ret = read; | 2098 | ret = read; |