diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/ftrace.c | 359 | ||||
-rw-r--r-- | kernel/trace/trace.c | 15 | ||||
-rw-r--r-- | kernel/trace/trace_output.c | 3 | ||||
-rw-r--r-- | kernel/trace/trace_printk.c | 120 |
4 files changed, 268 insertions, 229 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index ee24fa1935ac..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; |
@@ -2413,14 +2350,16 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable) | |||
2413 | ftrace_match_records(parser->buffer, parser->idx, enable); | 2350 | ftrace_match_records(parser->buffer, parser->idx, enable); |
2414 | } | 2351 | } |
2415 | 2352 | ||
2416 | mutex_lock(&ftrace_lock); | ||
2417 | if (ftrace_start_up && ftrace_enabled) | ||
2418 | ftrace_run_update_code(FTRACE_ENABLE_CALLS); | ||
2419 | mutex_unlock(&ftrace_lock); | ||
2420 | |||
2421 | trace_parser_put(parser); | 2353 | trace_parser_put(parser); |
2422 | kfree(iter); | 2354 | kfree(iter); |
2423 | 2355 | ||
2356 | if (file->f_mode & FMODE_WRITE) { | ||
2357 | mutex_lock(&ftrace_lock); | ||
2358 | if (ftrace_start_up && ftrace_enabled) | ||
2359 | ftrace_run_update_code(FTRACE_ENABLE_CALLS); | ||
2360 | mutex_unlock(&ftrace_lock); | ||
2361 | } | ||
2362 | |||
2424 | mutex_unlock(&ftrace_regex_lock); | 2363 | mutex_unlock(&ftrace_regex_lock); |
2425 | return 0; | 2364 | return 0; |
2426 | } | 2365 | } |
@@ -2444,13 +2383,6 @@ static const struct file_operations ftrace_avail_fops = { | |||
2444 | .release = seq_release_private, | 2383 | .release = seq_release_private, |
2445 | }; | 2384 | }; |
2446 | 2385 | ||
2447 | static const struct file_operations ftrace_failures_fops = { | ||
2448 | .open = ftrace_failures_open, | ||
2449 | .read = seq_read, | ||
2450 | .llseek = seq_lseek, | ||
2451 | .release = seq_release_private, | ||
2452 | }; | ||
2453 | |||
2454 | static const struct file_operations ftrace_filter_fops = { | 2386 | static const struct file_operations ftrace_filter_fops = { |
2455 | .open = ftrace_filter_open, | 2387 | .open = ftrace_filter_open, |
2456 | .read = seq_read, | 2388 | .read = seq_read, |
@@ -2573,9 +2505,6 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer) | |||
2573 | bool exists; | 2505 | bool exists; |
2574 | int i; | 2506 | int i; |
2575 | 2507 | ||
2576 | if (ftrace_disabled) | ||
2577 | return -ENODEV; | ||
2578 | |||
2579 | /* decode regex */ | 2508 | /* decode regex */ |
2580 | type = filter_parse_regex(buffer, strlen(buffer), &search, ¬); | 2509 | type = filter_parse_regex(buffer, strlen(buffer), &search, ¬); |
2581 | if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS) | 2510 | if (!not && *idx >= FTRACE_GRAPH_MAX_FUNCS) |
@@ -2584,12 +2513,18 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer) | |||
2584 | search_len = strlen(search); | 2513 | search_len = strlen(search); |
2585 | 2514 | ||
2586 | 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 | |||
2587 | do_for_each_ftrace_rec(pg, rec) { | 2522 | do_for_each_ftrace_rec(pg, rec) { |
2588 | 2523 | ||
2589 | if (rec->flags & (FTRACE_FL_FAILED | FTRACE_FL_FREE)) | 2524 | if (rec->flags & FTRACE_FL_FREE) |
2590 | continue; | 2525 | continue; |
2591 | 2526 | ||
2592 | if (ftrace_match_record(rec, search, search_len, type)) { | 2527 | if (ftrace_match_record(rec, NULL, search, search_len, type)) { |
2593 | /* if it is in the array */ | 2528 | /* if it is in the array */ |
2594 | exists = false; | 2529 | exists = false; |
2595 | for (i = 0; i < *idx; i++) { | 2530 | for (i = 0; i < *idx; i++) { |
@@ -2679,9 +2614,6 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer) | |||
2679 | trace_create_file("available_filter_functions", 0444, | 2614 | trace_create_file("available_filter_functions", 0444, |
2680 | d_tracer, NULL, &ftrace_avail_fops); | 2615 | d_tracer, NULL, &ftrace_avail_fops); |
2681 | 2616 | ||
2682 | trace_create_file("failures", 0444, | ||
2683 | d_tracer, NULL, &ftrace_failures_fops); | ||
2684 | |||
2685 | trace_create_file("set_ftrace_filter", 0644, d_tracer, | 2617 | trace_create_file("set_ftrace_filter", 0644, d_tracer, |
2686 | NULL, &ftrace_filter_fops); | 2618 | NULL, &ftrace_filter_fops); |
2687 | 2619 | ||
@@ -2703,7 +2635,6 @@ static int ftrace_process_locs(struct module *mod, | |||
2703 | { | 2635 | { |
2704 | unsigned long *p; | 2636 | unsigned long *p; |
2705 | unsigned long addr; | 2637 | unsigned long addr; |
2706 | unsigned long flags; | ||
2707 | 2638 | ||
2708 | mutex_lock(&ftrace_lock); | 2639 | mutex_lock(&ftrace_lock); |
2709 | p = start; | 2640 | p = start; |
@@ -2720,10 +2651,7 @@ static int ftrace_process_locs(struct module *mod, | |||
2720 | ftrace_record_ip(addr); | 2651 | ftrace_record_ip(addr); |
2721 | } | 2652 | } |
2722 | 2653 | ||
2723 | /* disable interrupts to prevent kstop machine */ | ||
2724 | local_irq_save(flags); | ||
2725 | ftrace_update_code(mod); | 2654 | ftrace_update_code(mod); |
2726 | local_irq_restore(flags); | ||
2727 | mutex_unlock(&ftrace_lock); | 2655 | mutex_unlock(&ftrace_lock); |
2728 | 2656 | ||
2729 | return 0; | 2657 | return 0; |
@@ -2735,10 +2663,11 @@ void ftrace_release_mod(struct module *mod) | |||
2735 | struct dyn_ftrace *rec; | 2663 | struct dyn_ftrace *rec; |
2736 | struct ftrace_page *pg; | 2664 | struct ftrace_page *pg; |
2737 | 2665 | ||
2666 | mutex_lock(&ftrace_lock); | ||
2667 | |||
2738 | if (ftrace_disabled) | 2668 | if (ftrace_disabled) |
2739 | return; | 2669 | goto out_unlock; |
2740 | 2670 | ||
2741 | mutex_lock(&ftrace_lock); | ||
2742 | do_for_each_ftrace_rec(pg, rec) { | 2671 | do_for_each_ftrace_rec(pg, rec) { |
2743 | if (within_module_core(rec->ip, mod)) { | 2672 | if (within_module_core(rec->ip, mod)) { |
2744 | /* | 2673 | /* |
@@ -2749,6 +2678,7 @@ void ftrace_release_mod(struct module *mod) | |||
2749 | ftrace_free_rec(rec); | 2678 | ftrace_free_rec(rec); |
2750 | } | 2679 | } |
2751 | } while_for_each_ftrace_rec(); | 2680 | } while_for_each_ftrace_rec(); |
2681 | out_unlock: | ||
2752 | mutex_unlock(&ftrace_lock); | 2682 | mutex_unlock(&ftrace_lock); |
2753 | } | 2683 | } |
2754 | 2684 | ||
@@ -3143,16 +3073,17 @@ void ftrace_kill(void) | |||
3143 | */ | 3073 | */ |
3144 | int register_ftrace_function(struct ftrace_ops *ops) | 3074 | int register_ftrace_function(struct ftrace_ops *ops) |
3145 | { | 3075 | { |
3146 | int ret; | 3076 | int ret = -1; |
3147 | |||
3148 | if (unlikely(ftrace_disabled)) | ||
3149 | return -1; | ||
3150 | 3077 | ||
3151 | mutex_lock(&ftrace_lock); | 3078 | mutex_lock(&ftrace_lock); |
3152 | 3079 | ||
3080 | if (unlikely(ftrace_disabled)) | ||
3081 | goto out_unlock; | ||
3082 | |||
3153 | ret = __register_ftrace_function(ops); | 3083 | ret = __register_ftrace_function(ops); |
3154 | ftrace_startup(0); | 3084 | ftrace_startup(0); |
3155 | 3085 | ||
3086 | out_unlock: | ||
3156 | mutex_unlock(&ftrace_lock); | 3087 | mutex_unlock(&ftrace_lock); |
3157 | return ret; | 3088 | return ret; |
3158 | } | 3089 | } |
@@ -3180,14 +3111,14 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, | |||
3180 | void __user *buffer, size_t *lenp, | 3111 | void __user *buffer, size_t *lenp, |
3181 | loff_t *ppos) | 3112 | loff_t *ppos) |
3182 | { | 3113 | { |
3183 | int ret; | 3114 | int ret = -ENODEV; |
3184 | |||
3185 | if (unlikely(ftrace_disabled)) | ||
3186 | return -ENODEV; | ||
3187 | 3115 | ||
3188 | mutex_lock(&ftrace_lock); | 3116 | mutex_lock(&ftrace_lock); |
3189 | 3117 | ||
3190 | 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); | ||
3191 | 3122 | ||
3192 | if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) | 3123 | if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled)) |
3193 | goto out; | 3124 | goto out; |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 1cb49be7c7fb..ee9c921d7f21 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -2014,9 +2014,10 @@ enum print_line_t print_trace_line(struct trace_iterator *iter) | |||
2014 | { | 2014 | { |
2015 | enum print_line_t ret; | 2015 | enum print_line_t ret; |
2016 | 2016 | ||
2017 | if (iter->lost_events) | 2017 | if (iter->lost_events && |
2018 | trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", | 2018 | !trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", |
2019 | iter->cpu, iter->lost_events); | 2019 | iter->cpu, iter->lost_events)) |
2020 | return TRACE_TYPE_PARTIAL_LINE; | ||
2020 | 2021 | ||
2021 | if (iter->trace && iter->trace->print_line) { | 2022 | if (iter->trace && iter->trace->print_line) { |
2022 | ret = iter->trace->print_line(iter); | 2023 | ret = iter->trace->print_line(iter); |
@@ -3230,6 +3231,14 @@ waitagain: | |||
3230 | 3231 | ||
3231 | if (iter->seq.len >= cnt) | 3232 | if (iter->seq.len >= cnt) |
3232 | break; | 3233 | break; |
3234 | |||
3235 | /* | ||
3236 | * Setting the full flag means we reached the trace_seq buffer | ||
3237 | * size and we should leave by partial output condition above. | ||
3238 | * One of the trace_seq_* functions is not used properly. | ||
3239 | */ | ||
3240 | WARN_ONCE(iter->seq.full, "full flag set for trace type %d", | ||
3241 | iter->ent->type); | ||
3233 | } | 3242 | } |
3234 | trace_access_unlock(iter->cpu_file); | 3243 | trace_access_unlock(iter->cpu_file); |
3235 | trace_event_read_unlock(); | 3244 | trace_event_read_unlock(); |
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 456be9063c2d..cf535ccedc86 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c | |||
@@ -830,6 +830,9 @@ EXPORT_SYMBOL_GPL(unregister_ftrace_event); | |||
830 | enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags, | 830 | enum print_line_t trace_nop_print(struct trace_iterator *iter, int flags, |
831 | struct trace_event *event) | 831 | struct trace_event *event) |
832 | { | 832 | { |
833 | if (!trace_seq_printf(&iter->seq, "type: %d\n", iter->ent->type)) | ||
834 | return TRACE_TYPE_PARTIAL_LINE; | ||
835 | |||
833 | return TRACE_TYPE_HANDLED; | 836 | return TRACE_TYPE_HANDLED; |
834 | } | 837 | } |
835 | 838 | ||
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index 2547d8813cf0..dff763b7baf1 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c | |||
@@ -32,7 +32,7 @@ static DEFINE_MUTEX(btrace_mutex); | |||
32 | 32 | ||
33 | struct trace_bprintk_fmt { | 33 | struct trace_bprintk_fmt { |
34 | struct list_head list; | 34 | struct list_head list; |
35 | char fmt[0]; | 35 | const char *fmt; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) | 38 | static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) |
@@ -49,6 +49,7 @@ static | |||
49 | void hold_module_trace_bprintk_format(const char **start, const char **end) | 49 | void hold_module_trace_bprintk_format(const char **start, const char **end) |
50 | { | 50 | { |
51 | const char **iter; | 51 | const char **iter; |
52 | char *fmt; | ||
52 | 53 | ||
53 | mutex_lock(&btrace_mutex); | 54 | mutex_lock(&btrace_mutex); |
54 | for (iter = start; iter < end; iter++) { | 55 | for (iter = start; iter < end; iter++) { |
@@ -58,14 +59,18 @@ void hold_module_trace_bprintk_format(const char **start, const char **end) | |||
58 | continue; | 59 | continue; |
59 | } | 60 | } |
60 | 61 | ||
61 | tb_fmt = kmalloc(offsetof(struct trace_bprintk_fmt, fmt) | 62 | tb_fmt = kmalloc(sizeof(*tb_fmt), GFP_KERNEL); |
62 | + strlen(*iter) + 1, GFP_KERNEL); | 63 | if (tb_fmt) |
63 | if (tb_fmt) { | 64 | fmt = kmalloc(strlen(*iter) + 1, GFP_KERNEL); |
65 | if (tb_fmt && fmt) { | ||
64 | list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list); | 66 | list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list); |
65 | strcpy(tb_fmt->fmt, *iter); | 67 | strcpy(fmt, *iter); |
68 | tb_fmt->fmt = fmt; | ||
66 | *iter = tb_fmt->fmt; | 69 | *iter = tb_fmt->fmt; |
67 | } else | 70 | } else { |
71 | kfree(tb_fmt); | ||
68 | *iter = NULL; | 72 | *iter = NULL; |
73 | } | ||
69 | } | 74 | } |
70 | mutex_unlock(&btrace_mutex); | 75 | mutex_unlock(&btrace_mutex); |
71 | } | 76 | } |
@@ -84,6 +89,76 @@ static int module_trace_bprintk_format_notify(struct notifier_block *self, | |||
84 | return 0; | 89 | return 0; |
85 | } | 90 | } |
86 | 91 | ||
92 | /* | ||
93 | * The debugfs/tracing/printk_formats file maps the addresses with | ||
94 | * the ASCII formats that are used in the bprintk events in the | ||
95 | * buffer. For userspace tools to be able to decode the events from | ||
96 | * the buffer, they need to be able to map the address with the format. | ||
97 | * | ||
98 | * The addresses of the bprintk formats are in their own section | ||
99 | * __trace_printk_fmt. But for modules we copy them into a link list. | ||
100 | * The code to print the formats and their addresses passes around the | ||
101 | * address of the fmt string. If the fmt address passed into the seq | ||
102 | * functions is within the kernel core __trace_printk_fmt section, then | ||
103 | * it simply uses the next pointer in the list. | ||
104 | * | ||
105 | * When the fmt pointer is outside the kernel core __trace_printk_fmt | ||
106 | * section, then we need to read the link list pointers. The trick is | ||
107 | * we pass the address of the string to the seq function just like | ||
108 | * we do for the kernel core formats. To get back the structure that | ||
109 | * holds the format, we simply use containerof() and then go to the | ||
110 | * next format in the list. | ||
111 | */ | ||
112 | static const char ** | ||
113 | find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos) | ||
114 | { | ||
115 | struct trace_bprintk_fmt *mod_fmt; | ||
116 | |||
117 | if (list_empty(&trace_bprintk_fmt_list)) | ||
118 | return NULL; | ||
119 | |||
120 | /* | ||
121 | * v will point to the address of the fmt record from t_next | ||
122 | * v will be NULL from t_start. | ||
123 | * If this is the first pointer or called from start | ||
124 | * then we need to walk the list. | ||
125 | */ | ||
126 | if (!v || start_index == *pos) { | ||
127 | struct trace_bprintk_fmt *p; | ||
128 | |||
129 | /* search the module list */ | ||
130 | list_for_each_entry(p, &trace_bprintk_fmt_list, list) { | ||
131 | if (start_index == *pos) | ||
132 | return &p->fmt; | ||
133 | start_index++; | ||
134 | } | ||
135 | /* pos > index */ | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * v points to the address of the fmt field in the mod list | ||
141 | * structure that holds the module print format. | ||
142 | */ | ||
143 | mod_fmt = container_of(v, typeof(*mod_fmt), fmt); | ||
144 | if (mod_fmt->list.next == &trace_bprintk_fmt_list) | ||
145 | return NULL; | ||
146 | |||
147 | mod_fmt = container_of(mod_fmt->list.next, typeof(*mod_fmt), list); | ||
148 | |||
149 | return &mod_fmt->fmt; | ||
150 | } | ||
151 | |||
152 | static void format_mod_start(void) | ||
153 | { | ||
154 | mutex_lock(&btrace_mutex); | ||
155 | } | ||
156 | |||
157 | static void format_mod_stop(void) | ||
158 | { | ||
159 | mutex_unlock(&btrace_mutex); | ||
160 | } | ||
161 | |||
87 | #else /* !CONFIG_MODULES */ | 162 | #else /* !CONFIG_MODULES */ |
88 | __init static int | 163 | __init static int |
89 | module_trace_bprintk_format_notify(struct notifier_block *self, | 164 | module_trace_bprintk_format_notify(struct notifier_block *self, |
@@ -91,6 +166,13 @@ module_trace_bprintk_format_notify(struct notifier_block *self, | |||
91 | { | 166 | { |
92 | return 0; | 167 | return 0; |
93 | } | 168 | } |
169 | static inline const char ** | ||
170 | find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos) | ||
171 | { | ||
172 | return NULL; | ||
173 | } | ||
174 | static inline void format_mod_start(void) { } | ||
175 | static inline void format_mod_stop(void) { } | ||
94 | #endif /* CONFIG_MODULES */ | 176 | #endif /* CONFIG_MODULES */ |
95 | 177 | ||
96 | 178 | ||
@@ -153,20 +235,33 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap) | |||
153 | } | 235 | } |
154 | EXPORT_SYMBOL_GPL(__ftrace_vprintk); | 236 | EXPORT_SYMBOL_GPL(__ftrace_vprintk); |
155 | 237 | ||
238 | static const char **find_next(void *v, loff_t *pos) | ||
239 | { | ||
240 | const char **fmt = v; | ||
241 | int start_index; | ||
242 | |||
243 | if (!fmt) | ||
244 | fmt = __start___trace_bprintk_fmt + *pos; | ||
245 | |||
246 | start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt; | ||
247 | |||
248 | if (*pos < start_index) | ||
249 | return fmt; | ||
250 | |||
251 | return find_next_mod_format(start_index, v, fmt, pos); | ||
252 | } | ||
253 | |||
156 | static void * | 254 | static void * |
157 | t_start(struct seq_file *m, loff_t *pos) | 255 | t_start(struct seq_file *m, loff_t *pos) |
158 | { | 256 | { |
159 | const char **fmt = __start___trace_bprintk_fmt + *pos; | 257 | format_mod_start(); |
160 | 258 | return find_next(NULL, pos); | |
161 | if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt) | ||
162 | return NULL; | ||
163 | return fmt; | ||
164 | } | 259 | } |
165 | 260 | ||
166 | static void *t_next(struct seq_file *m, void * v, loff_t *pos) | 261 | static void *t_next(struct seq_file *m, void * v, loff_t *pos) |
167 | { | 262 | { |
168 | (*pos)++; | 263 | (*pos)++; |
169 | return t_start(m, pos); | 264 | return find_next(v, pos); |
170 | } | 265 | } |
171 | 266 | ||
172 | static int t_show(struct seq_file *m, void *v) | 267 | static int t_show(struct seq_file *m, void *v) |
@@ -205,6 +300,7 @@ static int t_show(struct seq_file *m, void *v) | |||
205 | 300 | ||
206 | static void t_stop(struct seq_file *m, void *p) | 301 | static void t_stop(struct seq_file *m, void *p) |
207 | { | 302 | { |
303 | format_mod_stop(); | ||
208 | } | 304 | } |
209 | 305 | ||
210 | static const struct seq_operations show_format_seq_ops = { | 306 | static const struct seq_operations show_format_seq_ops = { |