aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2014-06-04 19:11:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-04 19:54:17 -0400
commit6d9bcb621b0b0a20604cbdb298c4487e44dd0da2 (patch)
treee6bb8032b8662be3551d4abcc04499c39c9e85df /kernel/time
parentc224815dac9c739b79050d3cc67443ff500bc478 (diff)
timekeeping: use printk_deferred when holding timekeeping seqlock
Jiri Bohac pointed out that there are rare but potential deadlock possibilities when calling printk while holding the timekeeping seqlock. This is due to printk() triggering console sem wakeup, which can cause scheduling code to trigger hrtimers which may try to read the time. Specifically, as Jiri pointed out, that path is: printk vprintk_emit console_unlock up(&console_sem) __up wake_up_process try_to_wake_up ttwu_do_activate ttwu_activate activate_task enqueue_task enqueue_task_fair hrtick_update hrtick_start_fair hrtick_start_fair get_time ktime_get --> endless loop on read_seqcount_retry(&timekeeper_seq, ...) This patch tries to avoid this issue by using printk_deferred (previously named printk_sched) which should defer printing via a irq_work_queue. Signed-off-by: John Stultz <john.stultz@linaro.org> Reported-by: Jiri Bohac <jbohac@suse.cz> Reviewed-by: Steven Rostedt <rostedt@goodmis.org> Cc: Jan Kara <jack@suse.cz> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/time')
-rw-r--r--kernel/time/ntp.c15
-rw-r--r--kernel/time/timekeeping.c7
2 files changed, 13 insertions, 9 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 419a52cecd20..5b0ac4de3822 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -786,8 +786,9 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
786 time_status |= STA_PPSERROR; 786 time_status |= STA_PPSERROR;
787 pps_errcnt++; 787 pps_errcnt++;
788 pps_dec_freq_interval(); 788 pps_dec_freq_interval();
789 pr_err("hardpps: PPSERROR: interval too long - %ld s\n", 789 printk_deferred(KERN_ERR
790 freq_norm.sec); 790 "hardpps: PPSERROR: interval too long - %ld s\n",
791 freq_norm.sec);
791 return 0; 792 return 0;
792 } 793 }
793 794
@@ -800,7 +801,8 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
800 delta = shift_right(ftemp - pps_freq, NTP_SCALE_SHIFT); 801 delta = shift_right(ftemp - pps_freq, NTP_SCALE_SHIFT);
801 pps_freq = ftemp; 802 pps_freq = ftemp;
802 if (delta > PPS_MAXWANDER || delta < -PPS_MAXWANDER) { 803 if (delta > PPS_MAXWANDER || delta < -PPS_MAXWANDER) {
803 pr_warning("hardpps: PPSWANDER: change=%ld\n", delta); 804 printk_deferred(KERN_WARNING
805 "hardpps: PPSWANDER: change=%ld\n", delta);
804 time_status |= STA_PPSWANDER; 806 time_status |= STA_PPSWANDER;
805 pps_stbcnt++; 807 pps_stbcnt++;
806 pps_dec_freq_interval(); 808 pps_dec_freq_interval();
@@ -844,8 +846,9 @@ static void hardpps_update_phase(long error)
844 * the time offset is updated. 846 * the time offset is updated.
845 */ 847 */
846 if (jitter > (pps_jitter << PPS_POPCORN)) { 848 if (jitter > (pps_jitter << PPS_POPCORN)) {
847 pr_warning("hardpps: PPSJITTER: jitter=%ld, limit=%ld\n", 849 printk_deferred(KERN_WARNING
848 jitter, (pps_jitter << PPS_POPCORN)); 850 "hardpps: PPSJITTER: jitter=%ld, limit=%ld\n",
851 jitter, (pps_jitter << PPS_POPCORN));
849 time_status |= STA_PPSJITTER; 852 time_status |= STA_PPSJITTER;
850 pps_jitcnt++; 853 pps_jitcnt++;
851 } else if (time_status & STA_PPSTIME) { 854 } else if (time_status & STA_PPSTIME) {
@@ -902,7 +905,7 @@ void __hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
902 time_status |= STA_PPSJITTER; 905 time_status |= STA_PPSJITTER;
903 /* restart the frequency calibration interval */ 906 /* restart the frequency calibration interval */
904 pps_fbase = *raw_ts; 907 pps_fbase = *raw_ts;
905 pr_err("hardpps: PPSJITTER: bad pulse\n"); 908 printk_deferred(KERN_ERR "hardpps: PPSJITTER: bad pulse\n");
906 return; 909 return;
907 } 910 }
908 911
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index f7df8ea21707..32d8d6aaedb8 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -852,8 +852,9 @@ static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
852 struct timespec *delta) 852 struct timespec *delta)
853{ 853{
854 if (!timespec_valid_strict(delta)) { 854 if (!timespec_valid_strict(delta)) {
855 printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid " 855 printk_deferred(KERN_WARNING
856 "sleep delta value!\n"); 856 "__timekeeping_inject_sleeptime: Invalid "
857 "sleep delta value!\n");
857 return; 858 return;
858 } 859 }
859 tk_xtime_add(tk, delta); 860 tk_xtime_add(tk, delta);
@@ -1157,7 +1158,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
1157 1158
1158 if (unlikely(tk->clock->maxadj && 1159 if (unlikely(tk->clock->maxadj &&
1159 (tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) { 1160 (tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) {
1160 printk_once(KERN_WARNING 1161 printk_deferred_once(KERN_WARNING
1161 "Adjusting %s more than 11%% (%ld vs %ld)\n", 1162 "Adjusting %s more than 11%% (%ld vs %ld)\n",
1162 tk->clock->name, (long)tk->mult + adj, 1163 tk->clock->name, (long)tk->mult + adj,
1163 (long)tk->clock->mult + tk->clock->maxadj); 1164 (long)tk->clock->mult + tk->clock->maxadj);