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

Commit 9a38a885 authored by Steven Rostedt (Red Hat)'s avatar Steven Rostedt (Red Hat) Committed by Steven Rostedt
Browse files

tracing: Add a method to pass in trace_array descriptor to option files



In preparation of having the multi buffer instances having their own trace
option flags, the trace option files needs a way to not only pass in the
flag they represent, but also the trace_array descriptor.

A new field is added to the trace_array descriptor called trace_flags_index,
which is a 32 byte character array representing a bit. This array is simply
filled with the index of the array, where

  index_array[n] = n;

Then the address of this array is passed to the file callbacks instead of
the index of the flag index. Then to retrieve both the flag index and the
trace_array descriptor:

  data is the passed in argument.

  index = *(unsigned char *)data;

  data -= index;

  /* Now data points to the address of the array in the trace_array */

  tr = container_of(data, struct trace_array, trace_flags_index);

Suggested-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 983f938a
Loading
Loading
Loading
Loading
+60 −7
Original line number Original line Diff line number Diff line
@@ -6186,14 +6186,51 @@ static const struct file_operations trace_options_fops = {
	.llseek	= generic_file_llseek,
	.llseek	= generic_file_llseek,
};
};


/*
 * In order to pass in both the trace_array descriptor as well as the index
 * to the flag that the trace option file represents, the trace_array
 * has a character array of trace_flags_index[], which holds the index
 * of the bit for the flag it represents. index[0] == 0, index[1] == 1, etc.
 * The address of this character array is passed to the flag option file
 * read/write callbacks.
 *
 * In order to extract both the index and the trace_array descriptor,
 * get_tr_index() uses the following algorithm.
 *
 *   idx = *ptr;
 *
 * As the pointer itself contains the address of the index (remember
 * index[1] == 1).
 *
 * Then to get the trace_array descriptor, by subtracting that index
 * from the ptr, we get to the start of the index itself.
 *
 *   ptr - idx == &index[0]
 *
 * Then a simple container_of() from that pointer gets us to the
 * trace_array descriptor.
 */
static void get_tr_index(void *data, struct trace_array **ptr,
			 unsigned int *pindex)
{
	*pindex = *(unsigned char *)data;

	*ptr = container_of(data - *pindex, struct trace_array,
			    trace_flags_index);
}

static ssize_t
static ssize_t
trace_options_core_read(struct file *filp, char __user *ubuf, size_t cnt,
trace_options_core_read(struct file *filp, char __user *ubuf, size_t cnt,
			loff_t *ppos)
			loff_t *ppos)
{
{
	long index = (long)filp->private_data;
	void *tr_index = filp->private_data;
	struct trace_array *tr;
	unsigned int index;
	char *buf;
	char *buf;


	if (global_trace.trace_flags & (1 << index))
	get_tr_index(tr_index, &tr, &index);

	if (tr->trace_flags & (1 << index))
		buf = "1\n";
		buf = "1\n";
	else
	else
		buf = "0\n";
		buf = "0\n";
@@ -6205,11 +6242,14 @@ static ssize_t
trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
			 loff_t *ppos)
			 loff_t *ppos)
{
{
	struct trace_array *tr = &global_trace;
	void *tr_index = filp->private_data;
	long index = (long)filp->private_data;
	struct trace_array *tr;
	unsigned int index;
	unsigned long val;
	unsigned long val;
	int ret;
	int ret;


	get_tr_index(tr_index, &tr, &index);

	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
	if (ret)
	if (ret)
		return ret;
		return ret;
@@ -6339,7 +6379,8 @@ create_trace_option_core_file(struct trace_array *tr,
	if (!t_options)
	if (!t_options)
		return NULL;
		return NULL;


	return trace_create_file(option, 0644, t_options, (void *)index,
	return trace_create_file(option, 0644, t_options,
				 (void *)&tr->trace_flags_index[index],
				 &trace_options_core_fops);
				 &trace_options_core_fops);
}
}


@@ -6490,6 +6531,15 @@ static void free_trace_buffers(struct trace_array *tr)
#endif
#endif
}
}


static void init_trace_flags_index(struct trace_array *tr)
{
	int i;

	/* Used by the trace options files */
	for (i = 0; i < TRACE_FLAGS_MAX_SIZE; i++)
		tr->trace_flags_index[i] = i;
}

static int instance_mkdir(const char *name)
static int instance_mkdir(const char *name)
{
{
	struct trace_array *tr;
	struct trace_array *tr;
@@ -6542,6 +6592,7 @@ static int instance_mkdir(const char *name)
	}
	}


	init_tracer_tracefs(tr, tr->dir);
	init_tracer_tracefs(tr, tr->dir);
	init_trace_flags_index(tr);


	list_add(&tr->list, &ftrace_trace_arrays);
	list_add(&tr->list, &ftrace_trace_arrays);


@@ -7068,7 +7119,7 @@ __init static int tracer_alloc_buffers(void)
	 * Make sure we don't accidently add more trace options
	 * Make sure we don't accidently add more trace options
	 * than we have bits for.
	 * than we have bits for.
	 */
	 */
	BUILD_BUG_ON(TRACE_ITER_LAST_BIT > 32);
	BUILD_BUG_ON(TRACE_ITER_LAST_BIT > TRACE_FLAGS_MAX_SIZE);


	if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL))
	if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL))
		goto out;
		goto out;
@@ -7128,6 +7179,8 @@ __init static int tracer_alloc_buffers(void)


	ftrace_init_global_array_ops(&global_trace);
	ftrace_init_global_array_ops(&global_trace);


	init_trace_flags_index(&global_trace);

	register_tracer(&nop_trace);
	register_tracer(&nop_trace);


	/* All seems OK, enable tracing */
	/* All seems OK, enable tracing */
+3 −0
Original line number Original line Diff line number Diff line
@@ -168,6 +168,8 @@ struct trace_buffer {
	int				cpu;
	int				cpu;
};
};


#define TRACE_FLAGS_MAX_SIZE		32

/*
/*
 * The trace array - an array of per-CPU trace arrays. This is the
 * The trace array - an array of per-CPU trace arrays. This is the
 * highest level data structure that individual tracers deal with.
 * highest level data structure that individual tracers deal with.
@@ -218,6 +220,7 @@ struct trace_array {
	int			clock_id;
	int			clock_id;
	struct tracer		*current_trace;
	struct tracer		*current_trace;
	unsigned int		trace_flags;
	unsigned int		trace_flags;
	unsigned char		trace_flags_index[TRACE_FLAGS_MAX_SIZE];
	unsigned int		flags;
	unsigned int		flags;
	raw_spinlock_t		start_lock;
	raw_spinlock_t		start_lock;
	struct dentry		*dir;
	struct dentry		*dir;