diff options
Diffstat (limited to 'kernel/trace/trace_events.c')
| -rw-r--r-- | kernel/trace/trace_events.c | 101 |
1 files changed, 72 insertions, 29 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index e71ffd4eccb5..3ddfd8f62c05 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
| @@ -27,12 +27,6 @@ | |||
| 27 | 27 | ||
| 28 | DEFINE_MUTEX(event_mutex); | 28 | DEFINE_MUTEX(event_mutex); |
| 29 | 29 | ||
| 30 | DEFINE_MUTEX(event_storage_mutex); | ||
| 31 | EXPORT_SYMBOL_GPL(event_storage_mutex); | ||
| 32 | |||
| 33 | char event_storage[EVENT_STORAGE_SIZE]; | ||
| 34 | EXPORT_SYMBOL_GPL(event_storage); | ||
| 35 | |||
| 36 | LIST_HEAD(ftrace_events); | 30 | LIST_HEAD(ftrace_events); |
| 37 | static LIST_HEAD(ftrace_common_fields); | 31 | static LIST_HEAD(ftrace_common_fields); |
| 38 | 32 | ||
| @@ -194,29 +188,60 @@ int trace_event_raw_init(struct ftrace_event_call *call) | |||
| 194 | } | 188 | } |
| 195 | EXPORT_SYMBOL_GPL(trace_event_raw_init); | 189 | EXPORT_SYMBOL_GPL(trace_event_raw_init); |
| 196 | 190 | ||
| 191 | void *ftrace_event_buffer_reserve(struct ftrace_event_buffer *fbuffer, | ||
| 192 | struct ftrace_event_file *ftrace_file, | ||
| 193 | unsigned long len) | ||
| 194 | { | ||
| 195 | struct ftrace_event_call *event_call = ftrace_file->event_call; | ||
| 196 | |||
| 197 | local_save_flags(fbuffer->flags); | ||
| 198 | fbuffer->pc = preempt_count(); | ||
| 199 | fbuffer->ftrace_file = ftrace_file; | ||
| 200 | |||
| 201 | fbuffer->event = | ||
| 202 | trace_event_buffer_lock_reserve(&fbuffer->buffer, ftrace_file, | ||
| 203 | event_call->event.type, len, | ||
| 204 | fbuffer->flags, fbuffer->pc); | ||
| 205 | if (!fbuffer->event) | ||
| 206 | return NULL; | ||
| 207 | |||
| 208 | fbuffer->entry = ring_buffer_event_data(fbuffer->event); | ||
| 209 | return fbuffer->entry; | ||
| 210 | } | ||
| 211 | EXPORT_SYMBOL_GPL(ftrace_event_buffer_reserve); | ||
| 212 | |||
| 213 | void ftrace_event_buffer_commit(struct ftrace_event_buffer *fbuffer) | ||
| 214 | { | ||
| 215 | event_trigger_unlock_commit(fbuffer->ftrace_file, fbuffer->buffer, | ||
| 216 | fbuffer->event, fbuffer->entry, | ||
| 217 | fbuffer->flags, fbuffer->pc); | ||
| 218 | } | ||
| 219 | EXPORT_SYMBOL_GPL(ftrace_event_buffer_commit); | ||
| 220 | |||
| 197 | int ftrace_event_reg(struct ftrace_event_call *call, | 221 | int ftrace_event_reg(struct ftrace_event_call *call, |
| 198 | enum trace_reg type, void *data) | 222 | enum trace_reg type, void *data) |
| 199 | { | 223 | { |
| 200 | struct ftrace_event_file *file = data; | 224 | struct ftrace_event_file *file = data; |
| 201 | 225 | ||
| 226 | WARN_ON(!(call->flags & TRACE_EVENT_FL_TRACEPOINT)); | ||
| 202 | switch (type) { | 227 | switch (type) { |
| 203 | case TRACE_REG_REGISTER: | 228 | case TRACE_REG_REGISTER: |
| 204 | return tracepoint_probe_register(call->name, | 229 | return tracepoint_probe_register(call->tp, |
| 205 | call->class->probe, | 230 | call->class->probe, |
| 206 | file); | 231 | file); |
| 207 | case TRACE_REG_UNREGISTER: | 232 | case TRACE_REG_UNREGISTER: |
| 208 | tracepoint_probe_unregister(call->name, | 233 | tracepoint_probe_unregister(call->tp, |
| 209 | call->class->probe, | 234 | call->class->probe, |
| 210 | file); | 235 | file); |
| 211 | return 0; | 236 | return 0; |
| 212 | 237 | ||
| 213 | #ifdef CONFIG_PERF_EVENTS | 238 | #ifdef CONFIG_PERF_EVENTS |
| 214 | case TRACE_REG_PERF_REGISTER: | 239 | case TRACE_REG_PERF_REGISTER: |
| 215 | return tracepoint_probe_register(call->name, | 240 | return tracepoint_probe_register(call->tp, |
| 216 | call->class->perf_probe, | 241 | call->class->perf_probe, |
| 217 | call); | 242 | call); |
| 218 | case TRACE_REG_PERF_UNREGISTER: | 243 | case TRACE_REG_PERF_UNREGISTER: |
| 219 | tracepoint_probe_unregister(call->name, | 244 | tracepoint_probe_unregister(call->tp, |
| 220 | call->class->perf_probe, | 245 | call->class->perf_probe, |
| 221 | call); | 246 | call); |
| 222 | return 0; | 247 | return 0; |
| @@ -328,7 +353,7 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file, | |||
| 328 | if (ret) { | 353 | if (ret) { |
| 329 | tracing_stop_cmdline_record(); | 354 | tracing_stop_cmdline_record(); |
| 330 | pr_info("event trace: Could not enable event " | 355 | pr_info("event trace: Could not enable event " |
| 331 | "%s\n", call->name); | 356 | "%s\n", ftrace_event_name(call)); |
| 332 | break; | 357 | break; |
| 333 | } | 358 | } |
| 334 | set_bit(FTRACE_EVENT_FL_ENABLED_BIT, &file->flags); | 359 | set_bit(FTRACE_EVENT_FL_ENABLED_BIT, &file->flags); |
| @@ -457,27 +482,29 @@ __ftrace_set_clr_event_nolock(struct trace_array *tr, const char *match, | |||
| 457 | { | 482 | { |
| 458 | struct ftrace_event_file *file; | 483 | struct ftrace_event_file *file; |
| 459 | struct ftrace_event_call *call; | 484 | struct ftrace_event_call *call; |
| 485 | const char *name; | ||
| 460 | int ret = -EINVAL; | 486 | int ret = -EINVAL; |
| 461 | 487 | ||
| 462 | list_for_each_entry(file, &tr->events, list) { | 488 | list_for_each_entry(file, &tr->events, list) { |
| 463 | 489 | ||
| 464 | call = file->event_call; | 490 | call = file->event_call; |
| 491 | name = ftrace_event_name(call); | ||
| 465 | 492 | ||
| 466 | if (!call->name || !call->class || !call->class->reg) | 493 | if (!name || !call->class || !call->class->reg) |
| 467 | continue; | 494 | continue; |
| 468 | 495 | ||
| 469 | if (call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) | 496 | if (call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) |
| 470 | continue; | 497 | continue; |
| 471 | 498 | ||
| 472 | if (match && | 499 | if (match && |
| 473 | strcmp(match, call->name) != 0 && | 500 | strcmp(match, name) != 0 && |
| 474 | strcmp(match, call->class->system) != 0) | 501 | strcmp(match, call->class->system) != 0) |
| 475 | continue; | 502 | continue; |
| 476 | 503 | ||
| 477 | if (sub && strcmp(sub, call->class->system) != 0) | 504 | if (sub && strcmp(sub, call->class->system) != 0) |
| 478 | continue; | 505 | continue; |
| 479 | 506 | ||
| 480 | if (event && strcmp(event, call->name) != 0) | 507 | if (event && strcmp(event, name) != 0) |
| 481 | continue; | 508 | continue; |
| 482 | 509 | ||
| 483 | ftrace_event_enable_disable(file, set); | 510 | ftrace_event_enable_disable(file, set); |
| @@ -675,7 +702,7 @@ static int t_show(struct seq_file *m, void *v) | |||
| 675 | 702 | ||
| 676 | if (strcmp(call->class->system, TRACE_SYSTEM) != 0) | 703 | if (strcmp(call->class->system, TRACE_SYSTEM) != 0) |
| 677 | seq_printf(m, "%s:", call->class->system); | 704 | seq_printf(m, "%s:", call->class->system); |
| 678 | seq_printf(m, "%s\n", call->name); | 705 | seq_printf(m, "%s\n", ftrace_event_name(call)); |
| 679 | 706 | ||
| 680 | return 0; | 707 | return 0; |
| 681 | } | 708 | } |
| @@ -768,7 +795,7 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, | |||
| 768 | mutex_lock(&event_mutex); | 795 | mutex_lock(&event_mutex); |
| 769 | list_for_each_entry(file, &tr->events, list) { | 796 | list_for_each_entry(file, &tr->events, list) { |
| 770 | call = file->event_call; | 797 | call = file->event_call; |
| 771 | if (!call->name || !call->class || !call->class->reg) | 798 | if (!ftrace_event_name(call) || !call->class || !call->class->reg) |
| 772 | continue; | 799 | continue; |
| 773 | 800 | ||
| 774 | if (system && strcmp(call->class->system, system->name) != 0) | 801 | if (system && strcmp(call->class->system, system->name) != 0) |
| @@ -883,7 +910,7 @@ static int f_show(struct seq_file *m, void *v) | |||
| 883 | 910 | ||
| 884 | switch ((unsigned long)v) { | 911 | switch ((unsigned long)v) { |
| 885 | case FORMAT_HEADER: | 912 | case FORMAT_HEADER: |
| 886 | seq_printf(m, "name: %s\n", call->name); | 913 | seq_printf(m, "name: %s\n", ftrace_event_name(call)); |
| 887 | seq_printf(m, "ID: %d\n", call->event.type); | 914 | seq_printf(m, "ID: %d\n", call->event.type); |
| 888 | seq_printf(m, "format:\n"); | 915 | seq_printf(m, "format:\n"); |
| 889 | return 0; | 916 | return 0; |
| @@ -1503,6 +1530,7 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file) | |||
| 1503 | struct trace_array *tr = file->tr; | 1530 | struct trace_array *tr = file->tr; |
| 1504 | struct list_head *head; | 1531 | struct list_head *head; |
| 1505 | struct dentry *d_events; | 1532 | struct dentry *d_events; |
| 1533 | const char *name; | ||
| 1506 | int ret; | 1534 | int ret; |
| 1507 | 1535 | ||
| 1508 | /* | 1536 | /* |
| @@ -1516,10 +1544,11 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file) | |||
| 1516 | } else | 1544 | } else |
| 1517 | d_events = parent; | 1545 | d_events = parent; |
| 1518 | 1546 | ||
| 1519 | file->dir = debugfs_create_dir(call->name, d_events); | 1547 | name = ftrace_event_name(call); |
| 1548 | file->dir = debugfs_create_dir(name, d_events); | ||
| 1520 | if (!file->dir) { | 1549 | if (!file->dir) { |
| 1521 | pr_warning("Could not create debugfs '%s' directory\n", | 1550 | pr_warning("Could not create debugfs '%s' directory\n", |
| 1522 | call->name); | 1551 | name); |
| 1523 | return -1; | 1552 | return -1; |
| 1524 | } | 1553 | } |
| 1525 | 1554 | ||
| @@ -1543,7 +1572,7 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file) | |||
| 1543 | ret = call->class->define_fields(call); | 1572 | ret = call->class->define_fields(call); |
| 1544 | if (ret < 0) { | 1573 | if (ret < 0) { |
| 1545 | pr_warning("Could not initialize trace point" | 1574 | pr_warning("Could not initialize trace point" |
| 1546 | " events/%s\n", call->name); | 1575 | " events/%s\n", name); |
| 1547 | return -1; | 1576 | return -1; |
| 1548 | } | 1577 | } |
| 1549 | } | 1578 | } |
| @@ -1607,15 +1636,17 @@ static void event_remove(struct ftrace_event_call *call) | |||
| 1607 | static int event_init(struct ftrace_event_call *call) | 1636 | static int event_init(struct ftrace_event_call *call) |
| 1608 | { | 1637 | { |
| 1609 | int ret = 0; | 1638 | int ret = 0; |
| 1639 | const char *name; | ||
| 1610 | 1640 | ||
| 1611 | if (WARN_ON(!call->name)) | 1641 | name = ftrace_event_name(call); |
| 1642 | if (WARN_ON(!name)) | ||
| 1612 | return -EINVAL; | 1643 | return -EINVAL; |
| 1613 | 1644 | ||
| 1614 | if (call->class->raw_init) { | 1645 | if (call->class->raw_init) { |
| 1615 | ret = call->class->raw_init(call); | 1646 | ret = call->class->raw_init(call); |
| 1616 | if (ret < 0 && ret != -ENOSYS) | 1647 | if (ret < 0 && ret != -ENOSYS) |
| 1617 | pr_warn("Could not initialize trace events/%s\n", | 1648 | pr_warn("Could not initialize trace events/%s\n", |
| 1618 | call->name); | 1649 | name); |
| 1619 | } | 1650 | } |
| 1620 | 1651 | ||
| 1621 | return ret; | 1652 | return ret; |
| @@ -1777,6 +1808,16 @@ static void trace_module_add_events(struct module *mod) | |||
| 1777 | { | 1808 | { |
| 1778 | struct ftrace_event_call **call, **start, **end; | 1809 | struct ftrace_event_call **call, **start, **end; |
| 1779 | 1810 | ||
| 1811 | if (!mod->num_trace_events) | ||
| 1812 | return; | ||
| 1813 | |||
| 1814 | /* Don't add infrastructure for mods without tracepoints */ | ||
| 1815 | if (trace_module_has_bad_taint(mod)) { | ||
| 1816 | pr_err("%s: module has bad taint, not creating trace events\n", | ||
| 1817 | mod->name); | ||
| 1818 | return; | ||
| 1819 | } | ||
| 1820 | |||
| 1780 | start = mod->trace_events; | 1821 | start = mod->trace_events; |
| 1781 | end = mod->trace_events + mod->num_trace_events; | 1822 | end = mod->trace_events + mod->num_trace_events; |
| 1782 | 1823 | ||
| @@ -1851,7 +1892,7 @@ __trace_add_event_dirs(struct trace_array *tr) | |||
| 1851 | ret = __trace_add_new_event(call, tr); | 1892 | ret = __trace_add_new_event(call, tr); |
| 1852 | if (ret < 0) | 1893 | if (ret < 0) |
| 1853 | pr_warning("Could not create directory for event %s\n", | 1894 | pr_warning("Could not create directory for event %s\n", |
| 1854 | call->name); | 1895 | ftrace_event_name(call)); |
| 1855 | } | 1896 | } |
| 1856 | } | 1897 | } |
| 1857 | 1898 | ||
| @@ -1860,18 +1901,20 @@ find_event_file(struct trace_array *tr, const char *system, const char *event) | |||
| 1860 | { | 1901 | { |
| 1861 | struct ftrace_event_file *file; | 1902 | struct ftrace_event_file *file; |
| 1862 | struct ftrace_event_call *call; | 1903 | struct ftrace_event_call *call; |
| 1904 | const char *name; | ||
| 1863 | 1905 | ||
| 1864 | list_for_each_entry(file, &tr->events, list) { | 1906 | list_for_each_entry(file, &tr->events, list) { |
| 1865 | 1907 | ||
| 1866 | call = file->event_call; | 1908 | call = file->event_call; |
| 1909 | name = ftrace_event_name(call); | ||
| 1867 | 1910 | ||
| 1868 | if (!call->name || !call->class || !call->class->reg) | 1911 | if (!name || !call->class || !call->class->reg) |
| 1869 | continue; | 1912 | continue; |
| 1870 | 1913 | ||
| 1871 | if (call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) | 1914 | if (call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) |
| 1872 | continue; | 1915 | continue; |
| 1873 | 1916 | ||
| 1874 | if (strcmp(event, call->name) == 0 && | 1917 | if (strcmp(event, name) == 0 && |
| 1875 | strcmp(system, call->class->system) == 0) | 1918 | strcmp(system, call->class->system) == 0) |
| 1876 | return file; | 1919 | return file; |
| 1877 | } | 1920 | } |
| @@ -1939,7 +1982,7 @@ event_enable_print(struct seq_file *m, unsigned long ip, | |||
| 1939 | seq_printf(m, "%s:%s:%s", | 1982 | seq_printf(m, "%s:%s:%s", |
| 1940 | data->enable ? ENABLE_EVENT_STR : DISABLE_EVENT_STR, | 1983 | data->enable ? ENABLE_EVENT_STR : DISABLE_EVENT_STR, |
| 1941 | data->file->event_call->class->system, | 1984 | data->file->event_call->class->system, |
| 1942 | data->file->event_call->name); | 1985 | ftrace_event_name(data->file->event_call)); |
| 1943 | 1986 | ||
| 1944 | if (data->count == -1) | 1987 | if (data->count == -1) |
| 1945 | seq_printf(m, ":unlimited\n"); | 1988 | seq_printf(m, ":unlimited\n"); |
| @@ -2159,7 +2202,7 @@ __trace_early_add_event_dirs(struct trace_array *tr) | |||
| 2159 | ret = event_create_dir(tr->event_dir, file); | 2202 | ret = event_create_dir(tr->event_dir, file); |
| 2160 | if (ret < 0) | 2203 | if (ret < 0) |
| 2161 | pr_warning("Could not create directory for event %s\n", | 2204 | pr_warning("Could not create directory for event %s\n", |
| 2162 | file->event_call->name); | 2205 | ftrace_event_name(file->event_call)); |
| 2163 | } | 2206 | } |
| 2164 | } | 2207 | } |
| 2165 | 2208 | ||
| @@ -2183,7 +2226,7 @@ __trace_early_add_events(struct trace_array *tr) | |||
| 2183 | ret = __trace_early_add_new_event(call, tr); | 2226 | ret = __trace_early_add_new_event(call, tr); |
| 2184 | if (ret < 0) | 2227 | if (ret < 0) |
| 2185 | pr_warning("Could not create early event %s\n", | 2228 | pr_warning("Could not create early event %s\n", |
| 2186 | call->name); | 2229 | ftrace_event_name(call)); |
| 2187 | } | 2230 | } |
| 2188 | } | 2231 | } |
| 2189 | 2232 | ||
| @@ -2515,7 +2558,7 @@ static __init void event_trace_self_tests(void) | |||
| 2515 | continue; | 2558 | continue; |
| 2516 | #endif | 2559 | #endif |
| 2517 | 2560 | ||
| 2518 | pr_info("Testing event %s: ", call->name); | 2561 | pr_info("Testing event %s: ", ftrace_event_name(call)); |
| 2519 | 2562 | ||
| 2520 | /* | 2563 | /* |
| 2521 | * If an event is already enabled, someone is using | 2564 | * If an event is already enabled, someone is using |
