diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 15:02:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 15:02:25 -0500 |
commit | da184a8064efe2a78d8542877970f7c6bb62775a (patch) | |
tree | d10193bb583f60333e243fe46386cab31f591e0c /kernel/trace/trace.c | |
parent | 525995d77ca08dfc2ba6f8e606f93694271dbd66 (diff) | |
parent | e36c54582c6f14adc9e10473e2aec2cc4f0acc03 (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.c | 182 |
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 | */ | ||
1156 | void 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 | |||
1154 | void | 1169 | void |
1155 | ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc) | 1170 | ftrace_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 | ||
2319 | static ssize_t | 2334 | static int tracing_trace_options_show(struct seq_file *m, void *v) |
2320 | tracing_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); | 2362 | static 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 | ||
2416 | static void set_tracer_flags(unsigned int mask, int enabled) | 2397 | static 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 | ||
2454 | static 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 | |||
2474 | static const struct file_operations tracing_iter_fops = { | 2461 | static 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 | ||
3395 | static ssize_t tracing_clock_read(struct file *filp, char __user *ubuf, | 3384 | static 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 | ||
3412 | static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf, | 3398 | static 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 | ||
3437 | static 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 | |||
3451 | static const struct file_operations tracing_max_lat_fops = { | 3444 | static 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 | ||
3488 | static const struct file_operations trace_clock_fops = { | 3481 | static 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; |