]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Feb 2014 17:53:10 +0000 (09:53 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Feb 2014 17:53:10 +0000 (09:53 -0800)
added patches:
timekeeping-fix-lost-updates-to-tai-adjustment.patch
timekeeping-fix-potential-lost-pv-notification-of-time-change.patch

queue-3.13/series
queue-3.13/timekeeping-fix-lost-updates-to-tai-adjustment.patch [new file with mode: 0644]
queue-3.13/timekeeping-fix-potential-lost-pv-notification-of-time-change.patch [new file with mode: 0644]

index 6c060650e04eb2569e1f8b14cf6202b697fb6a94..cf266a19e69789144c1c95509d8c2d704c542189 100644 (file)
@@ -109,3 +109,5 @@ ftrace-fix-synchronization-location-disabling-and-freeing-ftrace_ops.patch
 ftrace-have-function-graph-only-trace-based-on-global_ops-filters.patch
 powerpc-thp-fix-crash-on-mremap.patch
 powerpc-mm-fix-compile-error-of-pgtable-ppc64.h.patch
+timekeeping-fix-lost-updates-to-tai-adjustment.patch
+timekeeping-fix-potential-lost-pv-notification-of-time-change.patch
diff --git a/queue-3.13/timekeeping-fix-lost-updates-to-tai-adjustment.patch b/queue-3.13/timekeeping-fix-lost-updates-to-tai-adjustment.patch
new file mode 100644 (file)
index 0000000..625b7f0
--- /dev/null
@@ -0,0 +1,53 @@
+From f55c07607a38f84b5c7e6066ee1cfe433fa5643c Mon Sep 17 00:00:00 2001
+From: John Stultz <john.stultz@linaro.org>
+Date: Wed, 11 Dec 2013 18:50:25 -0800
+Subject: timekeeping: Fix lost updates to tai adjustment
+
+From: John Stultz <john.stultz@linaro.org>
+
+commit f55c07607a38f84b5c7e6066ee1cfe433fa5643c upstream.
+
+Since 48cdc135d4840 (Implement a shadow timekeeper), we have to
+call timekeeping_update() after any adjustment to the timekeeping
+structure in order to make sure that any adjustments to the structure
+persist.
+
+Unfortunately, the updates to the tai offset via adjtimex do not
+trigger this update, causing adjustments to the tai offset to be
+made and then over-written by the previous value at the next
+update_wall_time() call.
+
+This patch resovles the issue by calling timekeeping_update()
+right after setting the tai offset.
+
+Cc: Sasha Levin <sasha.levin@oracle.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Prarit Bhargava <prarit@redhat.com>
+Cc: Richard Cochran <richardcochran@gmail.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/time/timekeeping.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -610,6 +610,7 @@ void timekeeping_set_tai_offset(s32 tai_
+       raw_spin_lock_irqsave(&timekeeper_lock, flags);
+       write_seqcount_begin(&timekeeper_seq);
+       __timekeeping_set_tai_offset(tk, tai_offset);
++      timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
+       write_seqcount_end(&timekeeper_seq);
+       raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
+       clock_was_set();
+@@ -1698,7 +1699,7 @@ int do_adjtimex(struct timex *txc)
+       if (tai != orig_tai) {
+               __timekeeping_set_tai_offset(tk, tai);
+-              update_pvclock_gtod(tk, true);
++              timekeeping_update(tk, TK_MIRROR | TK_CLOCK_WAS_SET);
+               clock_was_set_delayed();
+       }
+       write_seqcount_end(&timekeeper_seq);
diff --git a/queue-3.13/timekeeping-fix-potential-lost-pv-notification-of-time-change.patch b/queue-3.13/timekeeping-fix-potential-lost-pv-notification-of-time-change.patch
new file mode 100644 (file)
index 0000000..77234fa
--- /dev/null
@@ -0,0 +1,123 @@
+From 5258d3f25c76f6ab86e9333abf97a55a877d3870 Mon Sep 17 00:00:00 2001
+From: John Stultz <john.stultz@linaro.org>
+Date: Wed, 11 Dec 2013 20:07:49 -0800
+Subject: timekeeping: Fix potential lost pv notification of time change
+
+From: John Stultz <john.stultz@linaro.org>
+
+commit 5258d3f25c76f6ab86e9333abf97a55a877d3870 upstream.
+
+In 780427f0e11 (Indicate that clock was set in the pvclock
+gtod notifier), logic was added to pass a CLOCK_WAS_SET
+notification to the pvclock notifier chain.
+
+While that patch added a action flag returned from
+accumulate_nsecs_to_secs(), it only uses the returned value
+in one location, and not in the logarithmic accumulation.
+
+This means if a leap second triggered during the logarithmic
+accumulation (which is most likely where it would happen),
+the notification that the clock was set would not make it to
+the pv notifiers.
+
+This patch extends the logarithmic_accumulation pass down
+that action flag so proper notification will occur.
+
+This patch also changes the varialbe action -> clock_set
+per Ingo's suggestion.
+
+Cc: Sasha Levin <sasha.levin@oracle.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: David Vrabel <david.vrabel@citrix.com>
+Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Cc: Prarit Bhargava <prarit@redhat.com>
+Cc: Richard Cochran <richardcochran@gmail.com>
+Cc: <xen-devel@lists.xen.org>
+Signed-off-by: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/time/timekeeping.c |   20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -1256,7 +1256,7 @@ out_adjust:
+ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
+ {
+       u64 nsecps = (u64)NSEC_PER_SEC << tk->shift;
+-      unsigned int action = 0;
++      unsigned int clock_set = 0;
+       while (tk->xtime_nsec >= nsecps) {
+               int leap;
+@@ -1279,10 +1279,10 @@ static inline unsigned int accumulate_ns
+                       __timekeeping_set_tai_offset(tk, tk->tai_offset - leap);
+                       clock_was_set_delayed();
+-                      action = TK_CLOCK_WAS_SET;
++                      clock_set = TK_CLOCK_WAS_SET;
+               }
+       }
+-      return action;
++      return clock_set;
+ }
+ /**
+@@ -1295,7 +1295,8 @@ static inline unsigned int accumulate_ns
+  * Returns the unconsumed cycles.
+  */
+ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
+-                                              u32 shift)
++                                              u32 shift,
++                                              unsigned int *clock_set)
+ {
+       cycle_t interval = tk->cycle_interval << shift;
+       u64 raw_nsecs;
+@@ -1309,7 +1310,7 @@ static cycle_t logarithmic_accumulation(
+       tk->cycle_last += interval;
+       tk->xtime_nsec += tk->xtime_interval << shift;
+-      accumulate_nsecs_to_secs(tk);
++      *clock_set |= accumulate_nsecs_to_secs(tk);
+       /* Accumulate raw time */
+       raw_nsecs = (u64)tk->raw_interval << shift;
+@@ -1367,7 +1368,7 @@ static void update_wall_time(void)
+       struct timekeeper *tk = &shadow_timekeeper;
+       cycle_t offset;
+       int shift = 0, maxshift;
+-      unsigned int action;
++      unsigned int clock_set = 0;
+       unsigned long flags;
+       raw_spin_lock_irqsave(&timekeeper_lock, flags);
+@@ -1402,7 +1403,8 @@ static void update_wall_time(void)
+       maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
+       shift = min(shift, maxshift);
+       while (offset >= tk->cycle_interval) {
+-              offset = logarithmic_accumulation(tk, offset, shift);
++              offset = logarithmic_accumulation(tk, offset, shift,
++                                                      &clock_set);
+               if (offset < tk->cycle_interval<<shift)
+                       shift--;
+       }
+@@ -1420,7 +1422,7 @@ static void update_wall_time(void)
+        * Finally, make sure that after the rounding
+        * xtime_nsec isn't larger than NSEC_PER_SEC
+        */
+-      action = accumulate_nsecs_to_secs(tk);
++      clock_set |= accumulate_nsecs_to_secs(tk);
+       write_seqcount_begin(&timekeeper_seq);
+       /* Update clock->cycle_last with the new value */
+@@ -1436,7 +1438,7 @@ static void update_wall_time(void)
+        * updating.
+        */
+       memcpy(real_tk, tk, sizeof(*tk));
+-      timekeeping_update(real_tk, action);
++      timekeeping_update(real_tk, clock_set);
+       write_seqcount_end(&timekeeper_seq);
+ out:
+       raw_spin_unlock_irqrestore(&timekeeper_lock, flags);