diff options
author | John Stultz <john.stultz@linaro.org> | 2012-03-14 19:38:15 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2012-03-15 21:17:54 -0400 |
commit | f695cf94837de53864180400cbac42cfa370426f (patch) | |
tree | 9bb91a9b8c5a1291a083a37e790da00d477b18f8 /kernel | |
parent | a939e817aa7e199d2fff05a67cb745be32dd5c2d (diff) |
time: Fix change_clocksource locking
change_clocksource() fails to grab locks or call timekeeping_update(),
which leaves a race window for time inconsistencies.
This adds proper locking and a call to timekeeping_update() to fix this.
CC: Andy Lutomirski <luto@amacapital.net>
CC: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/time/timekeeping.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 403c2a092830..b53da5ecbea2 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -448,9 +448,12 @@ EXPORT_SYMBOL(timekeeping_inject_offset); | |||
448 | static int change_clocksource(void *data) | 448 | static int change_clocksource(void *data) |
449 | { | 449 | { |
450 | struct clocksource *new, *old; | 450 | struct clocksource *new, *old; |
451 | unsigned long flags; | ||
451 | 452 | ||
452 | new = (struct clocksource *) data; | 453 | new = (struct clocksource *) data; |
453 | 454 | ||
455 | write_seqlock_irqsave(&timekeeper.lock, flags); | ||
456 | |||
454 | timekeeping_forward_now(); | 457 | timekeeping_forward_now(); |
455 | if (!new->enable || new->enable(new) == 0) { | 458 | if (!new->enable || new->enable(new) == 0) { |
456 | old = timekeeper.clock; | 459 | old = timekeeper.clock; |
@@ -458,6 +461,10 @@ static int change_clocksource(void *data) | |||
458 | if (old->disable) | 461 | if (old->disable) |
459 | old->disable(old); | 462 | old->disable(old); |
460 | } | 463 | } |
464 | timekeeping_update(true); | ||
465 | |||
466 | write_sequnlock_irqrestore(&timekeeper.lock, flags); | ||
467 | |||
461 | return 0; | 468 | return 0; |
462 | } | 469 | } |
463 | 470 | ||