mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 14:21:47 +00:00
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>
This commit is contained in:
parent
e7882d6c40
commit
1d17d17484
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user