aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_printk.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-03-12 14:23:17 -0400
committerSteven Rostedt <srostedt@redhat.com>2009-03-12 21:15:01 -0400
commit7975a2be16dd42df2cab80c80cb6ece382edb6ec (patch)
treeb9fdae6b0f3cd7c902beb8bf995efe2d827e02a2 /kernel/trace/trace_printk.c
parente9fb2b6d5845e24f104713591286b6f39761c027 (diff)
tracing: export trace formats to user space
The binary printk saves a pointer to the format string in the ring buffer. On output, the format is processed. But if the user is reading the ring buffer through a binary interface, the pointer is meaningless. This patch creates a file called printk_formats that maps the pointers to the formats. # cat /debug/tracing/printk_formats 0xffffffff80713d40 : "irq_handler_entry: irq=%d handler=%s\n" 0xffffffff80713d48 : "lock_acquire: %s%s%s\n" 0xffffffff80713d50 : "lock_release: %s\n" Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel/trace/trace_printk.c')
-rw-r--r--kernel/trace/trace_printk.c119
1 files changed, 114 insertions, 5 deletions
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
index f307a11e2332..486785214e3e 100644
--- a/kernel/trace/trace_printk.c
+++ b/kernel/trace/trace_printk.c
@@ -4,18 +4,19 @@
4 * Copyright (C) 2008 Lai Jiangshan <laijs@cn.fujitsu.com> 4 * Copyright (C) 2008 Lai Jiangshan <laijs@cn.fujitsu.com>
5 * 5 *
6 */ 6 */
7#include <linux/seq_file.h>
8#include <linux/debugfs.h>
9#include <linux/uaccess.h>
7#include <linux/kernel.h> 10#include <linux/kernel.h>
8#include <linux/ftrace.h> 11#include <linux/ftrace.h>
9#include <linux/string.h> 12#include <linux/string.h>
13#include <linux/module.h>
14#include <linux/marker.h>
15#include <linux/mutex.h>
10#include <linux/ctype.h> 16#include <linux/ctype.h>
11#include <linux/list.h> 17#include <linux/list.h>
12#include <linux/mutex.h>
13#include <linux/slab.h> 18#include <linux/slab.h>
14#include <linux/module.h>
15#include <linux/seq_file.h>
16#include <linux/fs.h> 19#include <linux/fs.h>
17#include <linux/marker.h>
18#include <linux/uaccess.h>
19 20
20#include "trace.h" 21#include "trace.h"
21 22
@@ -153,6 +154,114 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
153} 154}
154EXPORT_SYMBOL_GPL(__ftrace_vprintk); 155EXPORT_SYMBOL_GPL(__ftrace_vprintk);
155 156
157static void *
158t_next(struct seq_file *m, void *v, loff_t *pos)
159{
160 const char **fmt = m->private;
161 const char **next = fmt;
162
163 (*pos)++;
164
165 if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt)
166 return NULL;
167
168 next = fmt;
169 m->private = ++next;
170
171 return fmt;
172}
173
174static void *t_start(struct seq_file *m, loff_t *pos)
175{
176 return t_next(m, NULL, pos);
177}
178
179static int t_show(struct seq_file *m, void *v)
180{
181 const char **fmt = v;
182 const char *str = *fmt;
183 int i;
184
185 seq_printf(m, "0x%lx : \"", (unsigned long)fmt);
186
187 /*
188 * Tabs and new lines need to be converted.
189 */
190 for (i = 0; str[i]; i++) {
191 switch (str[i]) {
192 case '\n':
193 seq_puts(m, "\\n");
194 break;
195 case '\t':
196 seq_puts(m, "\\t");
197 break;
198 case '\\':
199 seq_puts(m, "\\");
200 break;
201 case '"':
202 seq_puts(m, "\\\"");
203 break;
204 default:
205 seq_putc(m, str[i]);
206 }
207 }
208 seq_puts(m, "\"\n");
209
210 return 0;
211}
212
213static void t_stop(struct seq_file *m, void *p)
214{
215}
216
217static const struct seq_operations show_format_seq_ops = {
218 .start = t_start,
219 .next = t_next,
220 .show = t_show,
221 .stop = t_stop,
222};
223
224static int
225ftrace_formats_open(struct inode *inode, struct file *file)
226{
227 int ret;
228
229 ret = seq_open(file, &show_format_seq_ops);
230 if (!ret) {
231 struct seq_file *m = file->private_data;
232
233 m->private = __start___trace_bprintk_fmt;
234 }
235 return ret;
236}
237
238static const struct file_operations ftrace_formats_fops = {
239 .open = ftrace_formats_open,
240 .read = seq_read,
241 .llseek = seq_lseek,
242 .release = seq_release,
243};
244
245static __init int init_trace_printk_function_export(void)
246{
247 struct dentry *d_tracer;
248 struct dentry *entry;
249
250 d_tracer = tracing_init_dentry();
251 if (!d_tracer)
252 return 0;
253
254 entry = debugfs_create_file("printk_formats", 0444, d_tracer,
255 NULL, &ftrace_formats_fops);
256 if (!entry)
257 pr_warning("Could not create debugfs "
258 "'printk_formats' entry\n");
259
260 return 0;
261}
262
263fs_initcall(init_trace_printk_function_export);
264
156static __init int init_trace_printk(void) 265static __init int init_trace_printk(void)
157{ 266{
158 return register_module_notifier(&module_trace_bprintk_format_nb); 267 return register_module_notifier(&module_trace_bprintk_format_nb);