aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-16 15:02:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-16 15:02:25 -0500
commitda184a8064efe2a78d8542877970f7c6bb62775a (patch)
treed10193bb583f60333e243fe46386cab31f591e0c /kernel/trace/trace.c
parent525995d77ca08dfc2ba6f8e606f93694271dbd66 (diff)
parente36c54582c6f14adc9e10473e2aec2cc4f0acc03 (diff)
Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: tracing: Fix return of trace_dump_stack() ksym_tracer: Fix bad cast tracing/power: Remove two exports tracing: Change event->profile_count to be int type tracing: Simplify trace_option_write() tracing: Remove useless trace option tracing: Use seq file for trace_clock tracing: Use seq file for trace_options function-graph: Allow writing the same val to set_graph_function ftrace: Call trace_parser_clear() properly ftrace: Return EINVAL when writing invalid val to set_ftrace_filter tracing: Move a printk out of ftrace_raw_reg_event_foo() tracing: Pull up calls to trace_define_common_fields() tracing: Extract duplicate ftrace_raw_init_event_foo() ftrace.h: Use common pr_info fmt string tracing: Add stack trace to irqsoff tracer tracing: Add trace_dump_stack() ring-buffer: Move resize integrity check under reader lock ring-buffer: Use sync sched protection on ring buffer resizing tracing: Fix wrong usage of strstrip in trace_ksyms
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c182
1 files changed, 77 insertions, 105 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 31118ae16f03..06ba26747d7e 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -313,7 +313,6 @@ static const char *trace_options[] = {
313 "bin", 313 "bin",
314 "block", 314 "block",
315 "stacktrace", 315 "stacktrace",
316 "sched-tree",
317 "trace_printk", 316 "trace_printk",
318 "ftrace_preempt", 317 "ftrace_preempt",
319 "branch", 318 "branch",
@@ -1151,6 +1150,22 @@ void __trace_stack(struct trace_array *tr, unsigned long flags, int skip,
1151 __ftrace_trace_stack(tr->buffer, flags, skip, pc); 1150 __ftrace_trace_stack(tr->buffer, flags, skip, pc);
1152} 1151}
1153 1152
1153/**
1154 * trace_dump_stack - record a stack back trace in the trace buffer
1155 */
1156void trace_dump_stack(void)
1157{
1158 unsigned long flags;
1159
1160 if (tracing_disabled || tracing_selftest_running)
1161 return;
1162
1163 local_save_flags(flags);
1164
1165 /* skipping 3 traces, seems to get us at the caller of this function */
1166 __ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count());
1167}
1168
1154void 1169void
1155ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc) 1170ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc)
1156{ 1171{
@@ -2316,67 +2331,49 @@ static const struct file_operations tracing_cpumask_fops = {
2316 .write = tracing_cpumask_write, 2331 .write = tracing_cpumask_write,
2317}; 2332};
2318 2333
2319static ssize_t 2334static int tracing_trace_options_show(struct seq_file *m, void *v)
2320tracing_trace_options_read(struct file *filp, char __user *ubuf,
2321 size_t cnt, loff_t *ppos)
2322{ 2335{
2323 struct tracer_opt *trace_opts; 2336 struct tracer_opt *trace_opts;
2324 u32 tracer_flags; 2337 u32 tracer_flags;
2325 int len = 0;
2326 char *buf;
2327 int r = 0;
2328 int i; 2338 int i;
2329 2339
2330
2331 /* calculate max size */
2332 for (i = 0; trace_options[i]; i++) {
2333 len += strlen(trace_options[i]);
2334 len += 3; /* "no" and newline */
2335 }
2336
2337 mutex_lock(&trace_types_lock); 2340 mutex_lock(&trace_types_lock);
2338 tracer_flags = current_trace->flags->val; 2341 tracer_flags = current_trace->flags->val;
2339 trace_opts = current_trace->flags->opts; 2342 trace_opts = current_trace->flags->opts;
2340 2343
2341 /*
2342 * Increase the size with names of options specific
2343 * of the current tracer.
2344 */
2345 for (i = 0; trace_opts[i].name; i++) {
2346 len += strlen(trace_opts[i].name);
2347 len += 3; /* "no" and newline */
2348 }
2349
2350 /* +1 for \0 */
2351 buf = kmalloc(len + 1, GFP_KERNEL);
2352 if (!buf) {
2353 mutex_unlock(&trace_types_lock);
2354 return -ENOMEM;
2355 }
2356
2357 for (i = 0; trace_options[i]; i++) { 2344 for (i = 0; trace_options[i]; i++) {
2358 if (trace_flags & (1 << i)) 2345 if (trace_flags & (1 << i))
2359 r += sprintf(buf + r, "%s\n", trace_options[i]); 2346 seq_printf(m, "%s\n", trace_options[i]);
2360 else 2347 else
2361 r += sprintf(buf + r, "no%s\n", trace_options[i]); 2348 seq_printf(m, "no%s\n", trace_options[i]);
2362 } 2349 }
2363 2350
2364 for (i = 0; trace_opts[i].name; i++) { 2351 for (i = 0; trace_opts[i].name; i++) {
2365 if (tracer_flags & trace_opts[i].bit) 2352 if (tracer_flags & trace_opts[i].bit)
2366 r += sprintf(buf + r, "%s\n", 2353 seq_printf(m, "%s\n", trace_opts[i].name);
2367 trace_opts[i].name);
2368 else 2354 else
2369 r += sprintf(buf + r, "no%s\n", 2355 seq_printf(m, "no%s\n", trace_opts[i].name);
2370 trace_opts[i].name);
2371 } 2356 }
2372 mutex_unlock(&trace_types_lock); 2357 mutex_unlock(&trace_types_lock);
2373 2358
2374 WARN_ON(r >= len + 1); 2359 return 0;
2360}
2375 2361
2376 r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r); 2362static int __set_tracer_option(struct tracer *trace,
2363 struct tracer_flags *tracer_flags,
2364 struct tracer_opt *opts, int neg)
2365{
2366 int ret;
2377 2367
2378 kfree(buf); 2368 ret = trace->set_flag(tracer_flags->val, opts->bit, !neg);
2379 return r; 2369 if (ret)
2370 return ret;
2371
2372 if (neg)
2373 tracer_flags->val &= ~opts->bit;
2374 else
2375 tracer_flags->val |= opts->bit;
2376 return 0;
2380} 2377}
2381 2378
2382/* Try to assign a tracer specific option */ 2379/* Try to assign a tracer specific option */
@@ -2384,33 +2381,17 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
2384{ 2381{
2385 struct tracer_flags *tracer_flags = trace->flags; 2382 struct tracer_flags *tracer_flags = trace->flags;
2386 struct tracer_opt *opts = NULL; 2383 struct tracer_opt *opts = NULL;
2387 int ret = 0, i = 0; 2384 int i;
2388 int len;
2389 2385
2390 for (i = 0; tracer_flags->opts[i].name; i++) { 2386 for (i = 0; tracer_flags->opts[i].name; i++) {
2391 opts = &tracer_flags->opts[i]; 2387 opts = &tracer_flags->opts[i];
2392 len = strlen(opts->name);
2393 2388
2394 if (strncmp(cmp, opts->name, len) == 0) { 2389 if (strcmp(cmp, opts->name) == 0)
2395 ret = trace->set_flag(tracer_flags->val, 2390 return __set_tracer_option(trace, trace->flags,
2396 opts->bit, !neg); 2391 opts, neg);
2397 break;
2398 }
2399 } 2392 }
2400 /* Not found */
2401 if (!tracer_flags->opts[i].name)
2402 return -EINVAL;
2403
2404 /* Refused to handle */
2405 if (ret)
2406 return ret;
2407
2408 if (neg)
2409 tracer_flags->val &= ~opts->bit;
2410 else
2411 tracer_flags->val |= opts->bit;
2412 2393
2413 return 0; 2394 return -EINVAL;
2414} 2395}
2415 2396
2416static void set_tracer_flags(unsigned int mask, int enabled) 2397static void set_tracer_flags(unsigned int mask, int enabled)
@@ -2430,7 +2411,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2430 size_t cnt, loff_t *ppos) 2411 size_t cnt, loff_t *ppos)
2431{ 2412{
2432 char buf[64]; 2413 char buf[64];
2433 char *cmp = buf; 2414 char *cmp;
2434 int neg = 0; 2415 int neg = 0;
2435 int ret; 2416 int ret;
2436 int i; 2417 int i;
@@ -2442,16 +2423,15 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2442 return -EFAULT; 2423 return -EFAULT;
2443 2424
2444 buf[cnt] = 0; 2425 buf[cnt] = 0;
2426 cmp = strstrip(buf);
2445 2427
2446 if (strncmp(buf, "no", 2) == 0) { 2428 if (strncmp(cmp, "no", 2) == 0) {
2447 neg = 1; 2429 neg = 1;
2448 cmp += 2; 2430 cmp += 2;
2449 } 2431 }
2450 2432
2451 for (i = 0; trace_options[i]; i++) { 2433 for (i = 0; trace_options[i]; i++) {
2452 int len = strlen(trace_options[i]); 2434 if (strcmp(cmp, trace_options[i]) == 0) {
2453
2454 if (strncmp(cmp, trace_options[i], len) == 0) {
2455 set_tracer_flags(1 << i, !neg); 2435 set_tracer_flags(1 << i, !neg);
2456 break; 2436 break;
2457 } 2437 }
@@ -2471,9 +2451,18 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
2471 return cnt; 2451 return cnt;
2472} 2452}
2473 2453
2454static int tracing_trace_options_open(struct inode *inode, struct file *file)
2455{
2456 if (tracing_disabled)
2457 return -ENODEV;
2458 return single_open(file, tracing_trace_options_show, NULL);
2459}
2460
2474static const struct file_operations tracing_iter_fops = { 2461static const struct file_operations tracing_iter_fops = {
2475 .open = tracing_open_generic, 2462 .open = tracing_trace_options_open,
2476 .read = tracing_trace_options_read, 2463 .read = seq_read,
2464 .llseek = seq_lseek,
2465 .release = single_release,
2477 .write = tracing_trace_options_write, 2466 .write = tracing_trace_options_write,
2478}; 2467};
2479 2468
@@ -3392,21 +3381,18 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
3392 return cnt; 3381 return cnt;
3393} 3382}
3394 3383
3395static ssize_t tracing_clock_read(struct file *filp, char __user *ubuf, 3384static int tracing_clock_show(struct seq_file *m, void *v)
3396 size_t cnt, loff_t *ppos)
3397{ 3385{
3398 char buf[64];
3399 int bufiter = 0;
3400 int i; 3386 int i;
3401 3387
3402 for (i = 0; i < ARRAY_SIZE(trace_clocks); i++) 3388 for (i = 0; i < ARRAY_SIZE(trace_clocks); i++)
3403 bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter, 3389 seq_printf(m,
3404 "%s%s%s%s", i ? " " : "", 3390 "%s%s%s%s", i ? " " : "",
3405 i == trace_clock_id ? "[" : "", trace_clocks[i].name, 3391 i == trace_clock_id ? "[" : "", trace_clocks[i].name,
3406 i == trace_clock_id ? "]" : ""); 3392 i == trace_clock_id ? "]" : "");
3407 bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter, "\n"); 3393 seq_putc(m, '\n');
3408 3394
3409 return simple_read_from_buffer(ubuf, cnt, ppos, buf, bufiter); 3395 return 0;
3410} 3396}
3411 3397
3412static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf, 3398static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
@@ -3448,6 +3434,13 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
3448 return cnt; 3434 return cnt;
3449} 3435}
3450 3436
3437static int tracing_clock_open(struct inode *inode, struct file *file)
3438{
3439 if (tracing_disabled)
3440 return -ENODEV;
3441 return single_open(file, tracing_clock_show, NULL);
3442}
3443
3451static const struct file_operations tracing_max_lat_fops = { 3444static const struct file_operations tracing_max_lat_fops = {
3452 .open = tracing_open_generic, 3445 .open = tracing_open_generic,
3453 .read = tracing_max_lat_read, 3446 .read = tracing_max_lat_read,
@@ -3486,8 +3479,10 @@ static const struct file_operations tracing_mark_fops = {
3486}; 3479};
3487 3480
3488static const struct file_operations trace_clock_fops = { 3481static const struct file_operations trace_clock_fops = {
3489 .open = tracing_open_generic, 3482 .open = tracing_clock_open,
3490 .read = tracing_clock_read, 3483 .read = seq_read,
3484 .llseek = seq_lseek,
3485 .release = single_release,
3491 .write = tracing_clock_write, 3486 .write = tracing_clock_write,
3492}; 3487};
3493 3488
@@ -3948,39 +3943,16 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt,
3948 if (ret < 0) 3943 if (ret < 0)
3949 return ret; 3944 return ret;
3950 3945
3951 ret = 0; 3946 if (val != 0 && val != 1)
3952 switch (val) { 3947 return -EINVAL;
3953 case 0:
3954 /* do nothing if already cleared */
3955 if (!(topt->flags->val & topt->opt->bit))
3956 break;
3957
3958 mutex_lock(&trace_types_lock);
3959 if (current_trace->set_flag)
3960 ret = current_trace->set_flag(topt->flags->val,
3961 topt->opt->bit, 0);
3962 mutex_unlock(&trace_types_lock);
3963 if (ret)
3964 return ret;
3965 topt->flags->val &= ~topt->opt->bit;
3966 break;
3967 case 1:
3968 /* do nothing if already set */
3969 if (topt->flags->val & topt->opt->bit)
3970 break;
3971 3948
3949 if (!!(topt->flags->val & topt->opt->bit) != val) {
3972 mutex_lock(&trace_types_lock); 3950 mutex_lock(&trace_types_lock);
3973 if (current_trace->set_flag) 3951 ret = __set_tracer_option(current_trace, topt->flags,
3974 ret = current_trace->set_flag(topt->flags->val, 3952 topt->opt, val);
3975 topt->opt->bit, 1);
3976 mutex_unlock(&trace_types_lock); 3953 mutex_unlock(&trace_types_lock);
3977 if (ret) 3954 if (ret)
3978 return ret; 3955 return ret;
3979 topt->flags->val |= topt->opt->bit;
3980 break;
3981
3982 default:
3983 return -EINVAL;
3984 } 3956 }
3985 3957
3986 *ppos += cnt; 3958 *ppos += cnt;