timekeeping: Move ADJ_SETOFFSET to top level do_adjtimex()
John Stultz [Fri, 22 Mar 2013 22:04:13 +0000 (15:04 -0700)]
Since ADJ_SETOFFSET adjusts the timekeeping state, process
it as part of the top level do_adjtimex() function in
timekeeping.c.

This avoids deadlocks that could occur once we change the
ntp locking rules.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>

kernel/time/ntp.c
kernel/time/timekeeping.c

index d17e13c..a331ebc 100644 (file)
@@ -666,17 +666,6 @@ int __do_adjtimex(struct timex *txc, struct timespec *ts, s32 *time_tai)
 {
        int result;
 
-       if (txc->modes & ADJ_SETOFFSET) {
-               struct timespec delta;
-               delta.tv_sec  = txc->time.tv_sec;
-               delta.tv_nsec = txc->time.tv_usec;
-               if (!(txc->modes & ADJ_NANO))
-                       delta.tv_nsec *= 1000;
-               result = timekeeping_inject_offset(&delta);
-               if (result)
-                       return result;
-       }
-
        raw_spin_lock_irq(&ntp_lock);
 
        if (txc->modes & ADJ_ADJTIME) {
index 5f7a233..e44915c 100644 (file)
@@ -1627,6 +1627,17 @@ int do_adjtimex(struct timex *txc)
        if (ret)
                return ret;
 
+       if (txc->modes & ADJ_SETOFFSET) {
+               struct timespec delta;
+               delta.tv_sec  = txc->time.tv_sec;
+               delta.tv_nsec = txc->time.tv_usec;
+               if (!(txc->modes & ADJ_NANO))
+                       delta.tv_nsec *= 1000;
+               ret = timekeeping_inject_offset(&delta);
+               if (ret)
+                       return ret;
+       }
+
        getnstimeofday(&ts);
        orig_tai = tai = timekeeping_get_tai_offset();