Commit 8fe8ff09 authored by Kevin Hilman's avatar Kevin Hilman Committed by Frederic Weisbecker

sched/nohz: Fix overflow error in scheduler_tick_max_deferment()

While calculating the scheduler tick max deferment, the delta is
converted from microseconds to nanoseconds through a multiplication
against NSEC_PER_USEC.

But this microseconds operand is an unsigned int, thus the result may
likely overflow. The result is cast to u64 but only once the operation
is completed, which is too late to avoid overflown result.

This is currently not a problem because the scheduler tick max deferment
is 1 second. But this may become an issue as we plan to make this
value tunable.

So lets fix this by casting the usecs value to u64 before multiplying by
NSECS_PER_USEC.

Also to prevent from this kind of mistake to happen again, move this
ad-hoc jiffies -> nsecs conversion to a new helper.
Signed-off-by: default avatarKevin Hilman <khilman@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Alex Shi <alex.shi@linaro.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Kevin Hilman <khilman@linaro.org>
Link: http://lkml.kernel.org/r/1387315388-31676-2-git-send-email-khilman@linaro.org
[move ad-hoc conversion to jiffies_to_nsecs helper]
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
parent e9a2eb40
...@@ -294,6 +294,12 @@ extern unsigned long preset_lpj; ...@@ -294,6 +294,12 @@ extern unsigned long preset_lpj;
*/ */
extern unsigned int jiffies_to_msecs(const unsigned long j); extern unsigned int jiffies_to_msecs(const unsigned long j);
extern unsigned int jiffies_to_usecs(const unsigned long j); extern unsigned int jiffies_to_usecs(const unsigned long j);
static inline u64 jiffies_to_nsecs(const unsigned long j)
{
return (u64)jiffies_to_usecs(j) * NSEC_PER_USEC;
}
extern unsigned long msecs_to_jiffies(const unsigned int m); extern unsigned long msecs_to_jiffies(const unsigned int m);
extern unsigned long usecs_to_jiffies(const unsigned int u); extern unsigned long usecs_to_jiffies(const unsigned int u);
extern unsigned long timespec_to_jiffies(const struct timespec *value); extern unsigned long timespec_to_jiffies(const struct timespec *value);
......
...@@ -2325,7 +2325,7 @@ u64 scheduler_tick_max_deferment(void) ...@@ -2325,7 +2325,7 @@ u64 scheduler_tick_max_deferment(void)
if (time_before_eq(next, now)) if (time_before_eq(next, now))
return 0; return 0;
return jiffies_to_usecs(next - now) * NSEC_PER_USEC; return jiffies_to_nsecs(next - now);
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment