diff options
-rw-r--r-- | kernel/trace/ring_buffer.c | 39 | ||||
-rw-r--r-- | kernel/trace/trace.c | 54 | ||||
-rw-r--r-- | kernel/trace/trace.h | 1 |
3 files changed, 77 insertions, 17 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 9edb628603ab..5434c16f2192 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -489,6 +489,7 @@ struct ring_buffer_per_cpu { | |||
489 | local_t commits; | 489 | local_t commits; |
490 | local_t pages_touched; | 490 | local_t pages_touched; |
491 | local_t pages_read; | 491 | local_t pages_read; |
492 | long last_pages_touch; | ||
492 | size_t shortest_full; | 493 | size_t shortest_full; |
493 | unsigned long read; | 494 | unsigned long read; |
494 | unsigned long read_bytes; | 495 | unsigned long read_bytes; |
@@ -2632,7 +2633,9 @@ static void rb_commit(struct ring_buffer_per_cpu *cpu_buffer, | |||
2632 | static __always_inline void | 2633 | static __always_inline void |
2633 | rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer) | 2634 | rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer) |
2634 | { | 2635 | { |
2635 | bool pagebusy; | 2636 | size_t nr_pages; |
2637 | size_t dirty; | ||
2638 | size_t full; | ||
2636 | 2639 | ||
2637 | if (buffer->irq_work.waiters_pending) { | 2640 | if (buffer->irq_work.waiters_pending) { |
2638 | buffer->irq_work.waiters_pending = false; | 2641 | buffer->irq_work.waiters_pending = false; |
@@ -2646,24 +2649,27 @@ rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer) | |||
2646 | irq_work_queue(&cpu_buffer->irq_work.work); | 2649 | irq_work_queue(&cpu_buffer->irq_work.work); |
2647 | } | 2650 | } |
2648 | 2651 | ||
2649 | pagebusy = cpu_buffer->reader_page == cpu_buffer->commit_page; | 2652 | if (cpu_buffer->last_pages_touch == local_read(&cpu_buffer->pages_touched)) |
2653 | return; | ||
2650 | 2654 | ||
2651 | if (!pagebusy && cpu_buffer->irq_work.full_waiters_pending) { | 2655 | if (cpu_buffer->reader_page == cpu_buffer->commit_page) |
2652 | size_t nr_pages; | 2656 | return; |
2653 | size_t dirty; | ||
2654 | size_t full; | ||
2655 | 2657 | ||
2656 | full = cpu_buffer->shortest_full; | 2658 | if (!cpu_buffer->irq_work.full_waiters_pending) |
2657 | nr_pages = cpu_buffer->nr_pages; | 2659 | return; |
2658 | dirty = ring_buffer_nr_dirty_pages(buffer, cpu_buffer->cpu); | ||
2659 | if (full && nr_pages && (dirty * 100) <= full * nr_pages) | ||
2660 | return; | ||
2661 | 2660 | ||
2662 | cpu_buffer->irq_work.wakeup_full = true; | 2661 | cpu_buffer->last_pages_touch = local_read(&cpu_buffer->pages_touched); |
2663 | cpu_buffer->irq_work.full_waiters_pending = false; | 2662 | |
2664 | /* irq_work_queue() supplies it's own memory barriers */ | 2663 | full = cpu_buffer->shortest_full; |
2665 | irq_work_queue(&cpu_buffer->irq_work.work); | 2664 | nr_pages = cpu_buffer->nr_pages; |
2666 | } | 2665 | dirty = ring_buffer_nr_dirty_pages(buffer, cpu_buffer->cpu); |
2666 | if (full && nr_pages && (dirty * 100) <= full * nr_pages) | ||
2667 | return; | ||
2668 | |||
2669 | cpu_buffer->irq_work.wakeup_full = true; | ||
2670 | cpu_buffer->irq_work.full_waiters_pending = false; | ||
2671 | /* irq_work_queue() supplies it's own memory barriers */ | ||
2672 | irq_work_queue(&cpu_buffer->irq_work.work); | ||
2667 | } | 2673 | } |
2668 | 2674 | ||
2669 | /* | 2675 | /* |
@@ -4394,6 +4400,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) | |||
4394 | local_set(&cpu_buffer->commits, 0); | 4400 | local_set(&cpu_buffer->commits, 0); |
4395 | local_set(&cpu_buffer->pages_touched, 0); | 4401 | local_set(&cpu_buffer->pages_touched, 0); |
4396 | local_set(&cpu_buffer->pages_read, 0); | 4402 | local_set(&cpu_buffer->pages_read, 0); |
4403 | cpu_buffer->last_pages_touch = 0; | ||
4397 | cpu_buffer->shortest_full = 0; | 4404 | cpu_buffer->shortest_full = 0; |
4398 | cpu_buffer->read = 0; | 4405 | cpu_buffer->read = 0; |
4399 | cpu_buffer->read_bytes = 0; | 4406 | cpu_buffer->read_bytes = 0; |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 48d5eb22ff33..d382fd1aa4a6 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -6948,7 +6948,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, | |||
6948 | if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK)) | 6948 | if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK)) |
6949 | goto out; | 6949 | goto out; |
6950 | 6950 | ||
6951 | ret = wait_on_pipe(iter, 1); | 6951 | ret = wait_on_pipe(iter, iter->tr->buffer_percent); |
6952 | if (ret) | 6952 | if (ret) |
6953 | goto out; | 6953 | goto out; |
6954 | 6954 | ||
@@ -7662,6 +7662,53 @@ static const struct file_operations rb_simple_fops = { | |||
7662 | .llseek = default_llseek, | 7662 | .llseek = default_llseek, |
7663 | }; | 7663 | }; |
7664 | 7664 | ||
7665 | static ssize_t | ||
7666 | buffer_percent_read(struct file *filp, char __user *ubuf, | ||
7667 | size_t cnt, loff_t *ppos) | ||
7668 | { | ||
7669 | struct trace_array *tr = filp->private_data; | ||
7670 | char buf[64]; | ||
7671 | int r; | ||
7672 | |||
7673 | r = tr->buffer_percent; | ||
7674 | r = sprintf(buf, "%d\n", r); | ||
7675 | |||
7676 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | ||
7677 | } | ||
7678 | |||
7679 | static ssize_t | ||
7680 | buffer_percent_write(struct file *filp, const char __user *ubuf, | ||
7681 | size_t cnt, loff_t *ppos) | ||
7682 | { | ||
7683 | struct trace_array *tr = filp->private_data; | ||
7684 | unsigned long val; | ||
7685 | int ret; | ||
7686 | |||
7687 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); | ||
7688 | if (ret) | ||
7689 | return ret; | ||
7690 | |||
7691 | if (val > 100) | ||
7692 | return -EINVAL; | ||
7693 | |||
7694 | if (!val) | ||
7695 | val = 1; | ||
7696 | |||
7697 | tr->buffer_percent = val; | ||
7698 | |||
7699 | (*ppos)++; | ||
7700 | |||
7701 | return cnt; | ||
7702 | } | ||
7703 | |||
7704 | static const struct file_operations buffer_percent_fops = { | ||
7705 | .open = tracing_open_generic_tr, | ||
7706 | .read = buffer_percent_read, | ||
7707 | .write = buffer_percent_write, | ||
7708 | .release = tracing_release_generic_tr, | ||
7709 | .llseek = default_llseek, | ||
7710 | }; | ||
7711 | |||
7665 | struct dentry *trace_instance_dir; | 7712 | struct dentry *trace_instance_dir; |
7666 | 7713 | ||
7667 | static void | 7714 | static void |
@@ -7970,6 +8017,11 @@ init_tracer_tracefs(struct trace_array *tr, struct dentry *d_tracer) | |||
7970 | trace_create_file("timestamp_mode", 0444, d_tracer, tr, | 8017 | trace_create_file("timestamp_mode", 0444, d_tracer, tr, |
7971 | &trace_time_stamp_mode_fops); | 8018 | &trace_time_stamp_mode_fops); |
7972 | 8019 | ||
8020 | tr->buffer_percent = 1; | ||
8021 | |||
8022 | trace_create_file("buffer_percent", 0444, d_tracer, | ||
8023 | tr, &buffer_percent_fops); | ||
8024 | |||
7973 | create_trace_options_dir(tr); | 8025 | create_trace_options_dir(tr); |
7974 | 8026 | ||
7975 | #if defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER) | 8027 | #if defined(CONFIG_TRACER_MAX_TRACE) || defined(CONFIG_HWLAT_TRACER) |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index ab16eca76e59..08900828d282 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -247,6 +247,7 @@ struct trace_array { | |||
247 | int clock_id; | 247 | int clock_id; |
248 | int nr_topts; | 248 | int nr_topts; |
249 | bool clear_trace; | 249 | bool clear_trace; |
250 | int buffer_percent; | ||
250 | struct tracer *current_trace; | 251 | struct tracer *current_trace; |
251 | unsigned int trace_flags; | 252 | unsigned int trace_flags; |
252 | unsigned char trace_flags_index[TRACE_FLAGS_MAX_SIZE]; | 253 | unsigned char trace_flags_index[TRACE_FLAGS_MAX_SIZE]; |