diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 330 |
1 files changed, 209 insertions, 121 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index ee9c921d7f2..17a2d44e1af 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -343,26 +343,27 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | | |||
343 | static int trace_stop_count; | 343 | static int trace_stop_count; |
344 | static DEFINE_SPINLOCK(tracing_start_lock); | 344 | static DEFINE_SPINLOCK(tracing_start_lock); |
345 | 345 | ||
346 | static void wakeup_work_handler(struct work_struct *work) | ||
347 | { | ||
348 | wake_up(&trace_wait); | ||
349 | } | ||
350 | |||
351 | static DECLARE_DELAYED_WORK(wakeup_work, wakeup_work_handler); | ||
352 | |||
346 | /** | 353 | /** |
347 | * trace_wake_up - wake up tasks waiting for trace input | 354 | * trace_wake_up - wake up tasks waiting for trace input |
348 | * | 355 | * |
349 | * Simply wakes up any task that is blocked on the trace_wait | 356 | * Schedules a delayed work to wake up any task that is blocked on the |
350 | * queue. These is used with trace_poll for tasks polling the trace. | 357 | * trace_wait queue. These is used with trace_poll for tasks polling the |
358 | * trace. | ||
351 | */ | 359 | */ |
352 | void trace_wake_up(void) | 360 | void trace_wake_up(void) |
353 | { | 361 | { |
354 | int cpu; | 362 | const unsigned long delay = msecs_to_jiffies(2); |
355 | 363 | ||
356 | if (trace_flags & TRACE_ITER_BLOCK) | 364 | if (trace_flags & TRACE_ITER_BLOCK) |
357 | return; | 365 | return; |
358 | /* | 366 | schedule_delayed_work(&wakeup_work, delay); |
359 | * The runqueue_is_locked() can fail, but this is the best we | ||
360 | * have for now: | ||
361 | */ | ||
362 | cpu = get_cpu(); | ||
363 | if (!runqueue_is_locked(cpu)) | ||
364 | wake_up(&trace_wait); | ||
365 | put_cpu(); | ||
366 | } | 367 | } |
367 | 368 | ||
368 | static int __init set_buf_size(char *str) | 369 | static int __init set_buf_size(char *str) |
@@ -424,6 +425,7 @@ static const char *trace_options[] = { | |||
424 | "graph-time", | 425 | "graph-time", |
425 | "record-cmd", | 426 | "record-cmd", |
426 | "overwrite", | 427 | "overwrite", |
428 | "disable_on_free", | ||
427 | NULL | 429 | NULL |
428 | }; | 430 | }; |
429 | 431 | ||
@@ -1191,6 +1193,18 @@ void trace_nowake_buffer_unlock_commit(struct ring_buffer *buffer, | |||
1191 | } | 1193 | } |
1192 | EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit); | 1194 | EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit); |
1193 | 1195 | ||
1196 | void trace_nowake_buffer_unlock_commit_regs(struct ring_buffer *buffer, | ||
1197 | struct ring_buffer_event *event, | ||
1198 | unsigned long flags, int pc, | ||
1199 | struct pt_regs *regs) | ||
1200 | { | ||
1201 | ring_buffer_unlock_commit(buffer, event); | ||
1202 | |||
1203 | ftrace_trace_stack_regs(buffer, flags, 0, pc, regs); | ||
1204 | ftrace_trace_userstack(buffer, flags, pc); | ||
1205 | } | ||
1206 | EXPORT_SYMBOL_GPL(trace_nowake_buffer_unlock_commit_regs); | ||
1207 | |||
1194 | void trace_current_buffer_discard_commit(struct ring_buffer *buffer, | 1208 | void trace_current_buffer_discard_commit(struct ring_buffer *buffer, |
1195 | struct ring_buffer_event *event) | 1209 | struct ring_buffer_event *event) |
1196 | { | 1210 | { |
@@ -1234,30 +1248,103 @@ ftrace(struct trace_array *tr, struct trace_array_cpu *data, | |||
1234 | } | 1248 | } |
1235 | 1249 | ||
1236 | #ifdef CONFIG_STACKTRACE | 1250 | #ifdef CONFIG_STACKTRACE |
1251 | |||
1252 | #define FTRACE_STACK_MAX_ENTRIES (PAGE_SIZE / sizeof(unsigned long)) | ||
1253 | struct ftrace_stack { | ||
1254 | unsigned long calls[FTRACE_STACK_MAX_ENTRIES]; | ||
1255 | }; | ||
1256 | |||
1257 | static DEFINE_PER_CPU(struct ftrace_stack, ftrace_stack); | ||
1258 | static DEFINE_PER_CPU(int, ftrace_stack_reserve); | ||
1259 | |||
1237 | static void __ftrace_trace_stack(struct ring_buffer *buffer, | 1260 | static void __ftrace_trace_stack(struct ring_buffer *buffer, |
1238 | unsigned long flags, | 1261 | unsigned long flags, |
1239 | int skip, int pc) | 1262 | int skip, int pc, struct pt_regs *regs) |
1240 | { | 1263 | { |
1241 | struct ftrace_event_call *call = &event_kernel_stack; | 1264 | struct ftrace_event_call *call = &event_kernel_stack; |
1242 | struct ring_buffer_event *event; | 1265 | struct ring_buffer_event *event; |
1243 | struct stack_entry *entry; | 1266 | struct stack_entry *entry; |
1244 | struct stack_trace trace; | 1267 | struct stack_trace trace; |
1268 | int use_stack; | ||
1269 | int size = FTRACE_STACK_ENTRIES; | ||
1270 | |||
1271 | trace.nr_entries = 0; | ||
1272 | trace.skip = skip; | ||
1273 | |||
1274 | /* | ||
1275 | * Since events can happen in NMIs there's no safe way to | ||
1276 | * use the per cpu ftrace_stacks. We reserve it and if an interrupt | ||
1277 | * or NMI comes in, it will just have to use the default | ||
1278 | * FTRACE_STACK_SIZE. | ||
1279 | */ | ||
1280 | preempt_disable_notrace(); | ||
1281 | |||
1282 | use_stack = ++__get_cpu_var(ftrace_stack_reserve); | ||
1283 | /* | ||
1284 | * We don't need any atomic variables, just a barrier. | ||
1285 | * If an interrupt comes in, we don't care, because it would | ||
1286 | * have exited and put the counter back to what we want. | ||
1287 | * We just need a barrier to keep gcc from moving things | ||
1288 | * around. | ||
1289 | */ | ||
1290 | barrier(); | ||
1291 | if (use_stack == 1) { | ||
1292 | trace.entries = &__get_cpu_var(ftrace_stack).calls[0]; | ||
1293 | trace.max_entries = FTRACE_STACK_MAX_ENTRIES; | ||
1294 | |||
1295 | if (regs) | ||
1296 | save_stack_trace_regs(regs, &trace); | ||
1297 | else | ||
1298 | save_stack_trace(&trace); | ||
1299 | |||
1300 | if (trace.nr_entries > size) | ||
1301 | size = trace.nr_entries; | ||
1302 | } else | ||
1303 | /* From now on, use_stack is a boolean */ | ||
1304 | use_stack = 0; | ||
1305 | |||
1306 | size *= sizeof(unsigned long); | ||
1245 | 1307 | ||
1246 | event = trace_buffer_lock_reserve(buffer, TRACE_STACK, | 1308 | event = trace_buffer_lock_reserve(buffer, TRACE_STACK, |
1247 | sizeof(*entry), flags, pc); | 1309 | sizeof(*entry) + size, flags, pc); |
1248 | if (!event) | 1310 | if (!event) |
1249 | return; | 1311 | goto out; |
1250 | entry = ring_buffer_event_data(event); | 1312 | entry = ring_buffer_event_data(event); |
1251 | memset(&entry->caller, 0, sizeof(entry->caller)); | ||
1252 | 1313 | ||
1253 | trace.nr_entries = 0; | 1314 | memset(&entry->caller, 0, size); |
1254 | trace.max_entries = FTRACE_STACK_ENTRIES; | 1315 | |
1255 | trace.skip = skip; | 1316 | if (use_stack) |
1256 | trace.entries = entry->caller; | 1317 | memcpy(&entry->caller, trace.entries, |
1318 | trace.nr_entries * sizeof(unsigned long)); | ||
1319 | else { | ||
1320 | trace.max_entries = FTRACE_STACK_ENTRIES; | ||
1321 | trace.entries = entry->caller; | ||
1322 | if (regs) | ||
1323 | save_stack_trace_regs(regs, &trace); | ||
1324 | else | ||
1325 | save_stack_trace(&trace); | ||
1326 | } | ||
1327 | |||
1328 | entry->size = trace.nr_entries; | ||
1257 | 1329 | ||
1258 | save_stack_trace(&trace); | ||
1259 | if (!filter_check_discard(call, entry, buffer, event)) | 1330 | if (!filter_check_discard(call, entry, buffer, event)) |
1260 | ring_buffer_unlock_commit(buffer, event); | 1331 | ring_buffer_unlock_commit(buffer, event); |
1332 | |||
1333 | out: | ||
1334 | /* Again, don't let gcc optimize things here */ | ||
1335 | barrier(); | ||
1336 | __get_cpu_var(ftrace_stack_reserve)--; | ||
1337 | preempt_enable_notrace(); | ||
1338 | |||
1339 | } | ||
1340 | |||
1341 | void ftrace_trace_stack_regs(struct ring_buffer *buffer, unsigned long flags, | ||
1342 | int skip, int pc, struct pt_regs *regs) | ||
1343 | { | ||
1344 | if (!(trace_flags & TRACE_ITER_STACKTRACE)) | ||
1345 | return; | ||
1346 | |||
1347 | __ftrace_trace_stack(buffer, flags, skip, pc, regs); | ||
1261 | } | 1348 | } |
1262 | 1349 | ||
1263 | void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags, | 1350 | void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags, |
@@ -1266,13 +1353,13 @@ void ftrace_trace_stack(struct ring_buffer *buffer, unsigned long flags, | |||
1266 | if (!(trace_flags & TRACE_ITER_STACKTRACE)) | 1353 | if (!(trace_flags & TRACE_ITER_STACKTRACE)) |
1267 | return; | 1354 | return; |
1268 | 1355 | ||
1269 | __ftrace_trace_stack(buffer, flags, skip, pc); | 1356 | __ftrace_trace_stack(buffer, flags, skip, pc, NULL); |
1270 | } | 1357 | } |
1271 | 1358 | ||
1272 | void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, | 1359 | void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, |
1273 | int pc) | 1360 | int pc) |
1274 | { | 1361 | { |
1275 | __ftrace_trace_stack(tr->buffer, flags, skip, pc); | 1362 | __ftrace_trace_stack(tr->buffer, flags, skip, pc, NULL); |
1276 | } | 1363 | } |
1277 | 1364 | ||
1278 | /** | 1365 | /** |
@@ -1288,7 +1375,7 @@ void trace_dump_stack(void) | |||
1288 | local_save_flags(flags); | 1375 | local_save_flags(flags); |
1289 | 1376 | ||
1290 | /* skipping 3 traces, seems to get us at the caller of this function */ | 1377 | /* skipping 3 traces, seems to get us at the caller of this function */ |
1291 | __ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count()); | 1378 | __ftrace_trace_stack(global_trace.buffer, flags, 3, preempt_count(), NULL); |
1292 | } | 1379 | } |
1293 | 1380 | ||
1294 | static DEFINE_PER_CPU(int, user_stack_count); | 1381 | static DEFINE_PER_CPU(int, user_stack_count); |
@@ -1536,7 +1623,12 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts, | |||
1536 | 1623 | ||
1537 | ftrace_enable_cpu(); | 1624 | ftrace_enable_cpu(); |
1538 | 1625 | ||
1539 | return event ? ring_buffer_event_data(event) : NULL; | 1626 | if (event) { |
1627 | iter->ent_size = ring_buffer_event_length(event); | ||
1628 | return ring_buffer_event_data(event); | ||
1629 | } | ||
1630 | iter->ent_size = 0; | ||
1631 | return NULL; | ||
1540 | } | 1632 | } |
1541 | 1633 | ||
1542 | static struct trace_entry * | 1634 | static struct trace_entry * |
@@ -2051,6 +2143,9 @@ void trace_default_header(struct seq_file *m) | |||
2051 | { | 2143 | { |
2052 | struct trace_iterator *iter = m->private; | 2144 | struct trace_iterator *iter = m->private; |
2053 | 2145 | ||
2146 | if (!(trace_flags & TRACE_ITER_CONTEXT_INFO)) | ||
2147 | return; | ||
2148 | |||
2054 | if (iter->iter_flags & TRACE_FILE_LAT_FMT) { | 2149 | if (iter->iter_flags & TRACE_FILE_LAT_FMT) { |
2055 | /* print nothing if the buffers are empty */ | 2150 | /* print nothing if the buffers are empty */ |
2056 | if (trace_empty(iter)) | 2151 | if (trace_empty(iter)) |
@@ -2701,20 +2796,11 @@ tracing_ctrl_write(struct file *filp, const char __user *ubuf, | |||
2701 | size_t cnt, loff_t *ppos) | 2796 | size_t cnt, loff_t *ppos) |
2702 | { | 2797 | { |
2703 | struct trace_array *tr = filp->private_data; | 2798 | struct trace_array *tr = filp->private_data; |
2704 | char buf[64]; | ||
2705 | unsigned long val; | 2799 | unsigned long val; |
2706 | int ret; | 2800 | int ret; |
2707 | 2801 | ||
2708 | if (cnt >= sizeof(buf)) | 2802 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
2709 | return -EINVAL; | 2803 | if (ret) |
2710 | |||
2711 | if (copy_from_user(&buf, ubuf, cnt)) | ||
2712 | return -EFAULT; | ||
2713 | |||
2714 | buf[cnt] = 0; | ||
2715 | |||
2716 | ret = strict_strtoul(buf, 10, &val); | ||
2717 | if (ret < 0) | ||
2718 | return ret; | 2804 | return ret; |
2719 | 2805 | ||
2720 | val = !!val; | 2806 | val = !!val; |
@@ -2767,7 +2853,7 @@ int tracer_init(struct tracer *t, struct trace_array *tr) | |||
2767 | return t->init(tr); | 2853 | return t->init(tr); |
2768 | } | 2854 | } |
2769 | 2855 | ||
2770 | static int tracing_resize_ring_buffer(unsigned long size) | 2856 | static int __tracing_resize_ring_buffer(unsigned long size) |
2771 | { | 2857 | { |
2772 | int ret; | 2858 | int ret; |
2773 | 2859 | ||
@@ -2819,6 +2905,41 @@ static int tracing_resize_ring_buffer(unsigned long size) | |||
2819 | return ret; | 2905 | return ret; |
2820 | } | 2906 | } |
2821 | 2907 | ||
2908 | static ssize_t tracing_resize_ring_buffer(unsigned long size) | ||
2909 | { | ||
2910 | int cpu, ret = size; | ||
2911 | |||
2912 | mutex_lock(&trace_types_lock); | ||
2913 | |||
2914 | tracing_stop(); | ||
2915 | |||
2916 | /* disable all cpu buffers */ | ||
2917 | for_each_tracing_cpu(cpu) { | ||
2918 | if (global_trace.data[cpu]) | ||
2919 | atomic_inc(&global_trace.data[cpu]->disabled); | ||
2920 | if (max_tr.data[cpu]) | ||
2921 | atomic_inc(&max_tr.data[cpu]->disabled); | ||
2922 | } | ||
2923 | |||
2924 | if (size != global_trace.entries) | ||
2925 | ret = __tracing_resize_ring_buffer(size); | ||
2926 | |||
2927 | if (ret < 0) | ||
2928 | ret = -ENOMEM; | ||
2929 | |||
2930 | for_each_tracing_cpu(cpu) { | ||
2931 | if (global_trace.data[cpu]) | ||
2932 | atomic_dec(&global_trace.data[cpu]->disabled); | ||
2933 | if (max_tr.data[cpu]) | ||
2934 | atomic_dec(&max_tr.data[cpu]->disabled); | ||
2935 | } | ||
2936 | |||
2937 | tracing_start(); | ||
2938 | mutex_unlock(&trace_types_lock); | ||
2939 | |||
2940 | return ret; | ||
2941 | } | ||
2942 | |||
2822 | 2943 | ||
2823 | /** | 2944 | /** |
2824 | * tracing_update_buffers - used by tracing facility to expand ring buffers | 2945 | * tracing_update_buffers - used by tracing facility to expand ring buffers |
@@ -2836,7 +2957,7 @@ int tracing_update_buffers(void) | |||
2836 | 2957 | ||
2837 | mutex_lock(&trace_types_lock); | 2958 | mutex_lock(&trace_types_lock); |
2838 | if (!ring_buffer_expanded) | 2959 | if (!ring_buffer_expanded) |
2839 | ret = tracing_resize_ring_buffer(trace_buf_size); | 2960 | ret = __tracing_resize_ring_buffer(trace_buf_size); |
2840 | mutex_unlock(&trace_types_lock); | 2961 | mutex_unlock(&trace_types_lock); |
2841 | 2962 | ||
2842 | return ret; | 2963 | return ret; |
@@ -2860,7 +2981,7 @@ static int tracing_set_tracer(const char *buf) | |||
2860 | mutex_lock(&trace_types_lock); | 2981 | mutex_lock(&trace_types_lock); |
2861 | 2982 | ||
2862 | if (!ring_buffer_expanded) { | 2983 | if (!ring_buffer_expanded) { |
2863 | ret = tracing_resize_ring_buffer(trace_buf_size); | 2984 | ret = __tracing_resize_ring_buffer(trace_buf_size); |
2864 | if (ret < 0) | 2985 | if (ret < 0) |
2865 | goto out; | 2986 | goto out; |
2866 | ret = 0; | 2987 | ret = 0; |
@@ -2966,20 +3087,11 @@ tracing_max_lat_write(struct file *filp, const char __user *ubuf, | |||
2966 | size_t cnt, loff_t *ppos) | 3087 | size_t cnt, loff_t *ppos) |
2967 | { | 3088 | { |
2968 | unsigned long *ptr = filp->private_data; | 3089 | unsigned long *ptr = filp->private_data; |
2969 | char buf[64]; | ||
2970 | unsigned long val; | 3090 | unsigned long val; |
2971 | int ret; | 3091 | int ret; |
2972 | 3092 | ||
2973 | if (cnt >= sizeof(buf)) | 3093 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
2974 | return -EINVAL; | 3094 | if (ret) |
2975 | |||
2976 | if (copy_from_user(&buf, ubuf, cnt)) | ||
2977 | return -EFAULT; | ||
2978 | |||
2979 | buf[cnt] = 0; | ||
2980 | |||
2981 | ret = strict_strtoul(buf, 10, &val); | ||
2982 | if (ret < 0) | ||
2983 | return ret; | 3095 | return ret; |
2984 | 3096 | ||
2985 | *ptr = val * 1000; | 3097 | *ptr = val * 1000; |
@@ -3434,67 +3546,54 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
3434 | size_t cnt, loff_t *ppos) | 3546 | size_t cnt, loff_t *ppos) |
3435 | { | 3547 | { |
3436 | unsigned long val; | 3548 | unsigned long val; |
3437 | char buf[64]; | 3549 | int ret; |
3438 | int ret, cpu; | ||
3439 | |||
3440 | if (cnt >= sizeof(buf)) | ||
3441 | return -EINVAL; | ||
3442 | |||
3443 | if (copy_from_user(&buf, ubuf, cnt)) | ||
3444 | return -EFAULT; | ||
3445 | |||
3446 | buf[cnt] = 0; | ||
3447 | 3550 | ||
3448 | ret = strict_strtoul(buf, 10, &val); | 3551 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
3449 | if (ret < 0) | 3552 | if (ret) |
3450 | return ret; | 3553 | return ret; |
3451 | 3554 | ||
3452 | /* must have at least 1 entry */ | 3555 | /* must have at least 1 entry */ |
3453 | if (!val) | 3556 | if (!val) |
3454 | return -EINVAL; | 3557 | return -EINVAL; |
3455 | 3558 | ||
3456 | mutex_lock(&trace_types_lock); | ||
3457 | |||
3458 | tracing_stop(); | ||
3459 | |||
3460 | /* disable all cpu buffers */ | ||
3461 | for_each_tracing_cpu(cpu) { | ||
3462 | if (global_trace.data[cpu]) | ||
3463 | atomic_inc(&global_trace.data[cpu]->disabled); | ||
3464 | if (max_tr.data[cpu]) | ||
3465 | atomic_inc(&max_tr.data[cpu]->disabled); | ||
3466 | } | ||
3467 | |||
3468 | /* value is in KB */ | 3559 | /* value is in KB */ |
3469 | val <<= 10; | 3560 | val <<= 10; |
3470 | 3561 | ||
3471 | if (val != global_trace.entries) { | 3562 | ret = tracing_resize_ring_buffer(val); |
3472 | ret = tracing_resize_ring_buffer(val); | 3563 | if (ret < 0) |
3473 | if (ret < 0) { | 3564 | return ret; |
3474 | cnt = ret; | ||
3475 | goto out; | ||
3476 | } | ||
3477 | } | ||
3478 | 3565 | ||
3479 | *ppos += cnt; | 3566 | *ppos += cnt; |
3480 | 3567 | ||
3481 | /* If check pages failed, return ENOMEM */ | 3568 | return cnt; |
3482 | if (tracing_disabled) | 3569 | } |
3483 | cnt = -ENOMEM; | ||
3484 | out: | ||
3485 | for_each_tracing_cpu(cpu) { | ||
3486 | if (global_trace.data[cpu]) | ||
3487 | atomic_dec(&global_trace.data[cpu]->disabled); | ||
3488 | if (max_tr.data[cpu]) | ||
3489 | atomic_dec(&max_tr.data[cpu]->disabled); | ||
3490 | } | ||
3491 | 3570 | ||
3492 | tracing_start(); | 3571 | static ssize_t |
3493 | mutex_unlock(&trace_types_lock); | 3572 | tracing_free_buffer_write(struct file *filp, const char __user *ubuf, |
3573 | size_t cnt, loff_t *ppos) | ||
3574 | { | ||
3575 | /* | ||
3576 | * There is no need to read what the user has written, this function | ||
3577 | * is just to make sure that there is no error when "echo" is used | ||
3578 | */ | ||
3579 | |||
3580 | *ppos += cnt; | ||
3494 | 3581 | ||
3495 | return cnt; | 3582 | return cnt; |
3496 | } | 3583 | } |
3497 | 3584 | ||
3585 | static int | ||
3586 | tracing_free_buffer_release(struct inode *inode, struct file *filp) | ||
3587 | { | ||
3588 | /* disable tracing ? */ | ||
3589 | if (trace_flags & TRACE_ITER_STOP_ON_FREE) | ||
3590 | tracing_off(); | ||
3591 | /* resize the ring buffer to 0 */ | ||
3592 | tracing_resize_ring_buffer(0); | ||
3593 | |||
3594 | return 0; | ||
3595 | } | ||
3596 | |||
3498 | static int mark_printk(const char *fmt, ...) | 3597 | static int mark_printk(const char *fmt, ...) |
3499 | { | 3598 | { |
3500 | int ret; | 3599 | int ret; |
@@ -3640,6 +3739,11 @@ static const struct file_operations tracing_entries_fops = { | |||
3640 | .llseek = generic_file_llseek, | 3739 | .llseek = generic_file_llseek, |
3641 | }; | 3740 | }; |
3642 | 3741 | ||
3742 | static const struct file_operations tracing_free_buffer_fops = { | ||
3743 | .write = tracing_free_buffer_write, | ||
3744 | .release = tracing_free_buffer_release, | ||
3745 | }; | ||
3746 | |||
3643 | static const struct file_operations tracing_mark_fops = { | 3747 | static const struct file_operations tracing_mark_fops = { |
3644 | .open = tracing_open_generic, | 3748 | .open = tracing_open_generic, |
3645 | .write = tracing_mark_write, | 3749 | .write = tracing_mark_write, |
@@ -3696,7 +3800,7 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, | |||
3696 | return 0; | 3800 | return 0; |
3697 | 3801 | ||
3698 | if (!info->spare) | 3802 | if (!info->spare) |
3699 | info->spare = ring_buffer_alloc_read_page(info->tr->buffer); | 3803 | info->spare = ring_buffer_alloc_read_page(info->tr->buffer, info->cpu); |
3700 | if (!info->spare) | 3804 | if (!info->spare) |
3701 | return -ENOMEM; | 3805 | return -ENOMEM; |
3702 | 3806 | ||
@@ -3704,8 +3808,6 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, | |||
3704 | if (info->read < PAGE_SIZE) | 3808 | if (info->read < PAGE_SIZE) |
3705 | goto read; | 3809 | goto read; |
3706 | 3810 | ||
3707 | info->read = 0; | ||
3708 | |||
3709 | trace_access_lock(info->cpu); | 3811 | trace_access_lock(info->cpu); |
3710 | ret = ring_buffer_read_page(info->tr->buffer, | 3812 | ret = ring_buffer_read_page(info->tr->buffer, |
3711 | &info->spare, | 3813 | &info->spare, |
@@ -3715,6 +3817,8 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, | |||
3715 | if (ret < 0) | 3817 | if (ret < 0) |
3716 | return 0; | 3818 | return 0; |
3717 | 3819 | ||
3820 | info->read = 0; | ||
3821 | |||
3718 | read: | 3822 | read: |
3719 | size = PAGE_SIZE - info->read; | 3823 | size = PAGE_SIZE - info->read; |
3720 | if (size > count) | 3824 | if (size > count) |
@@ -3853,7 +3957,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3853 | 3957 | ||
3854 | ref->ref = 1; | 3958 | ref->ref = 1; |
3855 | ref->buffer = info->tr->buffer; | 3959 | ref->buffer = info->tr->buffer; |
3856 | ref->page = ring_buffer_alloc_read_page(ref->buffer); | 3960 | ref->page = ring_buffer_alloc_read_page(ref->buffer, info->cpu); |
3857 | if (!ref->page) { | 3961 | if (!ref->page) { |
3858 | kfree(ref); | 3962 | kfree(ref); |
3859 | break; | 3963 | break; |
@@ -3862,8 +3966,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
3862 | r = ring_buffer_read_page(ref->buffer, &ref->page, | 3966 | r = ring_buffer_read_page(ref->buffer, &ref->page, |
3863 | len, info->cpu, 1); | 3967 | len, info->cpu, 1); |
3864 | if (r < 0) { | 3968 | if (r < 0) { |
3865 | ring_buffer_free_read_page(ref->buffer, | 3969 | ring_buffer_free_read_page(ref->buffer, ref->page); |
3866 | ref->page); | ||
3867 | kfree(ref); | 3970 | kfree(ref); |
3868 | break; | 3971 | break; |
3869 | } | 3972 | } |
@@ -4099,19 +4202,10 @@ trace_options_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
4099 | { | 4202 | { |
4100 | struct trace_option_dentry *topt = filp->private_data; | 4203 | struct trace_option_dentry *topt = filp->private_data; |
4101 | unsigned long val; | 4204 | unsigned long val; |
4102 | char buf[64]; | ||
4103 | int ret; | 4205 | int ret; |
4104 | 4206 | ||
4105 | if (cnt >= sizeof(buf)) | 4207 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
4106 | return -EINVAL; | 4208 | if (ret) |
4107 | |||
4108 | if (copy_from_user(&buf, ubuf, cnt)) | ||
4109 | return -EFAULT; | ||
4110 | |||
4111 | buf[cnt] = 0; | ||
4112 | |||
4113 | ret = strict_strtoul(buf, 10, &val); | ||
4114 | if (ret < 0) | ||
4115 | return ret; | 4209 | return ret; |
4116 | 4210 | ||
4117 | if (val != 0 && val != 1) | 4211 | if (val != 0 && val != 1) |
@@ -4159,20 +4253,11 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
4159 | loff_t *ppos) | 4253 | loff_t *ppos) |
4160 | { | 4254 | { |
4161 | long index = (long)filp->private_data; | 4255 | long index = (long)filp->private_data; |
4162 | char buf[64]; | ||
4163 | unsigned long val; | 4256 | unsigned long val; |
4164 | int ret; | 4257 | int ret; |
4165 | 4258 | ||
4166 | if (cnt >= sizeof(buf)) | 4259 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); |
4167 | return -EINVAL; | 4260 | if (ret) |
4168 | |||
4169 | if (copy_from_user(&buf, ubuf, cnt)) | ||
4170 | return -EFAULT; | ||
4171 | |||
4172 | buf[cnt] = 0; | ||
4173 | |||
4174 | ret = strict_strtoul(buf, 10, &val); | ||
4175 | if (ret < 0) | ||
4176 | return ret; | 4261 | return ret; |
4177 | 4262 | ||
4178 | if (val != 0 && val != 1) | 4263 | if (val != 0 && val != 1) |
@@ -4365,6 +4450,9 @@ static __init int tracer_init_debugfs(void) | |||
4365 | trace_create_file("buffer_size_kb", 0644, d_tracer, | 4450 | trace_create_file("buffer_size_kb", 0644, d_tracer, |
4366 | &global_trace, &tracing_entries_fops); | 4451 | &global_trace, &tracing_entries_fops); |
4367 | 4452 | ||
4453 | trace_create_file("free_buffer", 0644, d_tracer, | ||
4454 | &global_trace, &tracing_free_buffer_fops); | ||
4455 | |||
4368 | trace_create_file("trace_marker", 0220, d_tracer, | 4456 | trace_create_file("trace_marker", 0220, d_tracer, |
4369 | NULL, &tracing_mark_fops); | 4457 | NULL, &tracing_mark_fops); |
4370 | 4458 | ||