Skip to content

Commit

Permalink
time: Fix adjustment cleanup bug in timekeeping_adjust()
Browse files Browse the repository at this point in the history
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 2a8c088 "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>
  • Loading branch information
Ingo Molnar committed Aug 5, 2012
1 parent e7882d6 commit 1d17d17
Showing 1 changed file with 17 additions and 14 deletions.
31 changes: 17 additions & 14 deletions kernel/time/timekeeping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))) {
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 1d17d17

Please sign in to comment.