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 666880d051e..d3406346ced 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; |
