diff options
| -rw-r--r-- | arch/x86/kernel/ftrace.c | 63 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 85 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 6 | ||||
| -rw-r--r-- | kernel/trace/trace_event_types.h | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_functions_graph.c | 219 | ||||
| -rw-r--r-- | kernel/trace/trace_mmiotrace.c | 2 | ||||
| -rw-r--r-- | kernel/trace/trace_output.c | 32 | ||||
| -rw-r--r-- | kernel/trace/trace_output.h | 5 | ||||
| -rw-r--r-- | kernel/trace/trace_printk.c | 8 |
9 files changed, 243 insertions, 179 deletions
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 1d0d7f42efe3..57b33edb7ce3 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
| @@ -79,11 +79,11 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) | |||
| 79 | * | 79 | * |
| 80 | * 1) Put the instruction pointer into the IP buffer | 80 | * 1) Put the instruction pointer into the IP buffer |
| 81 | * and the new code into the "code" buffer. | 81 | * and the new code into the "code" buffer. |
| 82 | * 2) Set a flag that says we are modifying code | 82 | * 2) Wait for any running NMIs to finish and set a flag that says |
| 83 | * 3) Wait for any running NMIs to finish. | 83 | * we are modifying code, it is done in an atomic operation. |
| 84 | * 4) Write the code | 84 | * 3) Write the code |
| 85 | * 5) clear the flag. | 85 | * 4) clear the flag. |
| 86 | * 6) Wait for any running NMIs to finish. | 86 | * 5) Wait for any running NMIs to finish. |
| 87 | * | 87 | * |
| 88 | * If an NMI is executed, the first thing it does is to call | 88 | * If an NMI is executed, the first thing it does is to call |
| 89 | * "ftrace_nmi_enter". This will check if the flag is set to write | 89 | * "ftrace_nmi_enter". This will check if the flag is set to write |
| @@ -95,9 +95,9 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) | |||
| 95 | * are the same as what exists. | 95 | * are the same as what exists. |
| 96 | */ | 96 | */ |
| 97 | 97 | ||
| 98 | #define MOD_CODE_WRITE_FLAG (1 << 31) /* set when NMI should do the write */ | ||
| 98 | static atomic_t nmi_running = ATOMIC_INIT(0); | 99 | static atomic_t nmi_running = ATOMIC_INIT(0); |
| 99 | static int mod_code_status; /* holds return value of text write */ | 100 | static int mod_code_status; /* holds return value of text write */ |
| 100 | static int mod_code_write; /* set when NMI should do the write */ | ||
| 101 | static void *mod_code_ip; /* holds the IP to write to */ | 101 | static void *mod_code_ip; /* holds the IP to write to */ |
| 102 | static void *mod_code_newcode; /* holds the text to write to the IP */ | 102 | static void *mod_code_newcode; /* holds the text to write to the IP */ |
| 103 | 103 | ||
| @@ -114,6 +114,20 @@ int ftrace_arch_read_dyn_info(char *buf, int size) | |||
| 114 | return r; | 114 | return r; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | static void clear_mod_flag(void) | ||
| 118 | { | ||
| 119 | int old = atomic_read(&nmi_running); | ||
| 120 | |||
| 121 | for (;;) { | ||
| 122 | int new = old & ~MOD_CODE_WRITE_FLAG; | ||
| 123 | |||
| 124 | if (old == new) | ||
| 125 | break; | ||
| 126 | |||
| 127 | old = atomic_cmpxchg(&nmi_running, old, new); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 117 | static void ftrace_mod_code(void) | 131 | static void ftrace_mod_code(void) |
| 118 | { | 132 | { |
| 119 | /* | 133 | /* |
| @@ -127,27 +141,39 @@ static void ftrace_mod_code(void) | |||
| 127 | 141 | ||
| 128 | /* if we fail, then kill any new writers */ | 142 | /* if we fail, then kill any new writers */ |
| 129 | if (mod_code_status) | 143 | if (mod_code_status) |
| 130 | mod_code_write = 0; | 144 | clear_mod_flag(); |
| 131 | } | 145 | } |
| 132 | 146 | ||
| 133 | void ftrace_nmi_enter(void) | 147 | void ftrace_nmi_enter(void) |
| 134 | { | 148 | { |
| 135 | atomic_inc(&nmi_running); | 149 | if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) { |
| 136 | /* Must have nmi_running seen before reading write flag */ | 150 | smp_rmb(); |
| 137 | smp_mb(); | ||
| 138 | if (mod_code_write) { | ||
| 139 | ftrace_mod_code(); | 151 | ftrace_mod_code(); |
| 140 | atomic_inc(&nmi_update_count); | 152 | atomic_inc(&nmi_update_count); |
| 141 | } | 153 | } |
| 154 | /* Must have previous changes seen before executions */ | ||
| 155 | smp_mb(); | ||
| 142 | } | 156 | } |
| 143 | 157 | ||
| 144 | void ftrace_nmi_exit(void) | 158 | void ftrace_nmi_exit(void) |
| 145 | { | 159 | { |
| 146 | /* Finish all executions before clearing nmi_running */ | 160 | /* Finish all executions before clearing nmi_running */ |
| 147 | smp_wmb(); | 161 | smp_mb(); |
| 148 | atomic_dec(&nmi_running); | 162 | atomic_dec(&nmi_running); |
| 149 | } | 163 | } |
| 150 | 164 | ||
| 165 | static void wait_for_nmi_and_set_mod_flag(void) | ||
| 166 | { | ||
| 167 | if (!atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG)) | ||
| 168 | return; | ||
| 169 | |||
| 170 | do { | ||
| 171 | cpu_relax(); | ||
| 172 | } while (atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG)); | ||
| 173 | |||
| 174 | nmi_wait_count++; | ||
| 175 | } | ||
| 176 | |||
| 151 | static void wait_for_nmi(void) | 177 | static void wait_for_nmi(void) |
| 152 | { | 178 | { |
| 153 | if (!atomic_read(&nmi_running)) | 179 | if (!atomic_read(&nmi_running)) |
| @@ -167,14 +193,9 @@ do_ftrace_mod_code(unsigned long ip, void *new_code) | |||
| 167 | mod_code_newcode = new_code; | 193 | mod_code_newcode = new_code; |
| 168 | 194 | ||
| 169 | /* The buffers need to be visible before we let NMIs write them */ | 195 | /* The buffers need to be visible before we let NMIs write them */ |
| 170 | smp_wmb(); | ||
| 171 | |||
| 172 | mod_code_write = 1; | ||
| 173 | |||
| 174 | /* Make sure write bit is visible before we wait on NMIs */ | ||
| 175 | smp_mb(); | 196 | smp_mb(); |
| 176 | 197 | ||
| 177 | wait_for_nmi(); | 198 | wait_for_nmi_and_set_mod_flag(); |
| 178 | 199 | ||
| 179 | /* Make sure all running NMIs have finished before we write the code */ | 200 | /* Make sure all running NMIs have finished before we write the code */ |
| 180 | smp_mb(); | 201 | smp_mb(); |
| @@ -182,13 +203,9 @@ do_ftrace_mod_code(unsigned long ip, void *new_code) | |||
| 182 | ftrace_mod_code(); | 203 | ftrace_mod_code(); |
| 183 | 204 | ||
| 184 | /* Make sure the write happens before clearing the bit */ | 205 | /* Make sure the write happens before clearing the bit */ |
| 185 | smp_wmb(); | ||
| 186 | |||
| 187 | mod_code_write = 0; | ||
| 188 | |||
| 189 | /* make sure NMIs see the cleared bit */ | ||
| 190 | smp_mb(); | 206 | smp_mb(); |
| 191 | 207 | ||
| 208 | clear_mod_flag(); | ||
| 192 | wait_for_nmi(); | 209 | wait_for_nmi(); |
| 193 | 210 | ||
| 194 | return mod_code_status; | 211 | return mod_code_status; |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index c95b7292be70..e3dfefe69348 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -1201,7 +1201,7 @@ void trace_graph_return(struct ftrace_graph_ret *trace) | |||
| 1201 | * trace_vbprintk - write binary msg to tracing buffer | 1201 | * trace_vbprintk - write binary msg to tracing buffer |
| 1202 | * | 1202 | * |
| 1203 | */ | 1203 | */ |
| 1204 | int trace_vbprintk(unsigned long ip, int depth, const char *fmt, va_list args) | 1204 | int trace_vbprintk(unsigned long ip, const char *fmt, va_list args) |
| 1205 | { | 1205 | { |
| 1206 | static raw_spinlock_t trace_buf_lock = | 1206 | static raw_spinlock_t trace_buf_lock = |
| 1207 | (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; | 1207 | (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; |
| @@ -1243,7 +1243,6 @@ int trace_vbprintk(unsigned long ip, int depth, const char *fmt, va_list args) | |||
| 1243 | goto out_unlock; | 1243 | goto out_unlock; |
| 1244 | entry = ring_buffer_event_data(event); | 1244 | entry = ring_buffer_event_data(event); |
| 1245 | entry->ip = ip; | 1245 | entry->ip = ip; |
| 1246 | entry->depth = depth; | ||
| 1247 | entry->fmt = fmt; | 1246 | entry->fmt = fmt; |
| 1248 | 1247 | ||
| 1249 | memcpy(entry->buf, trace_buf, sizeof(u32) * len); | 1248 | memcpy(entry->buf, trace_buf, sizeof(u32) * len); |
| @@ -1261,7 +1260,7 @@ out: | |||
| 1261 | } | 1260 | } |
| 1262 | EXPORT_SYMBOL_GPL(trace_vbprintk); | 1261 | EXPORT_SYMBOL_GPL(trace_vbprintk); |
| 1263 | 1262 | ||
| 1264 | int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args) | 1263 | int trace_vprintk(unsigned long ip, const char *fmt, va_list args) |
| 1265 | { | 1264 | { |
| 1266 | static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED; | 1265 | static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED; |
| 1267 | static char trace_buf[TRACE_BUF_SIZE]; | 1266 | static char trace_buf[TRACE_BUF_SIZE]; |
| @@ -1298,7 +1297,6 @@ int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args) | |||
| 1298 | goto out_unlock; | 1297 | goto out_unlock; |
| 1299 | entry = ring_buffer_event_data(event); | 1298 | entry = ring_buffer_event_data(event); |
| 1300 | entry->ip = ip; | 1299 | entry->ip = ip; |
| 1301 | entry->depth = depth; | ||
| 1302 | 1300 | ||
| 1303 | memcpy(&entry->buf, trace_buf, len); | 1301 | memcpy(&entry->buf, trace_buf, len); |
| 1304 | entry->buf[len] = 0; | 1302 | entry->buf[len] = 0; |
| @@ -1701,38 +1699,6 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) | |||
| 1701 | return TRACE_TYPE_HANDLED; | 1699 | return TRACE_TYPE_HANDLED; |
| 1702 | } | 1700 | } |
| 1703 | 1701 | ||
| 1704 | static enum print_line_t print_bprintk_msg_only(struct trace_iterator *iter) | ||
| 1705 | { | ||
| 1706 | struct trace_seq *s = &iter->seq; | ||
| 1707 | struct trace_entry *entry = iter->ent; | ||
| 1708 | struct bprint_entry *field; | ||
| 1709 | int ret; | ||
| 1710 | |||
| 1711 | trace_assign_type(field, entry); | ||
| 1712 | |||
| 1713 | ret = trace_seq_bprintf(s, field->fmt, field->buf); | ||
| 1714 | if (!ret) | ||
| 1715 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 1716 | |||
| 1717 | return TRACE_TYPE_HANDLED; | ||
| 1718 | } | ||
| 1719 | |||
| 1720 | static enum print_line_t print_printk_msg_only(struct trace_iterator *iter) | ||
| 1721 | { | ||
| 1722 | struct trace_seq *s = &iter->seq; | ||
| 1723 | struct trace_entry *entry = iter->ent; | ||
| 1724 | struct print_entry *field; | ||
| 1725 | int ret; | ||
| 1726 | |||
| 1727 | trace_assign_type(field, entry); | ||
| 1728 | |||
| 1729 | ret = trace_seq_printf(s, "%s", field->buf); | ||
| 1730 | if (!ret) | ||
| 1731 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 1732 | |||
| 1733 | return TRACE_TYPE_HANDLED; | ||
| 1734 | } | ||
| 1735 | |||
| 1736 | static enum print_line_t print_bin_fmt(struct trace_iterator *iter) | 1702 | static enum print_line_t print_bin_fmt(struct trace_iterator *iter) |
| 1737 | { | 1703 | { |
| 1738 | struct trace_seq *s = &iter->seq; | 1704 | struct trace_seq *s = &iter->seq; |
| @@ -1794,12 +1760,12 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter) | |||
| 1794 | if (iter->ent->type == TRACE_BPRINT && | 1760 | if (iter->ent->type == TRACE_BPRINT && |
| 1795 | trace_flags & TRACE_ITER_PRINTK && | 1761 | trace_flags & TRACE_ITER_PRINTK && |
| 1796 | trace_flags & TRACE_ITER_PRINTK_MSGONLY) | 1762 | trace_flags & TRACE_ITER_PRINTK_MSGONLY) |
| 1797 | return print_bprintk_msg_only(iter); | 1763 | return trace_print_bprintk_msg_only(iter); |
| 1798 | 1764 | ||
| 1799 | if (iter->ent->type == TRACE_PRINT && | 1765 | if (iter->ent->type == TRACE_PRINT && |
| 1800 | trace_flags & TRACE_ITER_PRINTK && | 1766 | trace_flags & TRACE_ITER_PRINTK && |
| 1801 | trace_flags & TRACE_ITER_PRINTK_MSGONLY) | 1767 | trace_flags & TRACE_ITER_PRINTK_MSGONLY) |
| 1802 | return print_printk_msg_only(iter); | 1768 | return trace_print_printk_msg_only(iter); |
| 1803 | 1769 | ||
| 1804 | if (trace_flags & TRACE_ITER_BIN) | 1770 | if (trace_flags & TRACE_ITER_BIN) |
| 1805 | return print_bin_fmt(iter); | 1771 | return print_bin_fmt(iter); |
| @@ -1948,9 +1914,14 @@ int tracing_open_generic(struct inode *inode, struct file *filp) | |||
| 1948 | static int tracing_release(struct inode *inode, struct file *file) | 1914 | static int tracing_release(struct inode *inode, struct file *file) |
| 1949 | { | 1915 | { |
| 1950 | struct seq_file *m = (struct seq_file *)file->private_data; | 1916 | struct seq_file *m = (struct seq_file *)file->private_data; |
| 1951 | struct trace_iterator *iter = m->private; | 1917 | struct trace_iterator *iter; |
| 1952 | int cpu; | 1918 | int cpu; |
| 1953 | 1919 | ||
| 1920 | if (!(file->f_mode & FMODE_READ)) | ||
| 1921 | return 0; | ||
| 1922 | |||
| 1923 | iter = m->private; | ||
| 1924 | |||
| 1954 | mutex_lock(&trace_types_lock); | 1925 | mutex_lock(&trace_types_lock); |
| 1955 | for_each_tracing_cpu(cpu) { | 1926 | for_each_tracing_cpu(cpu) { |
| 1956 | if (iter->buffer_iter[cpu]) | 1927 | if (iter->buffer_iter[cpu]) |
| @@ -1976,12 +1947,24 @@ static int tracing_open(struct inode *inode, struct file *file) | |||
| 1976 | struct trace_iterator *iter; | 1947 | struct trace_iterator *iter; |
| 1977 | int ret = 0; | 1948 | int ret = 0; |
| 1978 | 1949 | ||
| 1979 | iter = __tracing_open(inode, file); | 1950 | /* If this file was open for write, then erase contents */ |
| 1980 | if (IS_ERR(iter)) | 1951 | if ((file->f_mode & FMODE_WRITE) && |
| 1981 | ret = PTR_ERR(iter); | 1952 | !(file->f_flags & O_APPEND)) { |
| 1982 | else if (trace_flags & TRACE_ITER_LATENCY_FMT) | 1953 | long cpu = (long) inode->i_private; |
| 1983 | iter->iter_flags |= TRACE_FILE_LAT_FMT; | ||
| 1984 | 1954 | ||
| 1955 | if (cpu == TRACE_PIPE_ALL_CPU) | ||
| 1956 | tracing_reset_online_cpus(&global_trace); | ||
| 1957 | else | ||
| 1958 | tracing_reset(&global_trace, cpu); | ||
| 1959 | } | ||
| 1960 | |||
| 1961 | if (file->f_mode & FMODE_READ) { | ||
| 1962 | iter = __tracing_open(inode, file); | ||
| 1963 | if (IS_ERR(iter)) | ||
| 1964 | ret = PTR_ERR(iter); | ||
| 1965 | else if (trace_flags & TRACE_ITER_LATENCY_FMT) | ||
| 1966 | iter->iter_flags |= TRACE_FILE_LAT_FMT; | ||
| 1967 | } | ||
| 1985 | return ret; | 1968 | return ret; |
| 1986 | } | 1969 | } |
| 1987 | 1970 | ||
| @@ -2056,9 +2039,17 @@ static int show_traces_open(struct inode *inode, struct file *file) | |||
| 2056 | return ret; | 2039 | return ret; |
| 2057 | } | 2040 | } |
| 2058 | 2041 | ||
| 2042 | static ssize_t | ||
| 2043 | tracing_write_stub(struct file *filp, const char __user *ubuf, | ||
| 2044 | size_t count, loff_t *ppos) | ||
| 2045 | { | ||
| 2046 | return count; | ||
| 2047 | } | ||
| 2048 | |||
| 2059 | static const struct file_operations tracing_fops = { | 2049 | static const struct file_operations tracing_fops = { |
| 2060 | .open = tracing_open, | 2050 | .open = tracing_open, |
| 2061 | .read = seq_read, | 2051 | .read = seq_read, |
| 2052 | .write = tracing_write_stub, | ||
| 2062 | .llseek = seq_lseek, | 2053 | .llseek = seq_lseek, |
| 2063 | .release = tracing_release, | 2054 | .release = tracing_release, |
| 2064 | }; | 2055 | }; |
| @@ -3154,7 +3145,7 @@ static int mark_printk(const char *fmt, ...) | |||
| 3154 | int ret; | 3145 | int ret; |
| 3155 | va_list args; | 3146 | va_list args; |
| 3156 | va_start(args, fmt); | 3147 | va_start(args, fmt); |
| 3157 | ret = trace_vprintk(0, -1, fmt, args); | 3148 | ret = trace_vprintk(0, fmt, args); |
| 3158 | va_end(args); | 3149 | va_end(args); |
| 3159 | return ret; | 3150 | return ret; |
| 3160 | } | 3151 | } |
| @@ -3583,7 +3574,7 @@ static void tracing_init_debugfs_percpu(long cpu) | |||
| 3583 | pr_warning("Could not create debugfs 'trace_pipe' entry\n"); | 3574 | pr_warning("Could not create debugfs 'trace_pipe' entry\n"); |
| 3584 | 3575 | ||
| 3585 | /* per cpu trace */ | 3576 | /* per cpu trace */ |
| 3586 | entry = debugfs_create_file("trace", 0444, d_cpu, | 3577 | entry = debugfs_create_file("trace", 0644, d_cpu, |
| 3587 | (void *) cpu, &tracing_fops); | 3578 | (void *) cpu, &tracing_fops); |
| 3588 | if (!entry) | 3579 | if (!entry) |
| 3589 | pr_warning("Could not create debugfs 'trace' entry\n"); | 3580 | pr_warning("Could not create debugfs 'trace' entry\n"); |
| @@ -3897,7 +3888,7 @@ static __init int tracer_init_debugfs(void) | |||
| 3897 | if (!entry) | 3888 | if (!entry) |
| 3898 | pr_warning("Could not create debugfs 'tracing_cpumask' entry\n"); | 3889 | pr_warning("Could not create debugfs 'tracing_cpumask' entry\n"); |
| 3899 | 3890 | ||
| 3900 | entry = debugfs_create_file("trace", 0444, d_tracer, | 3891 | entry = debugfs_create_file("trace", 0644, d_tracer, |
| 3901 | (void *) TRACE_PIPE_ALL_CPU, &tracing_fops); | 3892 | (void *) TRACE_PIPE_ALL_CPU, &tracing_fops); |
| 3902 | if (!entry) | 3893 | if (!entry) |
| 3903 | pr_warning("Could not create debugfs 'trace' entry\n"); | 3894 | pr_warning("Could not create debugfs 'trace' entry\n"); |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 38276d1638e3..7c9a0cbf5dca 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
| @@ -123,7 +123,6 @@ struct userstack_entry { | |||
| 123 | struct bprint_entry { | 123 | struct bprint_entry { |
| 124 | struct trace_entry ent; | 124 | struct trace_entry ent; |
| 125 | unsigned long ip; | 125 | unsigned long ip; |
| 126 | int depth; | ||
| 127 | const char *fmt; | 126 | const char *fmt; |
| 128 | u32 buf[]; | 127 | u32 buf[]; |
| 129 | }; | 128 | }; |
| @@ -131,7 +130,6 @@ struct bprint_entry { | |||
| 131 | struct print_entry { | 130 | struct print_entry { |
| 132 | struct trace_entry ent; | 131 | struct trace_entry ent; |
| 133 | unsigned long ip; | 132 | unsigned long ip; |
| 134 | int depth; | ||
| 135 | char buf[]; | 133 | char buf[]; |
| 136 | }; | 134 | }; |
| 137 | 135 | ||
| @@ -598,9 +596,9 @@ extern int trace_selftest_startup_branch(struct tracer *trace, | |||
| 598 | extern void *head_page(struct trace_array_cpu *data); | 596 | extern void *head_page(struct trace_array_cpu *data); |
| 599 | extern long ns2usecs(cycle_t nsec); | 597 | extern long ns2usecs(cycle_t nsec); |
| 600 | extern int | 598 | extern int |
| 601 | trace_vbprintk(unsigned long ip, int depth, const char *fmt, va_list args); | 599 | trace_vbprintk(unsigned long ip, const char *fmt, va_list args); |
| 602 | extern int | 600 | extern int |
| 603 | trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args); | 601 | trace_vprintk(unsigned long ip, const char *fmt, va_list args); |
| 604 | 602 | ||
| 605 | extern unsigned long trace_flags; | 603 | extern unsigned long trace_flags; |
| 606 | 604 | ||
diff --git a/kernel/trace/trace_event_types.h b/kernel/trace/trace_event_types.h index 019915063fe6..fd78bee71dd7 100644 --- a/kernel/trace/trace_event_types.h +++ b/kernel/trace/trace_event_types.h | |||
| @@ -105,7 +105,6 @@ TRACE_EVENT_FORMAT(user_stack, TRACE_USER_STACK, userstack_entry, ignore, | |||
| 105 | TRACE_EVENT_FORMAT(bprint, TRACE_BPRINT, bprint_entry, ignore, | 105 | TRACE_EVENT_FORMAT(bprint, TRACE_BPRINT, bprint_entry, ignore, |
| 106 | TRACE_STRUCT( | 106 | TRACE_STRUCT( |
| 107 | TRACE_FIELD(unsigned long, ip, ip) | 107 | TRACE_FIELD(unsigned long, ip, ip) |
| 108 | TRACE_FIELD(unsigned int, depth, depth) | ||
| 109 | TRACE_FIELD(char *, fmt, fmt) | 108 | TRACE_FIELD(char *, fmt, fmt) |
| 110 | TRACE_FIELD_ZERO_CHAR(buf) | 109 | TRACE_FIELD_ZERO_CHAR(buf) |
| 111 | ), | 110 | ), |
| @@ -115,7 +114,6 @@ TRACE_EVENT_FORMAT(bprint, TRACE_BPRINT, bprint_entry, ignore, | |||
| 115 | TRACE_EVENT_FORMAT(print, TRACE_PRINT, print_entry, ignore, | 114 | TRACE_EVENT_FORMAT(print, TRACE_PRINT, print_entry, ignore, |
| 116 | TRACE_STRUCT( | 115 | TRACE_STRUCT( |
| 117 | TRACE_FIELD(unsigned long, ip, ip) | 116 | TRACE_FIELD(unsigned long, ip, ip) |
| 118 | TRACE_FIELD(unsigned int, depth, depth) | ||
| 119 | TRACE_FIELD_ZERO_CHAR(buf) | 117 | TRACE_FIELD_ZERO_CHAR(buf) |
| 120 | ), | 118 | ), |
| 121 | TP_RAW_FMT("%08lx (%d) fmt:%p %s") | 119 | TP_RAW_FMT("%08lx (%d) fmt:%p %s") |
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 6004ccac2dd7..e876816fa8e7 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
| @@ -14,6 +14,11 @@ | |||
| 14 | #include "trace.h" | 14 | #include "trace.h" |
| 15 | #include "trace_output.h" | 15 | #include "trace_output.h" |
| 16 | 16 | ||
| 17 | struct fgraph_data { | ||
| 18 | pid_t last_pid; | ||
| 19 | int depth; | ||
| 20 | }; | ||
| 21 | |||
| 17 | #define TRACE_GRAPH_INDENT 2 | 22 | #define TRACE_GRAPH_INDENT 2 |
| 18 | 23 | ||
| 19 | /* Flag options */ | 24 | /* Flag options */ |
| @@ -231,16 +236,16 @@ print_graph_proc(struct trace_seq *s, pid_t pid) | |||
| 231 | 236 | ||
| 232 | /* If the pid changed since the last trace, output this event */ | 237 | /* If the pid changed since the last trace, output this event */ |
| 233 | static enum print_line_t | 238 | static enum print_line_t |
| 234 | verif_pid(struct trace_seq *s, pid_t pid, int cpu, pid_t *last_pids_cpu) | 239 | verif_pid(struct trace_seq *s, pid_t pid, int cpu, struct fgraph_data *data) |
| 235 | { | 240 | { |
| 236 | pid_t prev_pid; | 241 | pid_t prev_pid; |
| 237 | pid_t *last_pid; | 242 | pid_t *last_pid; |
| 238 | int ret; | 243 | int ret; |
| 239 | 244 | ||
| 240 | if (!last_pids_cpu) | 245 | if (!data) |
| 241 | return TRACE_TYPE_HANDLED; | 246 | return TRACE_TYPE_HANDLED; |
| 242 | 247 | ||
| 243 | last_pid = per_cpu_ptr(last_pids_cpu, cpu); | 248 | last_pid = &(per_cpu_ptr(data, cpu)->last_pid); |
| 244 | 249 | ||
| 245 | if (*last_pid == pid) | 250 | if (*last_pid == pid) |
| 246 | return TRACE_TYPE_HANDLED; | 251 | return TRACE_TYPE_HANDLED; |
| @@ -471,6 +476,7 @@ print_graph_entry_leaf(struct trace_iterator *iter, | |||
| 471 | struct ftrace_graph_ent_entry *entry, | 476 | struct ftrace_graph_ent_entry *entry, |
| 472 | struct ftrace_graph_ret_entry *ret_entry, struct trace_seq *s) | 477 | struct ftrace_graph_ret_entry *ret_entry, struct trace_seq *s) |
| 473 | { | 478 | { |
| 479 | struct fgraph_data *data = iter->private; | ||
| 474 | struct ftrace_graph_ret *graph_ret; | 480 | struct ftrace_graph_ret *graph_ret; |
| 475 | struct ftrace_graph_ent *call; | 481 | struct ftrace_graph_ent *call; |
| 476 | unsigned long long duration; | 482 | unsigned long long duration; |
| @@ -481,6 +487,18 @@ print_graph_entry_leaf(struct trace_iterator *iter, | |||
| 481 | call = &entry->graph_ent; | 487 | call = &entry->graph_ent; |
| 482 | duration = graph_ret->rettime - graph_ret->calltime; | 488 | duration = graph_ret->rettime - graph_ret->calltime; |
| 483 | 489 | ||
| 490 | if (data) { | ||
| 491 | int cpu = iter->cpu; | ||
| 492 | int *depth = &(per_cpu_ptr(data, cpu)->depth); | ||
| 493 | |||
| 494 | /* | ||
| 495 | * Comments display at + 1 to depth. Since | ||
| 496 | * this is a leaf function, keep the comments | ||
| 497 | * equal to this depth. | ||
| 498 | */ | ||
| 499 | *depth = call->depth - 1; | ||
| 500 | } | ||
| 501 | |||
| 484 | /* Overhead */ | 502 | /* Overhead */ |
| 485 | ret = print_graph_overhead(duration, s); | 503 | ret = print_graph_overhead(duration, s); |
| 486 | if (!ret) | 504 | if (!ret) |
| @@ -512,12 +530,21 @@ print_graph_entry_leaf(struct trace_iterator *iter, | |||
| 512 | } | 530 | } |
| 513 | 531 | ||
| 514 | static enum print_line_t | 532 | static enum print_line_t |
| 515 | print_graph_entry_nested(struct ftrace_graph_ent_entry *entry, | 533 | print_graph_entry_nested(struct trace_iterator *iter, |
| 516 | struct trace_seq *s, pid_t pid, int cpu) | 534 | struct ftrace_graph_ent_entry *entry, |
| 535 | struct trace_seq *s, int cpu) | ||
| 517 | { | 536 | { |
| 518 | int i; | ||
| 519 | int ret; | ||
| 520 | struct ftrace_graph_ent *call = &entry->graph_ent; | 537 | struct ftrace_graph_ent *call = &entry->graph_ent; |
| 538 | struct fgraph_data *data = iter->private; | ||
| 539 | int ret; | ||
| 540 | int i; | ||
| 541 | |||
| 542 | if (data) { | ||
| 543 | int cpu = iter->cpu; | ||
| 544 | int *depth = &(per_cpu_ptr(data, cpu)->depth); | ||
| 545 | |||
| 546 | *depth = call->depth; | ||
| 547 | } | ||
| 521 | 548 | ||
| 522 | /* No overhead */ | 549 | /* No overhead */ |
| 523 | ret = print_graph_overhead(-1, s); | 550 | ret = print_graph_overhead(-1, s); |
| @@ -554,24 +581,24 @@ print_graph_entry_nested(struct ftrace_graph_ent_entry *entry, | |||
| 554 | } | 581 | } |
| 555 | 582 | ||
| 556 | static enum print_line_t | 583 | static enum print_line_t |
| 557 | print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, | 584 | print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, |
| 558 | struct trace_iterator *iter) | 585 | int type, unsigned long addr) |
| 559 | { | 586 | { |
| 560 | int ret; | 587 | struct fgraph_data *data = iter->private; |
| 561 | int cpu = iter->cpu; | ||
| 562 | pid_t *last_entry = iter->private; | ||
| 563 | struct trace_entry *ent = iter->ent; | 588 | struct trace_entry *ent = iter->ent; |
| 564 | struct ftrace_graph_ent *call = &field->graph_ent; | 589 | int cpu = iter->cpu; |
| 565 | struct ftrace_graph_ret_entry *leaf_ret; | 590 | int ret; |
| 566 | 591 | ||
| 567 | /* Pid */ | 592 | /* Pid */ |
| 568 | if (verif_pid(s, ent->pid, cpu, last_entry) == TRACE_TYPE_PARTIAL_LINE) | 593 | if (verif_pid(s, ent->pid, cpu, data) == TRACE_TYPE_PARTIAL_LINE) |
| 569 | return TRACE_TYPE_PARTIAL_LINE; | 594 | return TRACE_TYPE_PARTIAL_LINE; |
| 570 | 595 | ||
| 571 | /* Interrupt */ | 596 | if (type) { |
| 572 | ret = print_graph_irq(iter, call->func, TRACE_GRAPH_ENT, cpu, ent->pid); | 597 | /* Interrupt */ |
| 573 | if (ret == TRACE_TYPE_PARTIAL_LINE) | 598 | ret = print_graph_irq(iter, addr, type, cpu, ent->pid); |
| 574 | return TRACE_TYPE_PARTIAL_LINE; | 599 | if (ret == TRACE_TYPE_PARTIAL_LINE) |
| 600 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 601 | } | ||
| 575 | 602 | ||
| 576 | /* Absolute time */ | 603 | /* Absolute time */ |
| 577 | if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) { | 604 | if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) { |
| @@ -598,11 +625,25 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, | |||
| 598 | return TRACE_TYPE_PARTIAL_LINE; | 625 | return TRACE_TYPE_PARTIAL_LINE; |
| 599 | } | 626 | } |
| 600 | 627 | ||
| 628 | return 0; | ||
| 629 | } | ||
| 630 | |||
| 631 | static enum print_line_t | ||
| 632 | print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, | ||
| 633 | struct trace_iterator *iter) | ||
| 634 | { | ||
| 635 | int cpu = iter->cpu; | ||
| 636 | struct ftrace_graph_ent *call = &field->graph_ent; | ||
| 637 | struct ftrace_graph_ret_entry *leaf_ret; | ||
| 638 | |||
| 639 | if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func)) | ||
| 640 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 641 | |||
| 601 | leaf_ret = get_return_for_leaf(iter, field); | 642 | leaf_ret = get_return_for_leaf(iter, field); |
| 602 | if (leaf_ret) | 643 | if (leaf_ret) |
| 603 | return print_graph_entry_leaf(iter, field, leaf_ret, s); | 644 | return print_graph_entry_leaf(iter, field, leaf_ret, s); |
| 604 | else | 645 | else |
| 605 | return print_graph_entry_nested(field, s, iter->ent->pid, cpu); | 646 | return print_graph_entry_nested(iter, field, s, cpu); |
| 606 | 647 | ||
| 607 | } | 648 | } |
| 608 | 649 | ||
| @@ -610,40 +651,27 @@ static enum print_line_t | |||
| 610 | print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, | 651 | print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, |
| 611 | struct trace_entry *ent, struct trace_iterator *iter) | 652 | struct trace_entry *ent, struct trace_iterator *iter) |
| 612 | { | 653 | { |
| 613 | int i; | ||
| 614 | int ret; | ||
| 615 | int cpu = iter->cpu; | ||
| 616 | pid_t *last_pid = iter->private, pid = ent->pid; | ||
| 617 | unsigned long long duration = trace->rettime - trace->calltime; | 654 | unsigned long long duration = trace->rettime - trace->calltime; |
| 655 | struct fgraph_data *data = iter->private; | ||
| 656 | pid_t pid = ent->pid; | ||
| 657 | int cpu = iter->cpu; | ||
| 658 | int ret; | ||
| 659 | int i; | ||
| 618 | 660 | ||
| 619 | /* Pid */ | 661 | if (data) { |
| 620 | if (verif_pid(s, pid, cpu, last_pid) == TRACE_TYPE_PARTIAL_LINE) | 662 | int cpu = iter->cpu; |
| 621 | return TRACE_TYPE_PARTIAL_LINE; | 663 | int *depth = &(per_cpu_ptr(data, cpu)->depth); |
| 622 | |||
| 623 | /* Absolute time */ | ||
| 624 | if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) { | ||
| 625 | ret = print_graph_abs_time(iter->ts, s); | ||
| 626 | if (!ret) | ||
| 627 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 628 | } | ||
| 629 | 664 | ||
| 630 | /* Cpu */ | 665 | /* |
| 631 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { | 666 | * Comments display at + 1 to depth. This is the |
| 632 | ret = print_graph_cpu(s, cpu); | 667 | * return from a function, we now want the comments |
| 633 | if (ret == TRACE_TYPE_PARTIAL_LINE) | 668 | * to display at the same level of the bracket. |
| 634 | return TRACE_TYPE_PARTIAL_LINE; | 669 | */ |
| 670 | *depth = trace->depth - 1; | ||
| 635 | } | 671 | } |
| 636 | 672 | ||
| 637 | /* Proc */ | 673 | if (print_graph_prologue(iter, s, 0, 0)) |
| 638 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { | 674 | return TRACE_TYPE_PARTIAL_LINE; |
| 639 | ret = print_graph_proc(s, ent->pid); | ||
| 640 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
| 641 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 642 | |||
| 643 | ret = trace_seq_printf(s, " | "); | ||
| 644 | if (!ret) | ||
| 645 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 646 | } | ||
| 647 | 675 | ||
| 648 | /* Overhead */ | 676 | /* Overhead */ |
| 649 | ret = print_graph_overhead(duration, s); | 677 | ret = print_graph_overhead(duration, s); |
| @@ -684,42 +712,21 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, | |||
| 684 | } | 712 | } |
| 685 | 713 | ||
| 686 | static enum print_line_t | 714 | static enum print_line_t |
| 687 | print_graph_comment(struct bprint_entry *trace, struct trace_seq *s, | 715 | print_graph_comment(struct trace_seq *s, struct trace_entry *ent, |
| 688 | struct trace_entry *ent, struct trace_iterator *iter) | 716 | struct trace_iterator *iter) |
| 689 | { | 717 | { |
| 690 | int i; | 718 | unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); |
| 719 | struct fgraph_data *data = iter->private; | ||
| 720 | struct trace_event *event; | ||
| 721 | int depth = 0; | ||
| 691 | int ret; | 722 | int ret; |
| 692 | int cpu = iter->cpu; | 723 | int i; |
| 693 | pid_t *last_pid = iter->private; | ||
| 694 | |||
| 695 | /* Pid */ | ||
| 696 | if (verif_pid(s, ent->pid, cpu, last_pid) == TRACE_TYPE_PARTIAL_LINE) | ||
| 697 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 698 | |||
| 699 | /* Absolute time */ | ||
| 700 | if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) { | ||
| 701 | ret = print_graph_abs_time(iter->ts, s); | ||
| 702 | if (!ret) | ||
| 703 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 704 | } | ||
| 705 | |||
| 706 | /* Cpu */ | ||
| 707 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { | ||
| 708 | ret = print_graph_cpu(s, cpu); | ||
| 709 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
| 710 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 711 | } | ||
| 712 | 724 | ||
| 713 | /* Proc */ | 725 | if (data) |
| 714 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { | 726 | depth = per_cpu_ptr(data, iter->cpu)->depth; |
| 715 | ret = print_graph_proc(s, ent->pid); | ||
| 716 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
| 717 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 718 | 727 | ||
| 719 | ret = trace_seq_printf(s, " | "); | 728 | if (print_graph_prologue(iter, s, 0, 0)) |
| 720 | if (!ret) | 729 | return TRACE_TYPE_PARTIAL_LINE; |
| 721 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 722 | } | ||
| 723 | 730 | ||
| 724 | /* No overhead */ | 731 | /* No overhead */ |
| 725 | ret = print_graph_overhead(-1, s); | 732 | ret = print_graph_overhead(-1, s); |
| @@ -734,8 +741,8 @@ print_graph_comment(struct bprint_entry *trace, struct trace_seq *s, | |||
| 734 | } | 741 | } |
| 735 | 742 | ||
| 736 | /* Indentation */ | 743 | /* Indentation */ |
| 737 | if (trace->depth > 0) | 744 | if (depth > 0) |
| 738 | for (i = 0; i < (trace->depth + 1) * TRACE_GRAPH_INDENT; i++) { | 745 | for (i = 0; i < (depth + 1) * TRACE_GRAPH_INDENT; i++) { |
| 739 | ret = trace_seq_printf(s, " "); | 746 | ret = trace_seq_printf(s, " "); |
| 740 | if (!ret) | 747 | if (!ret) |
| 741 | return TRACE_TYPE_PARTIAL_LINE; | 748 | return TRACE_TYPE_PARTIAL_LINE; |
| @@ -746,9 +753,26 @@ print_graph_comment(struct bprint_entry *trace, struct trace_seq *s, | |||
| 746 | if (!ret) | 753 | if (!ret) |
| 747 | return TRACE_TYPE_PARTIAL_LINE; | 754 | return TRACE_TYPE_PARTIAL_LINE; |
| 748 | 755 | ||
| 749 | ret = trace_seq_bprintf(s, trace->fmt, trace->buf); | 756 | switch (iter->ent->type) { |
| 750 | if (!ret) | 757 | case TRACE_BPRINT: |
| 751 | return TRACE_TYPE_PARTIAL_LINE; | 758 | ret = trace_print_bprintk_msg_only(iter); |
| 759 | if (ret != TRACE_TYPE_HANDLED) | ||
| 760 | return ret; | ||
| 761 | break; | ||
| 762 | case TRACE_PRINT: | ||
| 763 | ret = trace_print_printk_msg_only(iter); | ||
| 764 | if (ret != TRACE_TYPE_HANDLED) | ||
| 765 | return ret; | ||
| 766 | break; | ||
| 767 | default: | ||
| 768 | event = ftrace_find_event(ent->type); | ||
| 769 | if (!event) | ||
| 770 | return TRACE_TYPE_UNHANDLED; | ||
| 771 | |||
| 772 | ret = event->trace(iter, sym_flags); | ||
| 773 | if (ret != TRACE_TYPE_HANDLED) | ||
| 774 | return ret; | ||
| 775 | } | ||
| 752 | 776 | ||
| 753 | /* Strip ending newline */ | 777 | /* Strip ending newline */ |
| 754 | if (s->buffer[s->len - 1] == '\n') { | 778 | if (s->buffer[s->len - 1] == '\n') { |
| @@ -767,8 +791,8 @@ print_graph_comment(struct bprint_entry *trace, struct trace_seq *s, | |||
| 767 | enum print_line_t | 791 | enum print_line_t |
| 768 | print_graph_function(struct trace_iterator *iter) | 792 | print_graph_function(struct trace_iterator *iter) |
| 769 | { | 793 | { |
| 770 | struct trace_seq *s = &iter->seq; | ||
| 771 | struct trace_entry *entry = iter->ent; | 794 | struct trace_entry *entry = iter->ent; |
| 795 | struct trace_seq *s = &iter->seq; | ||
| 772 | 796 | ||
| 773 | switch (entry->type) { | 797 | switch (entry->type) { |
| 774 | case TRACE_GRAPH_ENT: { | 798 | case TRACE_GRAPH_ENT: { |
| @@ -781,14 +805,11 @@ print_graph_function(struct trace_iterator *iter) | |||
| 781 | trace_assign_type(field, entry); | 805 | trace_assign_type(field, entry); |
| 782 | return print_graph_return(&field->ret, s, entry, iter); | 806 | return print_graph_return(&field->ret, s, entry, iter); |
| 783 | } | 807 | } |
| 784 | case TRACE_BPRINT: { | ||
| 785 | struct bprint_entry *field; | ||
| 786 | trace_assign_type(field, entry); | ||
| 787 | return print_graph_comment(field, s, entry, iter); | ||
| 788 | } | ||
| 789 | default: | 808 | default: |
| 790 | return TRACE_TYPE_UNHANDLED; | 809 | return print_graph_comment(s, entry, iter); |
| 791 | } | 810 | } |
| 811 | |||
| 812 | return TRACE_TYPE_HANDLED; | ||
| 792 | } | 813 | } |
| 793 | 814 | ||
| 794 | static void print_graph_headers(struct seq_file *s) | 815 | static void print_graph_headers(struct seq_file *s) |
| @@ -820,19 +841,21 @@ static void print_graph_headers(struct seq_file *s) | |||
| 820 | 841 | ||
| 821 | static void graph_trace_open(struct trace_iterator *iter) | 842 | static void graph_trace_open(struct trace_iterator *iter) |
| 822 | { | 843 | { |
| 823 | /* pid on the last trace processed */ | 844 | /* pid and depth on the last trace processed */ |
| 824 | pid_t *last_pid = alloc_percpu(pid_t); | 845 | struct fgraph_data *data = alloc_percpu(struct fgraph_data); |
| 825 | int cpu; | 846 | int cpu; |
| 826 | 847 | ||
| 827 | if (!last_pid) | 848 | if (!data) |
| 828 | pr_warning("function graph tracer: not enough memory\n"); | 849 | pr_warning("function graph tracer: not enough memory\n"); |
| 829 | else | 850 | else |
| 830 | for_each_possible_cpu(cpu) { | 851 | for_each_possible_cpu(cpu) { |
| 831 | pid_t *pid = per_cpu_ptr(last_pid, cpu); | 852 | pid_t *pid = &(per_cpu_ptr(data, cpu)->last_pid); |
| 853 | int *depth = &(per_cpu_ptr(data, cpu)->depth); | ||
| 832 | *pid = -1; | 854 | *pid = -1; |
| 855 | *depth = 0; | ||
| 833 | } | 856 | } |
| 834 | 857 | ||
| 835 | iter->private = last_pid; | 858 | iter->private = data; |
| 836 | } | 859 | } |
| 837 | 860 | ||
| 838 | static void graph_trace_close(struct trace_iterator *iter) | 861 | static void graph_trace_close(struct trace_iterator *iter) |
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c index f095916e477f..8e37fcddd8b4 100644 --- a/kernel/trace/trace_mmiotrace.c +++ b/kernel/trace/trace_mmiotrace.c | |||
| @@ -359,5 +359,5 @@ void mmio_trace_mapping(struct mmiotrace_map *map) | |||
| 359 | 359 | ||
| 360 | int mmio_trace_printk(const char *fmt, va_list args) | 360 | int mmio_trace_printk(const char *fmt, va_list args) |
| 361 | { | 361 | { |
| 362 | return trace_vprintk(0, -1, fmt, args); | 362 | return trace_vprintk(0, fmt, args); |
| 363 | } | 363 | } |
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 6a4c9dea191e..b45141748af5 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c | |||
| @@ -19,6 +19,38 @@ static struct hlist_head event_hash[EVENT_HASHSIZE] __read_mostly; | |||
| 19 | 19 | ||
| 20 | static int next_event_type = __TRACE_LAST_TYPE + 1; | 20 | static int next_event_type = __TRACE_LAST_TYPE + 1; |
| 21 | 21 | ||
| 22 | enum print_line_t trace_print_bprintk_msg_only(struct trace_iterator *iter) | ||
| 23 | { | ||
| 24 | struct trace_seq *s = &iter->seq; | ||
| 25 | struct trace_entry *entry = iter->ent; | ||
| 26 | struct bprint_entry *field; | ||
| 27 | int ret; | ||
| 28 | |||
| 29 | trace_assign_type(field, entry); | ||
| 30 | |||
| 31 | ret = trace_seq_bprintf(s, field->fmt, field->buf); | ||
| 32 | if (!ret) | ||
| 33 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 34 | |||
| 35 | return TRACE_TYPE_HANDLED; | ||
| 36 | } | ||
| 37 | |||
| 38 | enum print_line_t trace_print_printk_msg_only(struct trace_iterator *iter) | ||
| 39 | { | ||
| 40 | struct trace_seq *s = &iter->seq; | ||
| 41 | struct trace_entry *entry = iter->ent; | ||
| 42 | struct print_entry *field; | ||
| 43 | int ret; | ||
| 44 | |||
| 45 | trace_assign_type(field, entry); | ||
| 46 | |||
| 47 | ret = trace_seq_printf(s, "%s", field->buf); | ||
| 48 | if (!ret) | ||
| 49 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 50 | |||
| 51 | return TRACE_TYPE_HANDLED; | ||
| 52 | } | ||
| 53 | |||
| 22 | /** | 54 | /** |
| 23 | * trace_seq_printf - sequence printing of trace information | 55 | * trace_seq_printf - sequence printing of trace information |
| 24 | * @s: trace sequence descriptor | 56 | * @s: trace sequence descriptor |
diff --git a/kernel/trace/trace_output.h b/kernel/trace/trace_output.h index 3b90e6ade1aa..35c422fb51a9 100644 --- a/kernel/trace/trace_output.h +++ b/kernel/trace/trace_output.h | |||
| @@ -15,6 +15,11 @@ struct trace_event { | |||
| 15 | trace_print_func binary; | 15 | trace_print_func binary; |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | extern enum print_line_t | ||
| 19 | trace_print_bprintk_msg_only(struct trace_iterator *iter); | ||
| 20 | extern enum print_line_t | ||
| 21 | trace_print_printk_msg_only(struct trace_iterator *iter); | ||
| 22 | |||
| 18 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) | 23 | extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) |
| 19 | __attribute__ ((format (printf, 2, 3))); | 24 | __attribute__ ((format (printf, 2, 3))); |
| 20 | extern int | 25 | extern int |
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index 486785214e3e..eb81556107fe 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c | |||
| @@ -112,7 +112,7 @@ int __trace_bprintk(unsigned long ip, const char *fmt, ...) | |||
| 112 | return 0; | 112 | return 0; |
| 113 | 113 | ||
| 114 | va_start(ap, fmt); | 114 | va_start(ap, fmt); |
| 115 | ret = trace_vbprintk(ip, task_curr_ret_stack(current), fmt, ap); | 115 | ret = trace_vbprintk(ip, fmt, ap); |
| 116 | va_end(ap); | 116 | va_end(ap); |
| 117 | return ret; | 117 | return ret; |
| 118 | } | 118 | } |
| @@ -126,7 +126,7 @@ int __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap) | |||
| 126 | if (!(trace_flags & TRACE_ITER_PRINTK)) | 126 | if (!(trace_flags & TRACE_ITER_PRINTK)) |
| 127 | return 0; | 127 | return 0; |
| 128 | 128 | ||
| 129 | return trace_vbprintk(ip, task_curr_ret_stack(current), fmt, ap); | 129 | return trace_vbprintk(ip, fmt, ap); |
| 130 | } | 130 | } |
| 131 | EXPORT_SYMBOL_GPL(__ftrace_vbprintk); | 131 | EXPORT_SYMBOL_GPL(__ftrace_vbprintk); |
| 132 | 132 | ||
| @@ -139,7 +139,7 @@ int __trace_printk(unsigned long ip, const char *fmt, ...) | |||
| 139 | return 0; | 139 | return 0; |
| 140 | 140 | ||
| 141 | va_start(ap, fmt); | 141 | va_start(ap, fmt); |
| 142 | ret = trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap); | 142 | ret = trace_vprintk(ip, fmt, ap); |
| 143 | va_end(ap); | 143 | va_end(ap); |
| 144 | return ret; | 144 | return ret; |
| 145 | } | 145 | } |
| @@ -150,7 +150,7 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap) | |||
| 150 | if (!(trace_flags & TRACE_ITER_PRINTK)) | 150 | if (!(trace_flags & TRACE_ITER_PRINTK)) |
| 151 | return 0; | 151 | return 0; |
| 152 | 152 | ||
| 153 | return trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap); | 153 | return trace_vprintk(ip, fmt, ap); |
| 154 | } | 154 | } |
| 155 | EXPORT_SYMBOL_GPL(__ftrace_vprintk); | 155 | EXPORT_SYMBOL_GPL(__ftrace_vprintk); |
| 156 | 156 | ||
