summaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorPekka Paalanen <pq@iki.fi>2008-09-16 21:06:42 +0200
committerIngo Molnar <mingo@elte.hu>2008-10-14 10:37:20 +0200
commit5bf9a1ee350a10feb94107de32a203d81fbbe706 (patch)
treeac6b11aaa35194aed9fe9f1403c9542d070d0c62 /kernel/trace
parentmmiotrace: remove left-over marker cruft (diff)
downloadlinux-5bf9a1ee350a10feb94107de32a203d81fbbe706.tar.xz
linux-5bf9a1ee350a10feb94107de32a203d81fbbe706.zip
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>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace.c76
-rw-r--r--kernel/trace/trace.h4
2 files changed, 75 insertions, 5 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 7e7154f77009..eee1fd964898 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -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);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 648433d18ccb..42f65d0097f0 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -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