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

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
...@@ -6186,14 +6186,51 @@ static const struct file_operations trace_options_fops = { ...@@ -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 ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 */
......
...@@ -168,6 +168,8 @@ struct trace_buffer { ...@@ -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 { ...@@ -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;
......
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