Commit-ID: 1d17d17484d40f2d5b35c79518597a2b25296996 Gitweb: http://git.kernel.org/tip/1d17d17484d40f2d5b35c79518597a2b25296996 Author: Ingo Molnar <mi...@kernel.org> AuthorDate: Sat, 4 Aug 2012 21:21:14 +0200 Committer: Ingo Molnar <mi...@kernel.org> CommitDate: Sun, 5 Aug 2012 12:37:14 +0200
time: Fix adjustment cleanup bug in timekeeping_adjust() Tetsuo Handa reported that sporadically the system clock starts counting up too quickly which is enough to confuse the hangcheck timer to print a bogus stall warning. Commit 2a8c0883 "time: Move xtime_nsec adjustment underflow handling timekeeping_adjust" overlooked this exit path: } else return; which should really be a proper exit sequence, fixing the bug as a side effect. Also make the flow more readable by properly balancing curly braces. Reported-by: Tetsuo Handa <penguin-ker...@i-love.sakura.ne.jp> wrote: Tested-by: Tetsuo Handa <penguin-ker...@i-love.sakura.ne.jp> wrote: Signed-off-by: Ingo Molnar <mi...@kernel.org> Cc: john.stu...@linaro.org Cc: a.p.zijls...@chello.nl Cc: richardcoch...@gmail.com Cc: pra...@redhat.com Link: http://lkml.kernel.org/r/20120804192114.ga28...@gmail.com Signed-off-by: Ingo Molnar <mi...@kernel.org> --- kernel/time/timekeeping.c | 31 +++++++++++++++++-------------- 1 files changed, 17 insertions(+), 14 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 2988bc8..e16af19 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -923,20 +923,22 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) if (likely(error <= interval)) adj = 1; else - adj = timekeeping_bigadjust(tk, error, &interval, - &offset); - } else if (error < -interval) { - /* See comment above, this is just switched for the negative */ - error >>= 2; - if (likely(error >= -interval)) { - adj = -1; - interval = -interval; - offset = -offset; - } else - adj = timekeeping_bigadjust(tk, error, &interval, - &offset); - } else - return; + adj = timekeeping_bigadjust(tk, error, &interval, &offset); + } else { + if (error < -interval) { + /* See comment above, this is just switched for the negative */ + error >>= 2; + if (likely(error >= -interval)) { + adj = -1; + interval = -interval; + offset = -offset; + } else { + adj = timekeeping_bigadjust(tk, error, &interval, &offset); + } + } else { + goto out_adjust; + } + } if (unlikely(tk->clock->maxadj && (tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) { @@ -999,6 +1001,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset) tk->xtime_nsec -= offset; tk->ntp_error -= (interval - offset) << tk->ntp_error_shift; +out_adjust: /* * It may be possible that when we entered this function, xtime_nsec * was very small. Further, if we're slightly speeding the clocksource -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/