mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle
@ 2017-03-06  7:14 Tan Xiaojun
  2017-03-06  7:14 ` [PATCH -stable 4.1 1/4] " Tan Xiaojun
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Tan Xiaojun @ 2017-03-06  7:14 UTC (permalink / raw)
  To: alexander.levin, peterz, wangnan0, guohanjun; +Cc: linuxarm, linux-kernel

These four patches are needed for stable 4.1. They fix function of dynamic
interrupt throttle.

Kan Liang (1):
  perf/core: Fix implicitly enable dynamic interrupt throttle

Peter Zijlstra (2):
  perf/core: Fix dynamic interrupt throttle
  perf/core: Make sysctl_perf_cpu_time_max_percent conform to
    documentation

Tan Xiaojun (1):
  perf/core: Fix the perf_cpu_time_max_percent check

 kernel/events/core.c | 97 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 60 insertions(+), 37 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH -stable 4.1 1/4] perf/core: Fix dynamic interrupt throttle
  2017-03-06  7:14 [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle Tan Xiaojun
@ 2017-03-06  7:14 ` Tan Xiaojun
  2017-03-06  7:14 ` [PATCH -stable 4.1 2/4] perf/core: Fix implicitly enable " Tan Xiaojun
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Tan Xiaojun @ 2017-03-06  7:14 UTC (permalink / raw)
  To: alexander.levin, peterz, wangnan0, guohanjun; +Cc: linuxarm, linux-kernel

From: Peter Zijlstra <peterz@infradead.org>

There were two problems with the dynamic interrupt throttle mechanism,
both triggered by the same action.

When you (or perf_fuzzer) write a huge value into
/proc/sys/kernel/perf_event_max_sample_rate the computed
perf_sample_allowed_ns becomes 0. This effectively disables the whole
dynamic throttle.

This is fixed by ensuring update_perf_cpu_limits() never sets the
value to 0. However, we allow disabling of the dynamic throttle by
writing 100 to /proc/sys/kernel/perf_cpu_time_max_percent. This will
generate a warning in dmesg.

The second problem is that by setting the max_sample_rate to a huge
number, the adaptive process can take a few tries, since it halfs the
limit each time. Change that to directly compute a new value based on
the observed duration.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Tan Xiaojun <tanxiaojun@huawei.com>
---
 kernel/events/core.c | 87 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 51 insertions(+), 36 deletions(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6da64f0..3089a004 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -198,8 +198,11 @@ void update_perf_cpu_limits(void)
 	u64 tmp = perf_sample_period_ns;
 
 	tmp *= sysctl_perf_cpu_time_max_percent;
-	do_div(tmp, 100);
-	ACCESS_ONCE(perf_sample_allowed_ns) = tmp;
+	tmp = div_u64(tmp, 100);
+	if (!tmp)
+		tmp = 1;
+
+	WRITE_ONCE(perf_sample_allowed_ns, tmp);
 }
 
 static int perf_rotate_context(struct perf_cpu_context *cpuctx);
@@ -231,7 +234,13 @@ int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write,
 	if (ret || !write)
 		return ret;
 
-	update_perf_cpu_limits();
+	if (sysctl_perf_cpu_time_max_percent == 100) {
+		printk(KERN_WARNING
+		       "perf: Dynamic interrupt throttling disabled, can hang your system!\n");
+		WRITE_ONCE(perf_sample_allowed_ns, 0);
+	} else {
+		update_perf_cpu_limits();
+	}
 
 	return 0;
 }
@@ -245,62 +254,68 @@ int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write,
 #define NR_ACCUMULATED_SAMPLES 128
 static DEFINE_PER_CPU(u64, running_sample_length);
 
+static u64 __report_avg;
+static u64 __report_allowed;
+
 static void perf_duration_warn(struct irq_work *w)
 {
-	u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns);
-	u64 avg_local_sample_len;
-	u64 local_samples_len;
-
-	local_samples_len = __this_cpu_read(running_sample_length);
-	avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES;
-
 	printk_ratelimited(KERN_WARNING
-			"perf interrupt took too long (%lld > %lld), lowering "
-			"kernel.perf_event_max_sample_rate to %d\n",
-			avg_local_sample_len, allowed_ns >> 1,
-			sysctl_perf_event_sample_rate);
+		"perf: interrupt took too long (%lld > %lld), lowering "
+		"kernel.perf_event_max_sample_rate to %d\n",
+		__report_avg, __report_allowed,
+		sysctl_perf_event_sample_rate);
 }
 
 static DEFINE_IRQ_WORK(perf_duration_work, perf_duration_warn);
 
 void perf_sample_event_took(u64 sample_len_ns)
 {
-	u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns);
-	u64 avg_local_sample_len;
-	u64 local_samples_len;
+	u64 max_len = READ_ONCE(perf_sample_allowed_ns);
+	u64 running_len;
+	u64 avg_len;
+	u32 max;
 
-	if (allowed_ns == 0)
+	if (max_len == 0)
 		return;
 
-	/* decay the counter by 1 average sample */
-	local_samples_len = __this_cpu_read(running_sample_length);
-	local_samples_len -= local_samples_len/NR_ACCUMULATED_SAMPLES;
-	local_samples_len += sample_len_ns;
-	__this_cpu_write(running_sample_length, local_samples_len);
+	/* Decay the counter by 1 average sample. */
+	running_len = __this_cpu_read(running_sample_length);
+	running_len -= running_len/NR_ACCUMULATED_SAMPLES;
+	running_len += sample_len_ns;
+	__this_cpu_write(running_sample_length, running_len);
 
 	/*
-	 * note: this will be biased artifically low until we have
-	 * seen NR_ACCUMULATED_SAMPLES.  Doing it this way keeps us
+	 * Note: this will be biased artifically low until we have
+	 * seen NR_ACCUMULATED_SAMPLES. Doing it this way keeps us
 	 * from having to maintain a count.
 	 */
-	avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES;
-
-	if (avg_local_sample_len <= allowed_ns)
+	avg_len = running_len/NR_ACCUMULATED_SAMPLES;
+	if (avg_len <= max_len)
 		return;
 
-	if (max_samples_per_tick <= 1)
-		return;
+	__report_avg = avg_len;
+	__report_allowed = max_len;
 
-	max_samples_per_tick = DIV_ROUND_UP(max_samples_per_tick, 2);
-	sysctl_perf_event_sample_rate = max_samples_per_tick * HZ;
-	perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
+	/*
+	 * Compute a throttle threshold 25% below the current duration.
+	 */
+	avg_len += avg_len / 4;
+	max = (TICK_NSEC / 100) * sysctl_perf_cpu_time_max_percent;
+	if (avg_len < max)
+		max /= (u32)avg_len;
+	else
+		max = 1;
 
-	update_perf_cpu_limits();
+	WRITE_ONCE(perf_sample_allowed_ns, avg_len);
+	WRITE_ONCE(max_samples_per_tick, max);
+
+	sysctl_perf_event_sample_rate = max * HZ;
+	perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
 
 	if (!irq_work_queue(&perf_duration_work)) {
-		early_printk("perf interrupt took too long (%lld > %lld), lowering "
+		early_printk("perf: interrupt took too long (%lld > %lld), lowering "
 			     "kernel.perf_event_max_sample_rate to %d\n",
-			     avg_local_sample_len, allowed_ns >> 1,
+			     __report_avg, __report_allowed,
 			     sysctl_perf_event_sample_rate);
 	}
 }
-- 
1.9.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH -stable 4.1 2/4] perf/core: Fix implicitly enable dynamic interrupt throttle
  2017-03-06  7:14 [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle Tan Xiaojun
  2017-03-06  7:14 ` [PATCH -stable 4.1 1/4] " Tan Xiaojun
@ 2017-03-06  7:14 ` Tan Xiaojun
  2017-03-06  7:14 ` [PATCH -stable 4.1 3/4] perf/core: Make sysctl_perf_cpu_time_max_percent conform to documentation Tan Xiaojun
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Tan Xiaojun @ 2017-03-06  7:14 UTC (permalink / raw)
  To: alexander.levin, peterz, wangnan0, guohanjun; +Cc: linuxarm, linux-kernel

From: Kan Liang <kan.liang@intel.com>

This patch fixes an issue which was introduced by commit:

  91a612eea9a3 ("perf/core: Fix dynamic interrupt throttle")

... which commit unconditionally sets the perf_sample_allowed_ns value
to !0. But that could trigger a bug in the following corner case:

The user can disable the dynamic interrupt throttle mechanism by setting
perf_cpu_time_max_percent to 0. Then they change perf_event_max_sample_rate.
For this case, the mechanism will be enabled implicitly, because
perf_sample_allowed_ns becomes !0 - which is not what we want.

This patch only updates perf_sample_allowed_ns when the dynamic
interrupt throttle mechanism is enabled.

Signed-off-by: Kan Liang <kan.liang@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: acme@kernel.org
Link: http://lkml.kernel.org/r/1462260366-3160-1-git-send-email-kan.liang@intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Tan Xiaojun <tanxiaojun@huawei.com>
---
 kernel/events/core.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 3089a004..f96ad76 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -216,6 +216,13 @@ int perf_proc_update_handler(struct ctl_table *table, int write,
 	if (ret || !write)
 		return ret;
 
+	/*
+	 * If throttling is disabled don't allow the write:
+	 */
+	if (sysctl_perf_cpu_time_max_percent == 100 ||
+	    sysctl_perf_cpu_time_max_percent == 0)
+		return -EINVAL;
+
 	max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ);
 	perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
 	update_perf_cpu_limits();
-- 
1.9.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH -stable 4.1 3/4] perf/core: Make sysctl_perf_cpu_time_max_percent conform to documentation
  2017-03-06  7:14 [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle Tan Xiaojun
  2017-03-06  7:14 ` [PATCH -stable 4.1 1/4] " Tan Xiaojun
  2017-03-06  7:14 ` [PATCH -stable 4.1 2/4] perf/core: Fix implicitly enable " Tan Xiaojun
@ 2017-03-06  7:14 ` Tan Xiaojun
  2017-03-06  7:14 ` [PATCH -stable 4.1 4/4] perf/core: Fix the perf_cpu_time_max_percent check Tan Xiaojun
  2017-03-06 22:19 ` [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle alexander.levin
  4 siblings, 0 replies; 6+ messages in thread
From: Tan Xiaojun @ 2017-03-06  7:14 UTC (permalink / raw)
  To: alexander.levin, peterz, wangnan0, guohanjun; +Cc: linuxarm, linux-kernel

From: Peter Zijlstra <peterz@infradead.org>

Markus reported that 0 should also disable the throttling we per
Documentation/sysctl/kernel.txt.

Reported-by: Markus Trippelsdorf <markus@trippelsdorf.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Fixes: 91a612eea9a3 ("perf/core: Fix dynamic interrupt throttle")
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Tan Xiaojun <tanxiaojun@huawei.com>
---
 kernel/events/core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index f96ad76..350c45a 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -241,7 +241,8 @@ int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write,
 	if (ret || !write)
 		return ret;
 
-	if (sysctl_perf_cpu_time_max_percent == 100) {
+	if (sysctl_perf_cpu_time_max_percent == 100 ||
+	    sysctl_perf_cpu_time_max_percent == 0) {
 		printk(KERN_WARNING
 		       "perf: Dynamic interrupt throttling disabled, can hang your system!\n");
 		WRITE_ONCE(perf_sample_allowed_ns, 0);
-- 
1.9.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH -stable 4.1 4/4] perf/core: Fix the perf_cpu_time_max_percent check
  2017-03-06  7:14 [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle Tan Xiaojun
                   ` (2 preceding siblings ...)
  2017-03-06  7:14 ` [PATCH -stable 4.1 3/4] perf/core: Make sysctl_perf_cpu_time_max_percent conform to documentation Tan Xiaojun
@ 2017-03-06  7:14 ` Tan Xiaojun
  2017-03-06 22:19 ` [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle alexander.levin
  4 siblings, 0 replies; 6+ messages in thread
From: Tan Xiaojun @ 2017-03-06  7:14 UTC (permalink / raw)
  To: alexander.levin, peterz, wangnan0, guohanjun; +Cc: linuxarm, linux-kernel

Use "proc_dointvec_minmax" instead of "proc_dointvec" to check the input
value from user-space.

If not, we can set a big value and some vars will overflow like
"sysctl_perf_event_sample_rate" which will cause a lot of unexpected
problems.

Signed-off-by: Tan Xiaojun <tanxiaojun@huawei.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: <acme@kernel.org>
Cc: <alexander.shishkin@linux.intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Link: http://lkml.kernel.org/r/1487829879-56237-1-git-send-email-tanxiaojun@huawei.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/events/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/events/core.c b/kernel/events/core.c
index 350c45a..5b50b06 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -236,7 +236,7 @@ int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write,
 				void __user *buffer, size_t *lenp,
 				loff_t *ppos)
 {
-	int ret = proc_dointvec(table, write, buffer, lenp, ppos);
+	int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
 
 	if (ret || !write)
 		return ret;
-- 
1.9.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle
  2017-03-06  7:14 [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle Tan Xiaojun
                   ` (3 preceding siblings ...)
  2017-03-06  7:14 ` [PATCH -stable 4.1 4/4] perf/core: Fix the perf_cpu_time_max_percent check Tan Xiaojun
@ 2017-03-06 22:19 ` alexander.levin
  4 siblings, 0 replies; 6+ messages in thread
From: alexander.levin @ 2017-03-06 22:19 UTC (permalink / raw)
  To: Tan Xiaojun; +Cc: peterz, wangnan0, guohanjun, linuxarm, linux-kernel

On Mon, Mar 06, 2017 at 03:14:21PM +0800, Tan Xiaojun wrote:
> These four patches are needed for stable 4.1. They fix function of dynamic
> interrupt throttle.
> 
> Kan Liang (1):
>   perf/core: Fix implicitly enable dynamic interrupt throttle
> 
> Peter Zijlstra (2):
>   perf/core: Fix dynamic interrupt throttle
>   perf/core: Make sysctl_perf_cpu_time_max_percent conform to
>     documentation
> 
> Tan Xiaojun (1):
>   perf/core: Fix the perf_cpu_time_max_percent check
> 
>  kernel/events/core.c | 97 ++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 60 insertions(+), 37 deletions(-)
> 
> -- 
> 1.9.1
> 

Applied, thanks!

-- 

Thanks,
Sasha

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-03-07  1:31 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-06  7:14 [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle Tan Xiaojun
2017-03-06  7:14 ` [PATCH -stable 4.1 1/4] " Tan Xiaojun
2017-03-06  7:14 ` [PATCH -stable 4.1 2/4] perf/core: Fix implicitly enable " Tan Xiaojun
2017-03-06  7:14 ` [PATCH -stable 4.1 3/4] perf/core: Make sysctl_perf_cpu_time_max_percent conform to documentation Tan Xiaojun
2017-03-06  7:14 ` [PATCH -stable 4.1 4/4] perf/core: Fix the perf_cpu_time_max_percent check Tan Xiaojun
2017-03-06 22:19 ` [PATCH -stable 4.1 0/4] perf/core: Fix dynamic interrupt throttle alexander.levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®