aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2013-09-11 19:50:56 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-01 12:17:45 -0400
commit63946e8616205dafe39b4d88f9fc3dc7c4fd79aa (patch)
treee1f6377f19f8fd692376a336713f99dc0ac93344 /kernel
parentbeb6f0e8d246adca601d786d206d414d1d0a549b (diff)
timekeeping: Fix HRTICK related deadlock from ntp lock changes
commit 7bd36014460f793c19e7d6c94dab67b0afcfcb7f upstream. Gerlando Falauto reported that when HRTICK is enabled, it is possible to trigger system deadlocks. These were hard to reproduce, as HRTICK has been broken in the past, but seemed to be connected to the timekeeping_seq lock. Since seqlock/seqcount's aren't supported w/ lockdep, I added some extra spinlock based locking and triggered the following lockdep output: [ 15.849182] ntpd/4062 is trying to acquire lock: [ 15.849765] (&(&pool->lock)->rlock){..-...}, at: [<ffffffff810aa9b5>] __queue_work+0x145/0x480 [ 15.850051] [ 15.850051] but task is already holding lock: [ 15.850051] (timekeeper_lock){-.-.-.}, at: [<ffffffff810df6df>] do_adjtimex+0x7f/0x100 <snip> [ 15.850051] Chain exists of: &(&pool->lock)->rlock --> &p->pi_lock --> timekeeper_lock [ 15.850051] Possible unsafe locking scenario: [ 15.850051] [ 15.850051] CPU0 CPU1 [ 15.850051] ---- ---- [ 15.850051] lock(timekeeper_lock); [ 15.850051] lock(&p->pi_lock); [ 15.850051] lock(timekeeper_lock); [ 15.850051] lock(&(&pool->lock)->rlock); [ 15.850051] [ 15.850051] *** DEADLOCK *** The deadlock was introduced by 06c017fdd4dc48451a ("timekeeping: Hold timekeepering locks in do_adjtimex and hardpps") in 3.10 This patch avoids this deadlock, by moving the call to schedule_delayed_work() outside of the timekeeper lock critical section. Reported-by: Gerlando Falauto <gerlando.falauto@keymile.com> Tested-by: Lin Ming <minggr@gmail.com> Signed-off-by: John Stultz <john.stultz@linaro.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Link: http://lkml.kernel.org/r/1378943457-27314-1-git-send-email-john.stultz@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/time/ntp.c6
-rw-r--r--kernel/time/timekeeping.c2
2 files changed, 4 insertions, 4 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 8f5b3b98577b..bb2215174f05 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -516,13 +516,13 @@ static void sync_cmos_clock(struct work_struct *work)
516 schedule_delayed_work(&sync_cmos_work, timespec_to_jiffies(&next)); 516 schedule_delayed_work(&sync_cmos_work, timespec_to_jiffies(&next));
517} 517}
518 518
519static void notify_cmos_timer(void) 519void ntp_notify_cmos_timer(void)
520{ 520{
521 schedule_delayed_work(&sync_cmos_work, 0); 521 schedule_delayed_work(&sync_cmos_work, 0);
522} 522}
523 523
524#else 524#else
525static inline void notify_cmos_timer(void) { } 525void ntp_notify_cmos_timer(void) { }
526#endif 526#endif
527 527
528 528
@@ -687,8 +687,6 @@ int __do_adjtimex(struct timex *txc, struct timespec *ts, s32 *time_tai)
687 if (!(time_status & STA_NANO)) 687 if (!(time_status & STA_NANO))
688 txc->time.tv_usec /= NSEC_PER_USEC; 688 txc->time.tv_usec /= NSEC_PER_USEC;
689 689
690 notify_cmos_timer();
691
692 return result; 690 return result;
693} 691}
694 692
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index baeeb5c87cf1..fcc261c5df29 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1682,6 +1682,8 @@ int do_adjtimex(struct timex *txc)
1682 write_seqcount_end(&timekeeper_seq); 1682 write_seqcount_end(&timekeeper_seq);
1683 raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 1683 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
1684 1684
1685 ntp_notify_cmos_timer();
1686
1685 return ret; 1687 return ret;
1686} 1688}
1687 1689