ftrace: inject markers via trace_marker file
Allow a user to inject a marker (TRACE_PRINT entry) into the trace ring buffer. The related file operations are derived from code by Frédéric Weisbecker <fweisbec@gmail.com>. Signed-off-by: Pekka Paalanen <pq@iki.fi> Acked-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Родитель
4427414170
Коммит
5bf9a1ee35
|
@ -36,7 +36,7 @@ $ mount -t debugfs debugfs /debug
|
|||
$ echo mmiotrace > /debug/tracing/current_tracer
|
||||
$ cat /debug/tracing/trace_pipe > mydump.txt &
|
||||
Start X or whatever.
|
||||
$ echo "X is up" > /debug/tracing/marker
|
||||
$ echo "X is up" > /debug/tracing/trace_marker
|
||||
$ echo none > /debug/tracing/current_tracer
|
||||
Check for lost events.
|
||||
|
||||
|
@ -59,9 +59,8 @@ The 'cat' process should stay running (sleeping) in the background.
|
|||
Load the driver you want to trace and use it. Mmiotrace will only catch MMIO
|
||||
accesses to areas that are ioremapped while mmiotrace is active.
|
||||
|
||||
[Unimplemented feature:]
|
||||
During tracing you can place comments (markers) into the trace by
|
||||
$ echo "X is up" > /debug/tracing/marker
|
||||
$ echo "X is up" > /debug/tracing/trace_marker
|
||||
This makes it easier to see which part of the (huge) trace corresponds to
|
||||
which action. It is recommended to place descriptive markers about what you
|
||||
do.
|
||||
|
|
|
@ -2879,6 +2879,66 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,
|
|||
return cnt;
|
||||
}
|
||||
|
||||
static int tracing_open_mark(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = tracing_open_generic(inode, filp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (current_trace == &no_tracer)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mark_printk(const char *fmt, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
ret = trace_vprintk(0, fmt, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
tracing_mark_write(struct file *filp, const char __user *ubuf,
|
||||
size_t cnt, loff_t *fpos)
|
||||
{
|
||||
char *buf;
|
||||
char *end;
|
||||
struct trace_array *tr = &global_trace;
|
||||
|
||||
if (current_trace == &no_tracer || !tr->ctrl || tracing_disabled)
|
||||
return -EINVAL;
|
||||
|
||||
if (cnt > TRACE_BUF_SIZE)
|
||||
cnt = TRACE_BUF_SIZE;
|
||||
|
||||
buf = kmalloc(cnt + 1, GFP_KERNEL);
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(buf, ubuf, cnt)) {
|
||||
kfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Cut from the first nil or newline. */
|
||||
buf[cnt] = '\0';
|
||||
end = strchr(buf, '\n');
|
||||
if (end)
|
||||
*end = '\0';
|
||||
|
||||
cnt = mark_printk("%s\n", buf);
|
||||
kfree(buf);
|
||||
*fpos += cnt;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static struct file_operations tracing_max_lat_fops = {
|
||||
.open = tracing_open_generic,
|
||||
.read = tracing_max_lat_read,
|
||||
|
@ -2910,6 +2970,11 @@ static struct file_operations tracing_entries_fops = {
|
|||
.write = tracing_entries_write,
|
||||
};
|
||||
|
||||
static struct file_operations tracing_mark_fops = {
|
||||
.open = tracing_open_mark,
|
||||
.write = tracing_mark_write,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
|
||||
static ssize_t
|
||||
|
@ -3027,6 +3092,12 @@ static __init void tracer_init_debugfs(void)
|
|||
pr_warning("Could not create debugfs "
|
||||
"'trace_entries' entry\n");
|
||||
|
||||
entry = debugfs_create_file("trace_marker", 0220, d_tracer,
|
||||
NULL, &tracing_mark_fops);
|
||||
if (!entry)
|
||||
pr_warning("Could not create debugfs "
|
||||
"'trace_marker' entry\n");
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer,
|
||||
&ftrace_update_tot_cnt,
|
||||
|
@ -3040,11 +3111,6 @@ static __init void tracer_init_debugfs(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
#define TRACE_BUF_SIZE 1024
|
||||
#define TRACE_PRINT_BUF_SIZE \
|
||||
(sizeof(struct trace_field) - offsetof(struct trace_field, print.buf))
|
||||
#define TRACE_CONT_BUF_SIZE sizeof(struct trace_field)
|
||||
|
||||
int trace_vprintk(unsigned long ip, const char *fmt, va_list args)
|
||||
{
|
||||
static DEFINE_SPINLOCK(trace_buf_lock);
|
||||
|
|
|
@ -124,6 +124,10 @@ struct trace_entry {
|
|||
};
|
||||
|
||||
#define TRACE_ENTRY_SIZE sizeof(struct trace_entry)
|
||||
#define TRACE_BUF_SIZE 1024
|
||||
#define TRACE_PRINT_BUF_SIZE \
|
||||
(sizeof(struct trace_field) - offsetof(struct trace_field, print.buf))
|
||||
#define TRACE_CONT_BUF_SIZE sizeof(struct trace_field)
|
||||
|
||||
/*
|
||||
* The CPU trace array - it consists of thousands of trace entries
|
||||
|
|
Загрузка…
Ссылка в новой задаче