aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-02-26 23:43:05 -0500
committerSteven Rostedt <srostedt@redhat.com>2009-02-26 23:43:05 -0500
commit577b785f55168d5acb3d123ba41bfe8d7981e044 (patch)
tree6ae99a6f38fffda2c2b678a55f329d782337afbc /kernel/trace/trace.c
parenta8259075074fb09c230b4cd2c8d3ee3c49d6ecd1 (diff)
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>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c174
1 files changed, 173 insertions, 1 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 40e983ed994f..485c6e7f4465 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2275,8 +2275,17 @@ int tracer_init(struct tracer *t, struct trace_array *tr)
2275 return t->init(tr); 2275 return t->init(tr);
2276} 2276}
2277 2277
2278struct trace_option_dentry;
2279
2280static struct trace_option_dentry *
2281create_trace_option_files(struct tracer *tracer);
2282
2283static void
2284destroy_trace_option_files(struct trace_option_dentry *topts);
2285
2278static int tracing_set_tracer(const char *buf) 2286static int tracing_set_tracer(const char *buf)
2279{ 2287{
2288 static struct trace_option_dentry *topts;
2280 struct trace_array *tr = &global_trace; 2289 struct trace_array *tr = &global_trace;
2281 struct tracer *t; 2290 struct tracer *t;
2282 int ret = 0; 2291 int ret = 0;
@@ -2297,7 +2306,12 @@ static int tracing_set_tracer(const char *buf)
2297 if (current_trace && current_trace->reset) 2306 if (current_trace && current_trace->reset)
2298 current_trace->reset(tr); 2307 current_trace->reset(tr);
2299 2308
2309 destroy_trace_option_files(topts);
2310
2300 current_trace = t; 2311 current_trace = t;
2312
2313 topts = create_trace_option_files(current_trace);
2314
2301 if (t->init) { 2315 if (t->init) {
2302 ret = tracer_init(t, tr); 2316 ret = tracer_init(t, tr);
2303 if (ret) 2317 if (ret)
@@ -3093,6 +3107,95 @@ static void tracing_init_debugfs_percpu(long cpu)
3093#include "trace_selftest.c" 3107#include "trace_selftest.c"
3094#endif 3108#endif
3095 3109
3110struct trace_option_dentry {
3111 struct tracer_opt *opt;
3112 struct tracer_flags *flags;
3113 struct dentry *entry;
3114};
3115
3116static ssize_t
3117trace_options_read(struct file *filp, char __user *ubuf, size_t cnt,
3118 loff_t *ppos)
3119{
3120 struct trace_option_dentry *topt = filp->private_data;
3121 char *buf;
3122
3123 if (topt->flags->val & topt->opt->bit)
3124 buf = "1\n";
3125 else
3126 buf = "0\n";
3127
3128 return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
3129}
3130
3131static ssize_t
3132trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
3133 loff_t *ppos)
3134{
3135 struct trace_option_dentry *topt = filp->private_data;
3136 unsigned long val;
3137 char buf[64];
3138 int ret;
3139
3140 if (cnt >= sizeof(buf))
3141 return -EINVAL;
3142
3143 if (copy_from_user(&buf, ubuf, cnt))
3144 return -EFAULT;
3145
3146 buf[cnt] = 0;
3147
3148 ret = strict_strtoul(buf, 10, &val);
3149 if (ret < 0)
3150 return ret;
3151
3152 ret = 0;
3153 switch (val) {
3154 case 0:
3155 /* do nothing if already cleared */
3156 if (!(topt->flags->val & topt->opt->bit))
3157 break;
3158
3159 mutex_lock(&trace_types_lock);
3160 if (current_trace->set_flag)
3161 ret = current_trace->set_flag(topt->flags->val,
3162 topt->opt->bit, 0);
3163 mutex_unlock(&trace_types_lock);
3164 if (ret)
3165 return ret;
3166 topt->flags->val &= ~topt->opt->bit;
3167 break;
3168 case 1:
3169 /* do nothing if already set */
3170 if (topt->flags->val & topt->opt->bit)
3171 break;
3172
3173 mutex_lock(&trace_types_lock);
3174 if (current_trace->set_flag)
3175 ret = current_trace->set_flag(topt->flags->val,
3176 topt->opt->bit, 1);
3177 mutex_unlock(&trace_types_lock);
3178 if (ret)
3179 return ret;
3180 topt->flags->val |= topt->opt->bit;
3181 break;
3182
3183 default:
3184 return -EINVAL;
3185 }
3186
3187 *ppos += cnt;
3188
3189 return cnt;
3190}
3191
3192
3193static const struct file_operations trace_options_fops = {
3194 .open = tracing_open_generic,
3195 .read = trace_options_read,
3196 .write = trace_options_write,
3197};
3198
3096static ssize_t 3199static ssize_t
3097trace_options_core_read(struct file *filp, char __user *ubuf, size_t cnt, 3200trace_options_core_read(struct file *filp, char __user *ubuf, size_t cnt,
3098 loff_t *ppos) 3201 loff_t *ppos)
@@ -3146,7 +3249,6 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
3146 return cnt; 3249 return cnt;
3147} 3250}
3148 3251
3149
3150static const struct file_operations trace_options_core_fops = { 3252static const struct file_operations trace_options_core_fops = {
3151 .open = tracing_open_generic, 3253 .open = tracing_open_generic,
3152 .read = trace_options_core_read, 3254 .read = trace_options_core_read,
@@ -3174,6 +3276,76 @@ static struct dentry *trace_options_init_dentry(void)
3174 return t_options; 3276 return t_options;
3175} 3277}
3176 3278
3279static void
3280create_trace_option_file(struct trace_option_dentry *topt,
3281 struct tracer_flags *flags,
3282 struct tracer_opt *opt)
3283{
3284 struct dentry *t_options;
3285 struct dentry *entry;
3286
3287 t_options = trace_options_init_dentry();
3288 if (!t_options)
3289 return;
3290
3291 topt->flags = flags;
3292 topt->opt = opt;
3293
3294 entry = debugfs_create_file(opt->name, 0644, t_options, topt,
3295 &trace_options_fops);
3296
3297 topt->entry = entry;
3298
3299}
3300
3301static struct trace_option_dentry *
3302create_trace_option_files(struct tracer *tracer)
3303{
3304 struct trace_option_dentry *topts;
3305 struct tracer_flags *flags;
3306 struct tracer_opt *opts;
3307 int cnt;
3308
3309 if (!tracer)
3310 return NULL;
3311
3312 flags = tracer->flags;
3313
3314 if (!flags || !flags->opts)
3315 return NULL;
3316
3317 opts = flags->opts;
3318
3319 for (cnt = 0; opts[cnt].name; cnt++)
3320 ;
3321
3322 topts = kzalloc(sizeof(*topts) * (cnt + 1), GFP_KERNEL);
3323 if (!topts)
3324 return NULL;
3325
3326 for (cnt = 0; opts[cnt].name; cnt++)
3327 create_trace_option_file(&topts[cnt], flags,
3328 &opts[cnt]);
3329
3330 return topts;
3331}
3332
3333static void
3334destroy_trace_option_files(struct trace_option_dentry *topts)
3335{
3336 int cnt;
3337
3338 if (!topts)
3339 return;
3340
3341 for (cnt = 0; topts[cnt].opt; cnt++) {
3342 if (topts[cnt].entry)
3343 debugfs_remove(topts[cnt].entry);
3344 }
3345
3346 kfree(topts);
3347}
3348
3177static struct dentry * 3349static struct dentry *
3178create_trace_option_core_file(const char *option, long index) 3350create_trace_option_core_file(const char *option, long index)
3179{ 3351{