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 Original line 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);
	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)
	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 = {
	.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,
	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,


	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,
	};
	};
	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,
			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,
	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)
#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
}
}