aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-02-19 15:13:12 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-20 05:36:24 -0500
commitf9349a8f978929a0c71d2c42ae299f7d462c239d (patch)
treee5d010a27078993709fd286f358122886cbbc3bc
parent64b36ca7f408e0bd45487c8c28f168f11f3b6dcd (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.c56
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
1968static int 1977static int
1969ftrace_set_func(unsigned long *array, int idx, char *buffer) 1978ftrace_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, &not);
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;