Commit 6de58e62 authored by Steven Rostedt (Red Hat)'s avatar Steven Rostedt (Red Hat) Committed by Steven Rostedt

tracing: Add snapshot_raw to extract the raw data from snapshot

Add a 'snapshot_raw' per_cpu file that allows tools to read the raw
binary data of the snapshot buffer.
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 0b85ffc2
...@@ -4206,6 +4206,12 @@ static int tracing_clock_open(struct inode *inode, struct file *file) ...@@ -4206,6 +4206,12 @@ static int tracing_clock_open(struct inode *inode, struct file *file)
return single_open(file, tracing_clock_show, inode->i_private); return single_open(file, tracing_clock_show, inode->i_private);
} }
struct ftrace_buffer_info {
struct trace_iterator iter;
void *spare;
unsigned int read;
};
#ifdef CONFIG_TRACER_SNAPSHOT #ifdef CONFIG_TRACER_SNAPSHOT
static int tracing_snapshot_open(struct inode *inode, struct file *file) static int tracing_snapshot_open(struct inode *inode, struct file *file)
{ {
...@@ -4336,6 +4342,35 @@ static int tracing_snapshot_release(struct inode *inode, struct file *file) ...@@ -4336,6 +4342,35 @@ static int tracing_snapshot_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static int tracing_buffers_open(struct inode *inode, struct file *filp);
static ssize_t tracing_buffers_read(struct file *filp, char __user *ubuf,
size_t count, loff_t *ppos);
static int tracing_buffers_release(struct inode *inode, struct file *file);
static ssize_t tracing_buffers_splice_read(struct file *file, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len, unsigned int flags);
static int snapshot_raw_open(struct inode *inode, struct file *filp)
{
struct ftrace_buffer_info *info;
int ret;
ret = tracing_buffers_open(inode, filp);
if (ret < 0)
return ret;
info = filp->private_data;
if (info->iter.trace->use_max_tr) {
tracing_buffers_release(inode, filp);
return -EBUSY;
}
info->iter.snapshot = true;
info->iter.trace_buffer = &info->iter.tr->max_buffer;
return ret;
}
#endif /* CONFIG_TRACER_SNAPSHOT */ #endif /* CONFIG_TRACER_SNAPSHOT */
...@@ -4402,14 +4437,17 @@ static const struct file_operations snapshot_fops = { ...@@ -4402,14 +4437,17 @@ static const struct file_operations snapshot_fops = {
.llseek = tracing_seek, .llseek = tracing_seek,
.release = tracing_snapshot_release, .release = tracing_snapshot_release,
}; };
#endif /* CONFIG_TRACER_SNAPSHOT */
struct ftrace_buffer_info { static const struct file_operations snapshot_raw_fops = {
struct trace_iterator iter; .open = snapshot_raw_open,
void *spare; .read = tracing_buffers_read,
unsigned int read; .release = tracing_buffers_release,
.splice_read = tracing_buffers_splice_read,
.llseek = no_llseek,
}; };
#endif /* CONFIG_TRACER_SNAPSHOT */
static int tracing_buffers_open(struct inode *inode, struct file *filp) static int tracing_buffers_open(struct inode *inode, struct file *filp)
{ {
struct trace_cpu *tc = inode->i_private; struct trace_cpu *tc = inode->i_private;
...@@ -4452,16 +4490,26 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, ...@@ -4452,16 +4490,26 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
struct ftrace_buffer_info *info = filp->private_data; struct ftrace_buffer_info *info = filp->private_data;
struct trace_iterator *iter = &info->iter; struct trace_iterator *iter = &info->iter;
ssize_t ret; ssize_t ret;
size_t size; ssize_t size;
if (!count) if (!count)
return 0; return 0;
mutex_lock(&trace_types_lock);
#ifdef CONFIG_TRACER_MAX_TRACE
if (iter->snapshot && iter->tr->current_trace->use_max_tr) {
size = -EBUSY;
goto out_unlock;
}
#endif
if (!info->spare) if (!info->spare)
info->spare = ring_buffer_alloc_read_page(iter->trace_buffer->buffer, info->spare = ring_buffer_alloc_read_page(iter->trace_buffer->buffer,
iter->cpu_file); iter->cpu_file);
size = -ENOMEM;
if (!info->spare) if (!info->spare)
return -ENOMEM; goto out_unlock;
/* Do we have previous read data to read? */ /* Do we have previous read data to read? */
if (info->read < PAGE_SIZE) if (info->read < PAGE_SIZE)
...@@ -4477,31 +4525,42 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, ...@@ -4477,31 +4525,42 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
if (ret < 0) { if (ret < 0) {
if (trace_empty(iter)) { if (trace_empty(iter)) {
if ((filp->f_flags & O_NONBLOCK)) if ((filp->f_flags & O_NONBLOCK)) {
return -EAGAIN; size = -EAGAIN;
goto out_unlock;
}
mutex_unlock(&trace_types_lock);
iter->trace->wait_pipe(iter); iter->trace->wait_pipe(iter);
if (signal_pending(current)) mutex_lock(&trace_types_lock);
return -EINTR; if (signal_pending(current)) {
size = -EINTR;
goto out_unlock;
}
goto again; goto again;
} }
return 0; size = 0;
goto out_unlock;
} }
info->read = 0; info->read = 0;
read: read:
size = PAGE_SIZE - info->read; size = PAGE_SIZE - info->read;
if (size > count) if (size > count)
size = count; size = count;
ret = copy_to_user(ubuf, info->spare + info->read, size); ret = copy_to_user(ubuf, info->spare + info->read, size);
if (ret == size) if (ret == size) {
return -EFAULT; size = -EFAULT;
goto out_unlock;
}
size -= ret; size -= ret;
*ppos += size; *ppos += size;
info->read += size; info->read += size;
out_unlock:
mutex_unlock(&trace_types_lock);
return size; return size;
} }
...@@ -4591,10 +4650,21 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, ...@@ -4591,10 +4650,21 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
}; };
struct buffer_ref *ref; struct buffer_ref *ref;
int entries, size, i; int entries, size, i;
size_t ret; ssize_t ret;
if (splice_grow_spd(pipe, &spd)) mutex_lock(&trace_types_lock);
return -ENOMEM;
#ifdef CONFIG_TRACER_MAX_TRACE
if (iter->snapshot && iter->tr->current_trace->use_max_tr) {
ret = -EBUSY;
goto out;
}
#endif
if (splice_grow_spd(pipe, &spd)) {
ret = -ENOMEM;
goto out;
}
if (*ppos & (PAGE_SIZE - 1)) { if (*ppos & (PAGE_SIZE - 1)) {
ret = -EINVAL; ret = -EINVAL;
...@@ -4666,7 +4736,9 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, ...@@ -4666,7 +4736,9 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
ret = -EAGAIN; ret = -EAGAIN;
goto out; goto out;
} }
mutex_unlock(&trace_types_lock);
iter->trace->wait_pipe(iter); iter->trace->wait_pipe(iter);
mutex_lock(&trace_types_lock);
if (signal_pending(current)) { if (signal_pending(current)) {
ret = -EINTR; ret = -EINTR;
goto out; goto out;
...@@ -4677,6 +4749,8 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, ...@@ -4677,6 +4749,8 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
ret = splice_to_pipe(pipe, &spd); ret = splice_to_pipe(pipe, &spd);
splice_shrink_spd(&spd); splice_shrink_spd(&spd);
out: out:
mutex_unlock(&trace_types_lock);
return ret; return ret;
} }
...@@ -4880,6 +4954,9 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) ...@@ -4880,6 +4954,9 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
#ifdef CONFIG_TRACER_SNAPSHOT #ifdef CONFIG_TRACER_SNAPSHOT
trace_create_file("snapshot", 0644, d_cpu, trace_create_file("snapshot", 0644, d_cpu,
(void *)&data->trace_cpu, &snapshot_fops); (void *)&data->trace_cpu, &snapshot_fops);
trace_create_file("snapshot_raw", 0444, d_cpu,
(void *)&data->trace_cpu, &snapshot_raw_fops);
#endif #endif
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment