aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-08-04 15:21:14 -0400
committerIngo Molnar <mingo@kernel.org>2012-08-05 06:37:14 -0400
commit1d17d17484d40f2d5b35c79518597a2b25296996 (patch)
treea11000cb9a7197b5d70573d0faa417cb36ba0e4b /kernel
parente7882d6c40874a5b5033ca85f7508a602a60b662 (diff)
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-kernel@I-love.SAKURA.ne.jp> wrote: Tested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> wrote: Signed-off-by: Ingo Molnar <mingo@kernel.org> Cc: john.stultz@linaro.org Cc: a.p.zijlstra@chello.nl Cc: richardcochran@gmail.com Cc: prarit@redhat.com Link: http://lkml.kernel.org/r/20120804192114.GA28347@gmail.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/time/timekeeping.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 2988bc819187..e16af197a2bc 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -923,20 +923,22 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
923 if (likely(error <= interval)) 923 if (likely(error <= interval))
924 adj = 1; 924 adj = 1;
925 else 925 else
926 adj = timekeeping_bigadjust(tk, error, &interval, 926 adj = timekeeping_bigadjust(tk, error, &interval, &offset);
927 &offset); 927 } else {
928 } else if (error < -interval) { 928 if (error < -interval) {
929 /* See comment above, this is just switched for the negative */ 929 /* See comment above, this is just switched for the negative */
930 error >>= 2; 930 error >>= 2;
931 if (likely(error >= -interval)) { 931 if (likely(error >= -interval)) {
932 adj = -1; 932 adj = -1;
933 interval = -interval; 933 interval = -interval;
934 offset = -offset; 934 offset = -offset;
935 } else 935 } else {
936 adj = timekeeping_bigadjust(tk, error, &interval, 936 adj = timekeeping_bigadjust(tk, error, &interval, &offset);
937 &offset); 937 }
938 } else 938 } else {
939 return; 939 goto out_adjust;
940 }
941 }
940 942
941 if (unlikely(tk->clock->maxadj && 943 if (unlikely(tk->clock->maxadj &&
942 (tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) { 944 (tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) {
@@ -999,6 +1001,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
999 tk->xtime_nsec -= offset; 1001 tk->xtime_nsec -= offset;
1000 tk->ntp_error -= (interval - offset) << tk->ntp_error_shift; 1002 tk->ntp_error -= (interval - offset) << tk->ntp_error_shift;
1001 1003
1004out_adjust:
1002 /* 1005 /*
1003 * It may be possible that when we entered this function, xtime_nsec 1006 * It may be possible that when we entered this function, xtime_nsec
1004 * was very small. Further, if we're slightly speeding the clocksource 1007 * was very small. Further, if we're slightly speeding the clocksource