Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+95 −18
Original line number Diff line number Diff line
@@ -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);
}

struct ftrace_buffer_info {
	struct trace_iterator	iter;
	void			*spare;
	unsigned int		read;
};

#ifdef CONFIG_TRACER_SNAPSHOT
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)
	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 */


@@ -4402,14 +4437,17 @@ static const struct file_operations snapshot_fops = {
	.llseek		= tracing_seek,
	.release	= tracing_snapshot_release,
};
#endif /* CONFIG_TRACER_SNAPSHOT */

struct ftrace_buffer_info {
	struct trace_iterator	iter;
	void			*spare;
	unsigned int		read;
static const struct file_operations snapshot_raw_fops = {
	.open		= snapshot_raw_open,
	.read		= tracing_buffers_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)
{
	struct trace_cpu *tc = inode->i_private;
@@ -4452,16 +4490,26 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,
	struct ftrace_buffer_info *info = filp->private_data;
	struct trace_iterator *iter = &info->iter;
	ssize_t ret;
	size_t size;
	ssize_t size;

	if (!count)
		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)
		info->spare = ring_buffer_alloc_read_page(iter->trace_buffer->buffer,
							  iter->cpu_file);
	size = -ENOMEM;
	if (!info->spare)
		return -ENOMEM;
		goto out_unlock;

	/* Do we have previous read data to read? */
	if (info->read < PAGE_SIZE)
@@ -4477,31 +4525,42 @@ tracing_buffers_read(struct file *filp, char __user *ubuf,

	if (ret < 0) {
		if (trace_empty(iter)) {
			if ((filp->f_flags & O_NONBLOCK))
				return -EAGAIN;
			if ((filp->f_flags & O_NONBLOCK)) {
				size = -EAGAIN;
				goto out_unlock;
			}
			mutex_unlock(&trace_types_lock);
			iter->trace->wait_pipe(iter);
			if (signal_pending(current))
				return -EINTR;
			mutex_lock(&trace_types_lock);
			if (signal_pending(current)) {
				size = -EINTR;
				goto out_unlock;
			}
			goto again;
		}
		return 0;
		size = 0;
		goto out_unlock;
	}

	info->read = 0;

 read:
	size = PAGE_SIZE - info->read;
	if (size > count)
		size = count;

	ret = copy_to_user(ubuf, info->spare + info->read, size);
	if (ret == size)
		return -EFAULT;
	if (ret == size) {
		size = -EFAULT;
		goto out_unlock;
	}
	size -= ret;

	*ppos += size;
	info->read += size;

 out_unlock:
	mutex_unlock(&trace_types_lock);

	return size;
}

@@ -4591,10 +4650,21 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
	};
	struct buffer_ref *ref;
	int entries, size, i;
	size_t ret;
	ssize_t ret;

	if (splice_grow_spd(pipe, &spd))
		return -ENOMEM;
	mutex_lock(&trace_types_lock);

#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)) {
		ret = -EINVAL;
@@ -4666,7 +4736,9 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
			ret = -EAGAIN;
			goto out;
		}
		mutex_unlock(&trace_types_lock);
		iter->trace->wait_pipe(iter);
		mutex_lock(&trace_types_lock);
		if (signal_pending(current)) {
			ret = -EINTR;
			goto out;
@@ -4677,6 +4749,8 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
	ret = splice_to_pipe(pipe, &spd);
	splice_shrink_spd(&spd);
out:
	mutex_unlock(&trace_types_lock);

	return ret;
}

@@ -4880,6 +4954,9 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu)
#ifdef CONFIG_TRACER_SNAPSHOT
	trace_create_file("snapshot", 0644, d_cpu,
			  (void *)&data->trace_cpu, &snapshot_fops);

	trace_create_file("snapshot_raw", 0444, d_cpu,
			(void *)&data->trace_cpu, &snapshot_raw_fops);
#endif
}