mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 14:41:02 +07:00
tracing: add tracer dependent options to options directory
This patch adds the tracer dependent options dynamically to the options directory when the tracer is activated. These options are removed when the tracer is deactivated. Signed-off-by: Steven Rostedt <srostedt@redhat.com>
This commit is contained in:
parent
a825907507
commit
577b785f55
@ -2275,8 +2275,17 @@ int tracer_init(struct tracer *t, struct trace_array *tr)
|
||||
return t->init(tr);
|
||||
}
|
||||
|
||||
struct trace_option_dentry;
|
||||
|
||||
static struct trace_option_dentry *
|
||||
create_trace_option_files(struct tracer *tracer);
|
||||
|
||||
static void
|
||||
destroy_trace_option_files(struct trace_option_dentry *topts);
|
||||
|
||||
static int tracing_set_tracer(const char *buf)
|
||||
{
|
||||
static struct trace_option_dentry *topts;
|
||||
struct trace_array *tr = &global_trace;
|
||||
struct tracer *t;
|
||||
int ret = 0;
|
||||
@ -2297,7 +2306,12 @@ static int tracing_set_tracer(const char *buf)
|
||||
if (current_trace && current_trace->reset)
|
||||
current_trace->reset(tr);
|
||||
|
||||
destroy_trace_option_files(topts);
|
||||
|
||||
current_trace = t;
|
||||
|
||||
topts = create_trace_option_files(current_trace);
|
||||
|
||||
if (t->init) {
|
||||
ret = tracer_init(t, tr);
|
||||
if (ret)
|
||||
@ -3093,6 +3107,95 @@ static void tracing_init_debugfs_percpu(long cpu)
|
||||
#include "trace_selftest.c"
|
||||
#endif
|
||||
|
||||
struct trace_option_dentry {
|
||||
struct tracer_opt *opt;
|
||||
struct tracer_flags *flags;
|
||||
struct dentry *entry;
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
trace_options_read(struct file *filp, char __user *ubuf, size_t cnt,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct trace_option_dentry *topt = filp->private_data;
|
||||
char *buf;
|
||||
|
||||
if (topt->flags->val & topt->opt->bit)
|
||||
buf = "1\n";
|
||||
else
|
||||
buf = "0\n";
|
||||
|
||||
return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct trace_option_dentry *topt = filp->private_data;
|
||||
unsigned long val;
|
||||
char buf[64];
|
||||
int ret;
|
||||
|
||||
if (cnt >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&buf, ubuf, cnt))
|
||||
return -EFAULT;
|
||||
|
||||
buf[cnt] = 0;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = 0;
|
||||
switch (val) {
|
||||
case 0:
|
||||
/* do nothing if already cleared */
|
||||
if (!(topt->flags->val & topt->opt->bit))
|
||||
break;
|
||||
|
||||
mutex_lock(&trace_types_lock);
|
||||
if (current_trace->set_flag)
|
||||
ret = current_trace->set_flag(topt->flags->val,
|
||||
topt->opt->bit, 0);
|
||||
mutex_unlock(&trace_types_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
topt->flags->val &= ~topt->opt->bit;
|
||||
break;
|
||||
case 1:
|
||||
/* do nothing if already set */
|
||||
if (topt->flags->val & topt->opt->bit)
|
||||
break;
|
||||
|
||||
mutex_lock(&trace_types_lock);
|
||||
if (current_trace->set_flag)
|
||||
ret = current_trace->set_flag(topt->flags->val,
|
||||
topt->opt->bit, 1);
|
||||
mutex_unlock(&trace_types_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
topt->flags->val |= topt->opt->bit;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*ppos += cnt;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations trace_options_fops = {
|
||||
.open = tracing_open_generic,
|
||||
.read = trace_options_read,
|
||||
.write = trace_options_write,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
trace_options_core_read(struct file *filp, char __user *ubuf, size_t cnt,
|
||||
loff_t *ppos)
|
||||
@ -3146,7 +3249,6 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations trace_options_core_fops = {
|
||||
.open = tracing_open_generic,
|
||||
.read = trace_options_core_read,
|
||||
@ -3174,6 +3276,76 @@ static struct dentry *trace_options_init_dentry(void)
|
||||
return t_options;
|
||||
}
|
||||
|
||||
static void
|
||||
create_trace_option_file(struct trace_option_dentry *topt,
|
||||
struct tracer_flags *flags,
|
||||
struct tracer_opt *opt)
|
||||
{
|
||||
struct dentry *t_options;
|
||||
struct dentry *entry;
|
||||
|
||||
t_options = trace_options_init_dentry();
|
||||
if (!t_options)
|
||||
return;
|
||||
|
||||
topt->flags = flags;
|
||||
topt->opt = opt;
|
||||
|
||||
entry = debugfs_create_file(opt->name, 0644, t_options, topt,
|
||||
&trace_options_fops);
|
||||
|
||||
topt->entry = entry;
|
||||
|
||||
}
|
||||
|
||||
static struct trace_option_dentry *
|
||||
create_trace_option_files(struct tracer *tracer)
|
||||
{
|
||||
struct trace_option_dentry *topts;
|
||||
struct tracer_flags *flags;
|
||||
struct tracer_opt *opts;
|
||||
int cnt;
|
||||
|
||||
if (!tracer)
|
||||
return NULL;
|
||||
|
||||
flags = tracer->flags;
|
||||
|
||||
if (!flags || !flags->opts)
|
||||
return NULL;
|
||||
|
||||
opts = flags->opts;
|
||||
|
||||
for (cnt = 0; opts[cnt].name; cnt++)
|
||||
;
|
||||
|
||||
topts = kzalloc(sizeof(*topts) * (cnt + 1), GFP_KERNEL);
|
||||
if (!topts)
|
||||
return NULL;
|
||||
|
||||
for (cnt = 0; opts[cnt].name; cnt++)
|
||||
create_trace_option_file(&topts[cnt], flags,
|
||||
&opts[cnt]);
|
||||
|
||||
return topts;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_trace_option_files(struct trace_option_dentry *topts)
|
||||
{
|
||||
int cnt;
|
||||
|
||||
if (!topts)
|
||||
return;
|
||||
|
||||
for (cnt = 0; topts[cnt].opt; cnt++) {
|
||||
if (topts[cnt].entry)
|
||||
debugfs_remove(topts[cnt].entry);
|
||||
}
|
||||
|
||||
kfree(topts);
|
||||
}
|
||||
|
||||
static struct dentry *
|
||||
create_trace_option_core_file(const char *option, long index)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user