diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-05-01 13:11:42 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-05-01 13:11:42 -0400 |
commit | ac0a3260f37b8616da8d33488ec94b94e6ae5b31 (patch) | |
tree | 0db61f7492d45f1d548b0bcef06a0df9c904442c /kernel/trace | |
parent | 809435ff4f43a5c0cb0201b3b89176253d5ade18 (diff) | |
parent | b9df92d2a94eef8811061aecb1396290df440e2e (diff) |
Merge branch 'tip/perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace into perf/core
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/ftrace.c | 347 |
1 files changed, 138 insertions, 209 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 666880d051ef..d3406346ced6 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -39,16 +39,20 @@ | |||
39 | #include "trace_stat.h" | 39 | #include "trace_stat.h" |
40 | 40 | ||
41 | #define FTRACE_WARN_ON(cond) \ | 41 | #define FTRACE_WARN_ON(cond) \ |
42 | do { \ | 42 | ({ \ |
43 | if (WARN_ON(cond)) \ | 43 | int ___r = cond; \ |
44 | if (WARN_ON(___r)) \ | ||
44 | ftrace_kill(); \ | 45 | ftrace_kill(); \ |
45 | } while (0) | 46 | ___r; \ |
47 | }) | ||
46 | 48 | ||
47 | #define FTRACE_WARN_ON_ONCE(cond) \ | 49 | #define FTRACE_WARN_ON_ONCE(cond) \ |
48 | do { \ | 50 | ({ \ |
49 | if (WARN_ON_ONCE(cond)) \ | 51 | int ___r = cond; \ |
52 | if (WARN_ON_ONCE(___r)) \ | ||
50 | ftrace_kill(); \ | 53 | ftrace_kill(); \ |
51 | } while (0) | 54 | ___r; \ |
55 | }) | ||
52 | 56 | ||
53 | /* hash bits for specific function selection */ | 57 | /* hash bits for specific function selection */ |
54 | #define FTRACE_HASH_BITS 7 | 58 | #define FTRACE_HASH_BITS 7 |
@@ -147,6 +151,34 @@ static void ftrace_test_stop_func(unsigned long ip, unsigned long parent_ip) | |||
147 | } | 151 | } |
148 | #endif | 152 | #endif |
149 | 153 | ||
154 | static void update_ftrace_function(void) | ||
155 | { | ||
156 | ftrace_func_t func; | ||
157 | |||
158 | /* | ||
159 | * If there's only one function registered, then call that | ||
160 | * function directly. Otherwise, we need to iterate over the | ||
161 | * registered callers. | ||
162 | */ | ||
163 | if (ftrace_list == &ftrace_list_end || | ||
164 | ftrace_list->next == &ftrace_list_end) | ||
165 | func = ftrace_list->func; | ||
166 | else | ||
167 | func = ftrace_list_func; | ||
168 | |||
169 | /* If we filter on pids, update to use the pid function */ | ||
170 | if (!list_empty(&ftrace_pids)) { | ||
171 | set_ftrace_pid_function(func); | ||
172 | func = ftrace_pid_func; | ||
173 | } | ||
174 | #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST | ||
175 | ftrace_trace_function = func; | ||
176 | #else | ||
177 | __ftrace_trace_function = func; | ||
178 | ftrace_trace_function = ftrace_test_stop_func; | ||
179 | #endif | ||
180 | } | ||
181 | |||
150 | static int __register_ftrace_function(struct ftrace_ops *ops) | 182 | static int __register_ftrace_function(struct ftrace_ops *ops) |
151 | { | 183 | { |
152 | ops->next = ftrace_list; | 184 | ops->next = ftrace_list; |
@@ -158,30 +190,8 @@ static int __register_ftrace_function(struct ftrace_ops *ops) | |||
158 | */ | 190 | */ |
159 | rcu_assign_pointer(ftrace_list, ops); | 191 | rcu_assign_pointer(ftrace_list, ops); |
160 | 192 | ||
161 | if (ftrace_enabled) { | 193 | if (ftrace_enabled) |
162 | ftrace_func_t func; | 194 | update_ftrace_function(); |
163 | |||
164 | if (ops->next == &ftrace_list_end) | ||
165 | func = ops->func; | ||
166 | else | ||
167 | func = ftrace_list_func; | ||
168 | |||
169 | if (!list_empty(&ftrace_pids)) { | ||
170 | set_ftrace_pid_function(func); | ||
171 | func = ftrace_pid_func; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * For one func, simply call it directly. | ||
176 | * For more than one func, call the chain. | ||
177 | */ | ||
178 | #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST | ||
179 | ftrace_trace_function = func; | ||
180 | #else | ||
181 | __ftrace_trace_function = func; | ||
182 | ftrace_trace_function = ftrace_test_stop_func; | ||
183 | #endif | ||
184 | } | ||
185 | 195 | ||
186 | return 0; | 196 | return 0; |
187 | } | 197 | } |
@@ -209,52 +219,19 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) | |||
209 | 219 | ||
210 | *p = (*p)->next; | 220 | *p = (*p)->next; |
211 | 221 | ||
212 | if (ftrace_enabled) { | 222 | if (ftrace_enabled) |
213 | /* If we only have one func left, then call that directly */ | 223 | update_ftrace_function(); |
214 | if (ftrace_list->next == &ftrace_list_end) { | ||
215 | ftrace_func_t func = ftrace_list->func; | ||
216 | |||
217 | if (!list_empty(&ftrace_pids)) { | ||
218 | set_ftrace_pid_function(func); | ||
219 | func = ftrace_pid_func; | ||
220 | } | ||
221 | #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST | ||
222 | ftrace_trace_function = func; | ||
223 | #else | ||
224 | __ftrace_trace_function = func; | ||
225 | #endif | ||
226 | } | ||
227 | } | ||
228 | 224 | ||
229 | return 0; | 225 | return 0; |
230 | } | 226 | } |
231 | 227 | ||
232 | static void ftrace_update_pid_func(void) | 228 | static void ftrace_update_pid_func(void) |
233 | { | 229 | { |
234 | ftrace_func_t func; | 230 | /* Only do something if we are tracing something */ |
235 | |||
236 | if (ftrace_trace_function == ftrace_stub) | 231 | if (ftrace_trace_function == ftrace_stub) |
237 | return; | 232 | return; |
238 | 233 | ||
239 | #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST | 234 | update_ftrace_function(); |
240 | func = ftrace_trace_function; | ||
241 | #else | ||
242 | func = __ftrace_trace_function; | ||
243 | #endif | ||
244 | |||
245 | if (!list_empty(&ftrace_pids)) { | ||
246 | set_ftrace_pid_function(func); | ||
247 | func = ftrace_pid_func; | ||
248 | } else { | ||
249 | if (func == ftrace_pid_func) | ||
250 | func = ftrace_pid_function; | ||
251 | } | ||
252 | |||
253 | #ifdef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST | ||
254 | ftrace_trace_function = func; | ||
255 | #else | ||
256 | __ftrace_trace_function = func; | ||
257 | #endif | ||
258 | } | 235 | } |
259 | 236 | ||
260 | #ifdef CONFIG_FUNCTION_PROFILER | 237 | #ifdef CONFIG_FUNCTION_PROFILER |
@@ -1079,19 +1056,16 @@ static void ftrace_replace_code(int enable) | |||
1079 | struct ftrace_page *pg; | 1056 | struct ftrace_page *pg; |
1080 | int failed; | 1057 | int failed; |
1081 | 1058 | ||
1059 | if (unlikely(ftrace_disabled)) | ||
1060 | return; | ||
1061 | |||
1082 | do_for_each_ftrace_rec(pg, rec) { | 1062 | do_for_each_ftrace_rec(pg, rec) { |
1083 | /* | 1063 | /* Skip over free records */ |
1084 | * Skip over free records, records that have | 1064 | if (rec->flags & FTRACE_FL_FREE) |
1085 | * failed and not converted. | ||
1086 | */ | ||
1087 | if (rec->flags & FTRACE_FL_FREE || | ||
1088 | rec->flags & FTRACE_FL_FAILED || | ||
1089 | !(rec->flags & FTRACE_FL_CONVERTED)) | ||
1090 | continue; | 1065 | continue; |
1091 | 1066 | ||
1092 | failed = __ftrace_replace_code(rec, enable); | 1067 | failed = __ftrace_replace_code(rec, enable); |
1093 | if (failed) { | 1068 | if (failed) { |
1094 | rec->flags |= FTRACE_FL_FAILED; | ||
1095 | ftrace_bug(failed, rec->ip); | 1069 | ftrace_bug(failed, rec->ip); |
1096 | /* Stop processing */ | 1070 | /* Stop processing */ |
1097 | return; | 1071 | return; |
@@ -1107,10 +1081,12 @@ ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec) | |||
1107 | 1081 | ||
1108 | ip = rec->ip; | 1082 | ip = rec->ip; |
1109 | 1083 | ||
1084 | if (unlikely(ftrace_disabled)) | ||
1085 | return 0; | ||
1086 | |||
1110 | ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR); | 1087 | ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR); |
1111 | if (ret) { | 1088 | if (ret) { |
1112 | ftrace_bug(ret, ip); | 1089 | ftrace_bug(ret, ip); |
1113 | rec->flags |= FTRACE_FL_FAILED; | ||
1114 | return 0; | 1090 | return 0; |
1115 | } | 1091 | } |
1116 | return 1; | 1092 | return 1; |
@@ -1273,10 +1249,10 @@ static int ftrace_update_code(struct module *mod) | |||
1273 | */ | 1249 | */ |
1274 | if (!ftrace_code_disable(mod, p)) { | 1250 | if (!ftrace_code_disable(mod, p)) { |
1275 | ftrace_free_rec(p); | 1251 | ftrace_free_rec(p); |
1276 | continue; | 1252 | /* Game over */ |
1253 | break; | ||
1277 | } | 1254 | } |
1278 | 1255 | ||
1279 | p->flags |= FTRACE_FL_CONVERTED; | ||
1280 | ftrace_update_cnt++; | 1256 | ftrace_update_cnt++; |
1281 | 1257 | ||
1282 | /* | 1258 | /* |
@@ -1351,9 +1327,8 @@ static int __init ftrace_dyn_table_alloc(unsigned long num_to_init) | |||
1351 | enum { | 1327 | enum { |
1352 | FTRACE_ITER_FILTER = (1 << 0), | 1328 | FTRACE_ITER_FILTER = (1 << 0), |
1353 | FTRACE_ITER_NOTRACE = (1 << 1), | 1329 | FTRACE_ITER_NOTRACE = (1 << 1), |
1354 | FTRACE_ITER_FAILURES = (1 << 2), | 1330 | FTRACE_ITER_PRINTALL = (1 << 2), |
1355 | FTRACE_ITER_PRINTALL = (1 << 3), | 1331 | FTRACE_ITER_HASH = (1 << 3), |
1356 | FTRACE_ITER_HASH = (1 << 4), | ||
1357 | }; | 1332 | }; |
1358 | 1333 | ||
1359 | #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ | 1334 | #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ |
@@ -1463,6 +1438,9 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
1463 | struct ftrace_iterator *iter = m->private; | 1438 | struct ftrace_iterator *iter = m->private; |
1464 | struct dyn_ftrace *rec = NULL; | 1439 | struct dyn_ftrace *rec = NULL; |
1465 | 1440 | ||
1441 | if (unlikely(ftrace_disabled)) | ||
1442 | return NULL; | ||
1443 | |||
1466 | if (iter->flags & FTRACE_ITER_HASH) | 1444 | if (iter->flags & FTRACE_ITER_HASH) |
1467 | return t_hash_next(m, pos); | 1445 | return t_hash_next(m, pos); |
1468 | 1446 | ||
@@ -1483,12 +1461,6 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
1483 | rec = &iter->pg->records[iter->idx++]; | 1461 | rec = &iter->pg->records[iter->idx++]; |
1484 | if ((rec->flags & FTRACE_FL_FREE) || | 1462 | if ((rec->flags & FTRACE_FL_FREE) || |
1485 | 1463 | ||
1486 | (!(iter->flags & FTRACE_ITER_FAILURES) && | ||
1487 | (rec->flags & FTRACE_FL_FAILED)) || | ||
1488 | |||
1489 | ((iter->flags & FTRACE_ITER_FAILURES) && | ||
1490 | !(rec->flags & FTRACE_FL_FAILED)) || | ||
1491 | |||
1492 | ((iter->flags & FTRACE_ITER_FILTER) && | 1464 | ((iter->flags & FTRACE_ITER_FILTER) && |
1493 | !(rec->flags & FTRACE_FL_FILTER)) || | 1465 | !(rec->flags & FTRACE_FL_FILTER)) || |
1494 | 1466 | ||
@@ -1521,6 +1493,10 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
1521 | loff_t l; | 1493 | loff_t l; |
1522 | 1494 | ||
1523 | mutex_lock(&ftrace_lock); | 1495 | mutex_lock(&ftrace_lock); |
1496 | |||
1497 | if (unlikely(ftrace_disabled)) | ||
1498 | return NULL; | ||
1499 | |||
1524 | /* | 1500 | /* |
1525 | * If an lseek was done, then reset and start from beginning. | 1501 | * If an lseek was done, then reset and start from beginning. |
1526 | */ | 1502 | */ |
@@ -1629,24 +1605,6 @@ ftrace_avail_open(struct inode *inode, struct file *file) | |||
1629 | return ret; | 1605 | return ret; |
1630 | } | 1606 | } |
1631 | 1607 | ||
1632 | static int | ||
1633 | ftrace_failures_open(struct inode *inode, struct file *file) | ||
1634 | { | ||
1635 | int ret; | ||
1636 | struct seq_file *m; | ||
1637 | struct ftrace_iterator *iter; | ||
1638 | |||
1639 | ret = ftrace_avail_open(inode, file); | ||
1640 | if (!ret) { | ||
1641 | m = file->private_data; | ||
1642 | iter = m->private; | ||
1643 | iter->flags = FTRACE_ITER_FAILURES; | ||
1644 | } | ||
1645 | |||
1646 | return ret; | ||
1647 | } | ||
1648 | |||
1649 | |||
1650 | static void ftrace_filter_reset(int enable) | 1608 | static void ftrace_filter_reset(int enable) |
1651 | { | 1609 | { |
1652 | struct ftrace_page *pg; | 1610 | struct ftrace_page *pg; |
@@ -1657,8 +1615,6 @@ static void ftrace_filter_reset(int enable) | |||
1657 | if (enable) | 1615 | if (enable) |
1658 | ftrace_filtered = 0; | 1616 | ftrace_filtered = 0; |
1659 | do_for_each_ftrace_rec(pg, rec) { | 1617 | do_for_each_ftrace_rec(pg, rec) { |
1660 | if (rec->flags & FTRACE_FL_FAILED) | ||
1661 | continue; | ||
1662 | rec->flags &= ~type; | 1618 | rec->flags &= ~type; |
1663 | } while_for_each_ftrace_rec(); | 1619 | } while_for_each_ftrace_rec(); |
1664 | mutex_unlock(&ftrace_lock); | 1620 | mutex_unlock(&ftrace_lock); |
@@ -1760,42 +1716,63 @@ static int ftrace_match(char *str, char *regex, int len, int type) | |||
1760 | return matched; | 1716 | return matched; |
1761 | } | 1717 | } |
1762 | 1718 | ||
1719 | static void | ||
1720 | update_record(struct dyn_ftrace *rec, unsigned long flag, int not) | ||
1721 | { | ||
1722 | if (not) | ||
1723 | rec->flags &= ~flag; | ||
1724 | else | ||
1725 | rec->flags |= flag; | ||
1726 | } | ||
1727 | |||
1763 | static int | 1728 | static int |
1764 | ftrace_match_record(struct dyn_ftrace *rec, char *regex, int len, int type) | 1729 | ftrace_match_record(struct dyn_ftrace *rec, char *mod, |
1730 | char *regex, int len, int type) | ||
1765 | { | 1731 | { |
1766 | char str[KSYM_SYMBOL_LEN]; | 1732 | char str[KSYM_SYMBOL_LEN]; |
1733 | char *modname; | ||
1734 | |||
1735 | kallsyms_lookup(rec->ip, NULL, NULL, &modname, str); | ||
1736 | |||
1737 | if (mod) { | ||
1738 | /* module lookup requires matching the module */ | ||
1739 | if (!modname || strcmp(modname, mod)) | ||
1740 | return 0; | ||
1741 | |||
1742 | /* blank search means to match all funcs in the mod */ | ||
1743 | if (!len) | ||
1744 | return 1; | ||
1745 | } | ||
1767 | 1746 | ||
1768 | kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); | ||
1769 | return ftrace_match(str, regex, len, type); | 1747 | return ftrace_match(str, regex, len, type); |
1770 | } | 1748 | } |
1771 | 1749 | ||
1772 | static int ftrace_match_records(char *buff, int len, int enable) | 1750 | static int match_records(char *buff, int len, char *mod, int enable, int not) |
1773 | { | 1751 | { |
1774 | unsigned int search_len; | 1752 | unsigned search_len = 0; |
1775 | struct ftrace_page *pg; | 1753 | struct ftrace_page *pg; |
1776 | struct dyn_ftrace *rec; | 1754 | struct dyn_ftrace *rec; |
1755 | int type = MATCH_FULL; | ||
1756 | char *search = buff; | ||
1777 | unsigned long flag; | 1757 | unsigned long flag; |
1778 | char *search; | ||
1779 | int type; | ||
1780 | int not; | ||
1781 | int found = 0; | 1758 | int found = 0; |
1782 | 1759 | ||
1783 | flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; | 1760 | if (len) { |
1784 | type = filter_parse_regex(buff, len, &search, ¬); | 1761 | type = filter_parse_regex(buff, len, &search, ¬); |
1762 | search_len = strlen(search); | ||
1763 | } | ||
1785 | 1764 | ||
1786 | search_len = strlen(search); | 1765 | flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; |
1787 | 1766 | ||
1788 | mutex_lock(&ftrace_lock); | 1767 | mutex_lock(&ftrace_lock); |
1789 | do_for_each_ftrace_rec(pg, rec) { | ||
1790 | 1768 | ||
1791 | if (rec->flags & FTRACE_FL_FAILED) | 1769 | if (unlikely(ftrace_disabled)) |
1792 | continue; | 1770 | goto out_unlock; |
1793 | 1771 | ||
1794 | if (ftrace_match_record(rec, search, search_len, type)) { | 1772 | do_for_each_ftrace_rec(pg, rec) { |
1795 | if (not) | 1773 | |
1796 | rec->flags &= ~flag; | 1774 | if (ftrace_match_record(rec, mod, search, search_len, type)) { |
1797 | else | 1775 | update_record(rec, flag, not); |
1798 | rec->flags |= flag; | ||
1799 | found = 1; | 1776 | found = 1; |
1800 | } | 1777 | } |
1801 | /* | 1778 | /* |
@@ -1804,43 +1781,23 @@ static int ftrace_match_records(char *buff, int len, int enable) | |||
1804 | */ | 1781 | */ |
1805 | if (enable && (rec->flags & FTRACE_FL_FILTER)) | 1782 | if (enable && (rec->flags & FTRACE_FL_FILTER)) |
1806 | ftrace_filtered = 1; | 1783 | ftrace_filtered = 1; |
1784 | |||
1807 | } while_for_each_ftrace_rec(); | 1785 | } while_for_each_ftrace_rec(); |
1786 | out_unlock: | ||
1808 | mutex_unlock(&ftrace_lock); | 1787 | mutex_unlock(&ftrace_lock); |
1809 | 1788 | ||
1810 | return found; | 1789 | return found; |
1811 | } | 1790 | } |
1812 | 1791 | ||
1813 | static int | 1792 | static int |
1814 | ftrace_match_module_record(struct dyn_ftrace *rec, char *mod, | 1793 | ftrace_match_records(char *buff, int len, int enable) |
1815 | char *regex, int len, int type) | ||
1816 | { | 1794 | { |
1817 | char str[KSYM_SYMBOL_LEN]; | 1795 | return match_records(buff, len, NULL, enable, 0); |
1818 | char *modname; | ||
1819 | |||
1820 | kallsyms_lookup(rec->ip, NULL, NULL, &modname, str); | ||
1821 | |||
1822 | if (!modname || strcmp(modname, mod)) | ||
1823 | return 0; | ||
1824 | |||
1825 | /* blank search means to match all funcs in the mod */ | ||
1826 | if (len) | ||
1827 | return ftrace_match(str, regex, len, type); | ||
1828 | else | ||
1829 | return 1; | ||
1830 | } | 1796 | } |
1831 | 1797 | ||
1832 | static int ftrace_match_module_records(char *buff, char *mod, int enable) | 1798 | static int ftrace_match_module_records(char *buff, char *mod, int enable) |
1833 | { | 1799 | { |
1834 | unsigned search_len = 0; | ||
1835 | struct ftrace_page *pg; | ||
1836 | struct dyn_ftrace *rec; | ||
1837 | int type = MATCH_FULL; | ||
1838 | char *search = buff; | ||
1839 | unsigned long flag; | ||
1840 | int not = 0; | 1800 | int not = 0; |
1841 | int found = 0; | ||
1842 | |||
1843 | flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; | ||
1844 | 1801 | ||
1845 | /* blank or '*' mean the same */ | 1802 | /* blank or '*' mean the same */ |
1846 | if (strcmp(buff, "*") == 0) | 1803 | if (strcmp(buff, "*") == 0) |
@@ -1852,32 +1809,7 @@ static int ftrace_match_module_records(char *buff, char *mod, int enable) | |||
1852 | not = 1; | 1809 | not = 1; |
1853 | } | 1810 | } |
1854 | 1811 | ||
1855 | if (strlen(buff)) { | 1812 | return match_records(buff, strlen(buff), mod, enable, not); |
1856 | type = filter_parse_regex(buff, strlen(buff), &search, ¬); | ||
1857 | search_len = strlen(search); | ||
1858 | } | ||
1859 | |||
1860 | mutex_lock(&ftrace_lock); | ||
1861 | do_for_each_ftrace_rec(pg, rec) { | ||
1862 | |||
1863 | if (rec->flags & FTRACE_FL_FAILED) | ||
1864 | continue; | ||
1865 | |||
1866 | if (ftrace_match_module_record(rec, mod, | ||
1867 | search, search_len, type)) { | ||
1868 | if (not) | ||
1869 | rec->flags &= ~flag; | ||
1870 | else | ||
1871 | rec->flags |= flag; | ||
1872 | found = 1; | ||
1873 | } | ||
1874 | if (enable && (rec->flags & FTRACE_FL_FILTER)) | ||
1875 | ftrace_filtered = 1; | ||
1876 | |||
1877 | } while_for_each_ftrace_rec(); | ||
1878 | mutex_unlock(&ftrace_lock); | ||
1879 | |||
1880 | return found; | ||
1881 | } | 1813 | } |
1882 | 1814 | ||
1883 | /* | 1815 | /* |
@@ -2029,12 +1961,13 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
2029 | return -EINVAL; | 1961 | return -EINVAL; |
2030 | 1962 | ||
2031 | mutex_lock(&ftrace_lock); | 1963 | mutex_lock(&ftrace_lock); |
2032 | do_for_each_ftrace_rec(pg, rec) { | ||
2033 | 1964 | ||
2034 | if (rec->flags & FTRACE_FL_FAILED) | 1965 | if (unlikely(ftrace_disabled)) |
2035 | continue; | 1966 | goto out_unlock; |
2036 | 1967 | ||
2037 | if (!ftrace_match_record(rec, search, len, type)) | 1968 | do_for_each_ftrace_rec(pg, rec) { |
1969 | |||
1970 | if (!ftrace_match_record(rec, NULL, search, len, type)) | ||
2038 | continue; | 1971 | continue; |
2039 | 1972 | ||
2040 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | 1973 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
@@ -2239,6 +2172,10 @@ ftrace_regex_write(struct file *file, const char __user *ubuf, | |||
2239 | 2172 | ||
2240 | mutex_lock(&ftrace_regex_lock); | 2173 | mutex_lock(&ftrace_regex_lock); |
2241 | 2174 | ||
2175 | ret = -ENODEV; | ||
2176 | if (unlikely(ftrace_disabled)) | ||
2177 | goto out_unlock; | ||
2178 | |||
2242 | if (file->f_mode & FMODE_READ) { | 2179 | if (file->f_mode & FMODE_READ) { |
2243 | struct seq_file *m = file->private_data; | 2180 | struct seq_file *m = file->private_data; |
2244 | iter = m->private; | 2181 | iter = m->private; |
@@ -2446,13 +2383,6 @@ static const struct file_operations ftrace_avail_fops = { | |||
2446 | .release = seq_release_private, | 2383 | .release = seq_release_private, |
2447 | }; | 2384 | }; |
2448 | 2385 | ||
2449 | static const struct file_operations ftrace_failures_fops = { | ||
2450 | .open = ftrace_failures_open, | ||
2451 | .read = seq_read, | ||
2452 | .llseek = seq_lseek, | ||
2453 | .release = seq_release_private, | ||
2454 | }; | ||
2455 | |||
2456 | static const struct file_operations ftrace_filter_fops = { | 2386 | static const struct file_operations ftrace_filter_fops = { |
2457 | .open = ftrace_filter_open, | 2387 | .open = ftrace_filter_open, |
2458 | .read = seq_read, | 2388 | .read = seq_read, |
@@ -2575,9 +2505,6 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer) | |||
2575 | bool exists; | 2505 | bool exists; |
2576 | int i; | 2506 | int i; |
2577 | 2507 | ||
2578 | if (ftrace_disabled) | ||
2579 | return -ENODEV; | ||
2580 | |||
2581 | /* decode regex */ | 2508 | /* decode regex */ |
2582 | type = filter_parse_regex(buffer, strlen(buffer), &search, ¬); | 2509 | type = filter_parse_regex(buffer, strlen(buffer), &search, ¬); |
2583 | if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS) | 2510 | if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS) |
@@ -2586,12 +2513,18 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer) | |||
2586 | search_len = strlen(search); | 2513 | search_len = strlen(search); |
2587 | 2514 | ||
2588 | mutex_lock(&ftrace_lock); | 2515 | mutex_lock(&ftrace_lock); |
2516 | |||
2517 | if (unlikely(ftrace_disabled)) { | ||
2518 | mutex_unlock(&ftrace_lock); | ||
2519 | return -ENODEV; | ||
2520 | } | ||
2521 | |||
2589 | do_for_each_ftrace_rec(pg, rec) { | 2522 | do_for_each_ftrace_rec(pg, rec) { |
2590 | 2523 | ||
2591 | if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE)) | 2524 | if (rec->flags & FTRACE_FL_FREE) |
2592 | continue; | 2525 | continue; |
2593 | 2526 | ||
2594 | if (ftrace_match_record(rec, search, search_len, type)) { | 2527 | if (ftrace_match_record(rec, NULL, search, search_len, type)) { |
2595 | /* if it is in the array */ | 2528 | /* if it is in the array */ |
2596 | exists = false; | 2529 | exists = false; |
2597 | for (i = 0; i < *idx; i++) { | 2530 | for (i = 0; i < *idx; i++) { |
@@ -2681,9 +2614,6 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer) | |||
2681 | trace_create_file("available_filter_functions", 0444, | 2614 | trace_create_file("available_filter_functions", 0444, |
2682 | d_tracer, NULL, &ftrace_avail_fops); | 2615 | d_tracer, NULL, &ftrace_avail_fops); |
2683 | 2616 | ||
2684 | trace_create_file("failures", 0444, | ||
2685 | d_tracer, NULL, &ftrace_failures_fops); | ||
2686 | |||
2687 | trace_create_file("set_ftrace_filter", 0644, d_tracer, | 2617 | trace_create_file("set_ftrace_filter", 0644, d_tracer, |
2688 | NULL, &ftrace_filter_fops); | 2618 | NULL, &ftrace_filter_fops); |
2689 | 2619 | ||
@@ -2705,7 +2635,6 @@ static int ftrace_process_locs(struct module *mod, | |||
2705 | { | 2635 | { |
2706 | unsigned long *p; | 2636 | unsigned long *p; |
2707 | unsigned long addr; | 2637 | unsigned long addr; |
2708 | unsigned long flags; | ||
2709 | 2638 | ||
2710 | mutex_lock(&ftrace_lock); | 2639 | mutex_lock(&ftrace_lock); |
2711 | p = start; | 2640 | p = start; |
@@ -2722,10 +2651,7 @@ static int ftrace_process_locs(struct module *mod, | |||
2722 | ftrace_record_ip(addr); | 2651 | ftrace_record_ip(addr); |
2723 | } | 2652 | } |
2724 | 2653 | ||
2725 | /* disable interrupts to prevent kstop machine */ | ||
2726 | local_irq_save(flags); | ||
2727 | ftrace_update_code(mod); | 2654 | ftrace_update_code(mod); |
2728 | local_irq_restore(flags); | ||
2729 | mutex_unlock(&ftrace_lock); | 2655 | mutex_unlock(&ftrace_lock); |
2730 | 2656 | ||
2731 | return 0; | 2657 | return 0; |
@@ -2737,10 +2663,11 @@ void ftrace_release_mod(struct module *mod) | |||
2737 | struct dyn_ftrace *rec; | 2663 | struct dyn_ftrace *rec; |
2738 | struct ftrace_page *pg; | 2664 | struct ftrace_page *pg; |
2739 | 2665 | ||
2666 | mutex_lock(&ftrace_lock); | ||
2667 | |||
2740 | if (ftrace_disabled) | 2668 | if (ftrace_disabled) |
2741 | return; | 2669 | goto out_unlock; |
2742 | 2670 | ||
2743 | mutex_lock(&ftrace_lock); | ||
2744 | do_for_each_ftrace_rec(pg, rec) { | 2671 | do_for_each_ftrace_rec(pg, rec) { |
2745 | if (within_module_core(rec->ip, mod)) { | 2672 | if (within_module_core(rec->ip, mod)) { |
2746 | /* | 2673 | /* |
@@ -2751,6 +2678,7 @@ void ftrace_release_mod(struct module *mod) | |||
2751 | ftrace_free_rec(rec); | 2678 | ftrace_free_rec(rec); |
2752 | } | 2679 | } |
2753 | } while_for_each_ftrace_rec(); | 2680 | } while_for_each_ftrace_rec(); |
2681 | out_unlock: | ||
2754 | mutex_unlock(&ftrace_lock); | 2682 | mutex_unlock(&ftrace_lock); |
2755 | } | 2683 | } |
2756 | 2684 | ||
@@ -3145,16 +3073,17 @@ void ftrace_kill(void) | |||
3145 | */ | 3073 | */ |
3146 | int register_ftrace_function(struct ftrace_ops *ops) | 3074 | int register_ftrace_function(struct ftrace_ops *ops) |
3147 | { | 3075 | { |
3148 | int ret; | 3076 | int ret = -1; |
3149 | |||
3150 | if (unlikely(ftrace_disabled)) | ||
3151 | return -1; | ||
3152 | 3077 | ||
3153 | mutex_lock(&ftrace_lock); | 3078 | mutex_lock(&ftrace_lock); |
3154 | 3079 | ||
3080 | if (unlikely(ftrace_disabled)) | ||
3081 | goto out_unlock; | ||
3082 | |||
3155 | ret = __register_ftrace_function(ops); | 3083 | ret = __register_ftrace_function(ops); |
3156 | ftrace_startup(0); | 3084 | ftrace_startup(0); |
3157 | 3085 | ||
3086 | out_unlock: | ||
3158 | mutex_unlock(&ftrace_lock); | 3087 | mutex_unlock(&ftrace_lock); |
3159 | return ret; | 3088 | return ret; |
3160 | } | 3089 | } |
@@ -3182,14 +3111,14 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, | |||
3182 | void __user *buffer, size_t *lenp, | 3111 | void __user *buffer, size_t *lenp, |
3183 | loff_t *ppos) | 3112 | loff_t *ppos) |
3184 | { | 3113 | { |
3185 | int ret; | 3114 | int ret = -ENODEV; |
3186 | |||
3187 | if (unlikely(ftrace_disabled)) | ||
3188 | return -ENODEV; | ||
3189 | 3115 | ||
3190 | mutex_lock(&ftrace_lock); | 3116 | mutex_lock(&ftrace_lock); |
3191 | 3117 | ||
3192 | ret = proc_dointvec(table, write, buffer, lenp, ppos); | 3118 | if (unlikely(ftrace_disabled)) |
3119 | goto out; | ||
3120 | |||
3121 | ret = proc_dointvec(table, write, buffer, lenp, ppos); | ||
3193 | 3122 | ||
3194 | if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) | 3123 | if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) |
3195 | goto out; | 3124 | goto out; |