diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 101 |
1 files changed, 83 insertions, 18 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index aa58b7bc847c..d8d899f3bd6f 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -1294,20 +1294,32 @@ static void *s_next(struct seq_file *m, void *v, loff_t *pos) | |||
1294 | return ent; | 1294 | return ent; |
1295 | } | 1295 | } |
1296 | 1296 | ||
1297 | /* | ||
1298 | * No necessary locking here. The worst thing which can | ||
1299 | * happen is loosing events consumed at the same time | ||
1300 | * by a trace_pipe reader. | ||
1301 | * Other than that, we don't risk to crash the ring buffer | ||
1302 | * because it serializes the readers. | ||
1303 | * | ||
1304 | * The current tracer is copied to avoid a global locking | ||
1305 | * all around. | ||
1306 | */ | ||
1297 | static void *s_start(struct seq_file *m, loff_t *pos) | 1307 | static void *s_start(struct seq_file *m, loff_t *pos) |
1298 | { | 1308 | { |
1299 | struct trace_iterator *iter = m->private; | 1309 | struct trace_iterator *iter = m->private; |
1310 | static struct tracer *old_tracer; | ||
1300 | int cpu_file = iter->cpu_file; | 1311 | int cpu_file = iter->cpu_file; |
1301 | void *p = NULL; | 1312 | void *p = NULL; |
1302 | loff_t l = 0; | 1313 | loff_t l = 0; |
1303 | int cpu; | 1314 | int cpu; |
1304 | 1315 | ||
1316 | /* copy the tracer to avoid using a global lock all around */ | ||
1305 | mutex_lock(&trace_types_lock); | 1317 | mutex_lock(&trace_types_lock); |
1306 | 1318 | if (unlikely(old_tracer != current_trace && current_trace)) { | |
1307 | if (!current_trace || current_trace != iter->trace) { | 1319 | old_tracer = current_trace; |
1308 | mutex_unlock(&trace_types_lock); | 1320 | *iter->trace = *current_trace; |
1309 | return NULL; | ||
1310 | } | 1321 | } |
1322 | mutex_unlock(&trace_types_lock); | ||
1311 | 1323 | ||
1312 | atomic_inc(&trace_record_cmdline_disabled); | 1324 | atomic_inc(&trace_record_cmdline_disabled); |
1313 | 1325 | ||
@@ -1341,7 +1353,6 @@ static void *s_start(struct seq_file *m, loff_t *pos) | |||
1341 | static void s_stop(struct seq_file *m, void *p) | 1353 | static void s_stop(struct seq_file *m, void *p) |
1342 | { | 1354 | { |
1343 | atomic_dec(&trace_record_cmdline_disabled); | 1355 | atomic_dec(&trace_record_cmdline_disabled); |
1344 | mutex_unlock(&trace_types_lock); | ||
1345 | } | 1356 | } |
1346 | 1357 | ||
1347 | static void print_lat_help_header(struct seq_file *m) | 1358 | static void print_lat_help_header(struct seq_file *m) |
@@ -1691,13 +1702,25 @@ __tracing_open(struct inode *inode, struct file *file, int *ret) | |||
1691 | goto out; | 1702 | goto out; |
1692 | } | 1703 | } |
1693 | 1704 | ||
1705 | /* | ||
1706 | * We make a copy of the current tracer to avoid concurrent | ||
1707 | * changes on it while we are reading. | ||
1708 | */ | ||
1694 | mutex_lock(&trace_types_lock); | 1709 | mutex_lock(&trace_types_lock); |
1710 | iter->trace = kzalloc(sizeof(*iter->trace), GFP_KERNEL); | ||
1711 | if (!iter->trace) { | ||
1712 | *ret = -ENOMEM; | ||
1713 | goto fail; | ||
1714 | } | ||
1715 | if (current_trace) | ||
1716 | *iter->trace = *current_trace; | ||
1717 | |||
1695 | if (current_trace && current_trace->print_max) | 1718 | if (current_trace && current_trace->print_max) |
1696 | iter->tr = &max_tr; | 1719 | iter->tr = &max_tr; |
1697 | else | 1720 | else |
1698 | iter->tr = &global_trace; | 1721 | iter->tr = &global_trace; |
1699 | iter->trace = current_trace; | ||
1700 | iter->pos = -1; | 1722 | iter->pos = -1; |
1723 | mutex_init(&iter->mutex); | ||
1701 | iter->cpu_file = cpu_file; | 1724 | iter->cpu_file = cpu_file; |
1702 | 1725 | ||
1703 | /* Notify the tracer early; before we stop tracing. */ | 1726 | /* Notify the tracer early; before we stop tracing. */ |
@@ -1747,8 +1770,9 @@ __tracing_open(struct inode *inode, struct file *file, int *ret) | |||
1747 | if (iter->buffer_iter[cpu]) | 1770 | if (iter->buffer_iter[cpu]) |
1748 | ring_buffer_read_finish(iter->buffer_iter[cpu]); | 1771 | ring_buffer_read_finish(iter->buffer_iter[cpu]); |
1749 | } | 1772 | } |
1750 | fail: | 1773 | fail: |
1751 | mutex_unlock(&trace_types_lock); | 1774 | mutex_unlock(&trace_types_lock); |
1775 | kfree(iter->trace); | ||
1752 | kfree(iter); | 1776 | kfree(iter); |
1753 | 1777 | ||
1754 | return ERR_PTR(-ENOMEM); | 1778 | return ERR_PTR(-ENOMEM); |
@@ -1783,6 +1807,8 @@ static int tracing_release(struct inode *inode, struct file *file) | |||
1783 | mutex_unlock(&trace_types_lock); | 1807 | mutex_unlock(&trace_types_lock); |
1784 | 1808 | ||
1785 | seq_release(inode, file); | 1809 | seq_release(inode, file); |
1810 | mutex_destroy(&iter->mutex); | ||
1811 | kfree(iter->trace); | ||
1786 | kfree(iter); | 1812 | kfree(iter); |
1787 | return 0; | 1813 | return 0; |
1788 | } | 1814 | } |
@@ -2392,10 +2418,21 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) | |||
2392 | goto out; | 2418 | goto out; |
2393 | } | 2419 | } |
2394 | 2420 | ||
2421 | /* | ||
2422 | * We make a copy of the current tracer to avoid concurrent | ||
2423 | * changes on it while we are reading. | ||
2424 | */ | ||
2425 | iter->trace = kmalloc(sizeof(*iter->trace), GFP_KERNEL); | ||
2426 | if (!iter->trace) { | ||
2427 | ret = -ENOMEM; | ||
2428 | goto fail; | ||
2429 | } | ||
2430 | if (current_trace) | ||
2431 | *iter->trace = *current_trace; | ||
2432 | |||
2395 | if (!alloc_cpumask_var(&iter->started, GFP_KERNEL)) { | 2433 | if (!alloc_cpumask_var(&iter->started, GFP_KERNEL)) { |
2396 | kfree(iter); | ||
2397 | ret = -ENOMEM; | 2434 | ret = -ENOMEM; |
2398 | goto out; | 2435 | goto fail; |
2399 | } | 2436 | } |
2400 | 2437 | ||
2401 | /* trace pipe does not show start of buffer */ | 2438 | /* trace pipe does not show start of buffer */ |
@@ -2403,7 +2440,7 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) | |||
2403 | 2440 | ||
2404 | iter->cpu_file = cpu_file; | 2441 | iter->cpu_file = cpu_file; |
2405 | iter->tr = &global_trace; | 2442 | iter->tr = &global_trace; |
2406 | iter->trace = current_trace; | 2443 | mutex_init(&iter->mutex); |
2407 | filp->private_data = iter; | 2444 | filp->private_data = iter; |
2408 | 2445 | ||
2409 | if (iter->trace->pipe_open) | 2446 | if (iter->trace->pipe_open) |
@@ -2412,6 +2449,12 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) | |||
2412 | out: | 2449 | out: |
2413 | mutex_unlock(&trace_types_lock); | 2450 | mutex_unlock(&trace_types_lock); |
2414 | return ret; | 2451 | return ret; |
2452 | |||
2453 | fail: | ||
2454 | kfree(iter->trace); | ||
2455 | kfree(iter); | ||
2456 | mutex_unlock(&trace_types_lock); | ||
2457 | return ret; | ||
2415 | } | 2458 | } |
2416 | 2459 | ||
2417 | static int tracing_release_pipe(struct inode *inode, struct file *file) | 2460 | static int tracing_release_pipe(struct inode *inode, struct file *file) |
@@ -2428,6 +2471,8 @@ static int tracing_release_pipe(struct inode *inode, struct file *file) | |||
2428 | mutex_unlock(&trace_types_lock); | 2471 | mutex_unlock(&trace_types_lock); |
2429 | 2472 | ||
2430 | free_cpumask_var(iter->started); | 2473 | free_cpumask_var(iter->started); |
2474 | mutex_destroy(&iter->mutex); | ||
2475 | kfree(iter->trace); | ||
2431 | kfree(iter); | 2476 | kfree(iter); |
2432 | 2477 | ||
2433 | return 0; | 2478 | return 0; |
@@ -2497,18 +2542,15 @@ static int tracing_wait_pipe(struct file *filp) | |||
2497 | return -EAGAIN; | 2542 | return -EAGAIN; |
2498 | } | 2543 | } |
2499 | 2544 | ||
2500 | mutex_unlock(&trace_types_lock); | 2545 | mutex_unlock(&iter->mutex); |
2501 | 2546 | ||
2502 | iter->trace->wait_pipe(iter); | 2547 | iter->trace->wait_pipe(iter); |
2503 | 2548 | ||
2504 | mutex_lock(&trace_types_lock); | 2549 | mutex_lock(&iter->mutex); |
2505 | 2550 | ||
2506 | if (signal_pending(current)) | 2551 | if (signal_pending(current)) |
2507 | return -EINTR; | 2552 | return -EINTR; |
2508 | 2553 | ||
2509 | if (iter->trace != current_trace) | ||
2510 | return 0; | ||
2511 | |||
2512 | /* | 2554 | /* |
2513 | * We block until we read something and tracing is disabled. | 2555 | * We block until we read something and tracing is disabled. |
2514 | * We still block if tracing is disabled, but we have never | 2556 | * We still block if tracing is disabled, but we have never |
@@ -2533,6 +2575,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, | |||
2533 | size_t cnt, loff_t *ppos) | 2575 | size_t cnt, loff_t *ppos) |
2534 | { | 2576 | { |
2535 | struct trace_iterator *iter = filp->private_data; | 2577 | struct trace_iterator *iter = filp->private_data; |
2578 | static struct tracer *old_tracer; | ||
2536 | ssize_t sret; | 2579 | ssize_t sret; |
2537 | 2580 | ||
2538 | /* return any leftover data */ | 2581 | /* return any leftover data */ |
@@ -2542,7 +2585,20 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, | |||
2542 | 2585 | ||
2543 | trace_seq_reset(&iter->seq); | 2586 | trace_seq_reset(&iter->seq); |
2544 | 2587 | ||
2588 | /* copy the tracer to avoid using a global lock all around */ | ||
2545 | mutex_lock(&trace_types_lock); | 2589 | mutex_lock(&trace_types_lock); |
2590 | if (unlikely(old_tracer != current_trace && current_trace)) { | ||
2591 | old_tracer = current_trace; | ||
2592 | *iter->trace = *current_trace; | ||
2593 | } | ||
2594 | mutex_unlock(&trace_types_lock); | ||
2595 | |||
2596 | /* | ||
2597 | * Avoid more than one consumer on a single file descriptor | ||
2598 | * This is just a matter of traces coherency, the ring buffer itself | ||
2599 | * is protected. | ||
2600 | */ | ||
2601 | mutex_lock(&iter->mutex); | ||
2546 | if (iter->trace->read) { | 2602 | if (iter->trace->read) { |
2547 | sret = iter->trace->read(iter, filp, ubuf, cnt, ppos); | 2603 | sret = iter->trace->read(iter, filp, ubuf, cnt, ppos); |
2548 | if (sret) | 2604 | if (sret) |
@@ -2599,7 +2655,7 @@ waitagain: | |||
2599 | goto waitagain; | 2655 | goto waitagain; |
2600 | 2656 | ||
2601 | out: | 2657 | out: |
2602 | mutex_unlock(&trace_types_lock); | 2658 | mutex_unlock(&iter->mutex); |
2603 | 2659 | ||
2604 | return sret; | 2660 | return sret; |
2605 | } | 2661 | } |
@@ -2676,11 +2732,20 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
2676 | .ops = &tracing_pipe_buf_ops, | 2732 | .ops = &tracing_pipe_buf_ops, |
2677 | .spd_release = tracing_spd_release_pipe, | 2733 | .spd_release = tracing_spd_release_pipe, |
2678 | }; | 2734 | }; |
2735 | static struct tracer *old_tracer; | ||
2679 | ssize_t ret; | 2736 | ssize_t ret; |
2680 | size_t rem; | 2737 | size_t rem; |
2681 | unsigned int i; | 2738 | unsigned int i; |
2682 | 2739 | ||
2740 | /* copy the tracer to avoid using a global lock all around */ | ||
2683 | mutex_lock(&trace_types_lock); | 2741 | mutex_lock(&trace_types_lock); |
2742 | if (unlikely(old_tracer != current_trace && current_trace)) { | ||
2743 | old_tracer = current_trace; | ||
2744 | *iter->trace = *current_trace; | ||
2745 | } | ||
2746 | mutex_unlock(&trace_types_lock); | ||
2747 | |||
2748 | mutex_lock(&iter->mutex); | ||
2684 | 2749 | ||
2685 | if (iter->trace->splice_read) { | 2750 | if (iter->trace->splice_read) { |
2686 | ret = iter->trace->splice_read(iter, filp, | 2751 | ret = iter->trace->splice_read(iter, filp, |
@@ -2720,14 +2785,14 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, | |||
2720 | trace_seq_reset(&iter->seq); | 2785 | trace_seq_reset(&iter->seq); |
2721 | } | 2786 | } |
2722 | 2787 | ||
2723 | mutex_unlock(&trace_types_lock); | 2788 | mutex_unlock(&iter->mutex); |
2724 | 2789 | ||
2725 | spd.nr_pages = i; | 2790 | spd.nr_pages = i; |
2726 | 2791 | ||
2727 | return splice_to_pipe(pipe, &spd); | 2792 | return splice_to_pipe(pipe, &spd); |
2728 | 2793 | ||
2729 | out_err: | 2794 | out_err: |
2730 | mutex_unlock(&trace_types_lock); | 2795 | mutex_unlock(&iter->mutex); |
2731 | 2796 | ||
2732 | return ret; | 2797 | return ret; |
2733 | } | 2798 | } |