Commit b845b517b5e3706a3729f6ea83b88ab85f0725b0

Authored by Peter Zijlstra
Committed by Ingo Molnar
1 parent 796aadeb1b

printk: robustify printk

Avoid deadlocks against rq->lock and xtime_lock by deferring the klogd
wakeup by polling from the timer tick.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Showing 4 changed files with 23 additions and 3 deletions Side-by-side Diff

include/linux/kernel.h
... ... @@ -200,6 +200,8 @@
200 200 extern int printk_ratelimit(void);
201 201 extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
202 202 unsigned int interval_msec);
  203 +extern void printk_tick(void);
  204 +extern int printk_needs_cpu(int);
203 205 #else
204 206 static inline int vprintk(const char *s, va_list args)
205 207 __attribute__ ((format (printf, 1, 0)));
... ... @@ -211,6 +213,8 @@
211 213 static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies, \
212 214 unsigned int interval_msec) \
213 215 { return false; }
  216 +static inline void printk_tick(void) { }
  217 +static inline int printk_needs_cpu(int) { return 0; }
214 218 #endif
215 219  
216 220 extern void asmlinkage __attribute__((format(printf, 1, 2)))
... ... @@ -982,10 +982,25 @@
982 982 return console_locked;
983 983 }
984 984  
985   -void wake_up_klogd(void)
  985 +static DEFINE_PER_CPU(int, printk_pending);
  986 +
  987 +void printk_tick(void)
986 988 {
987   - if (!oops_in_progress && waitqueue_active(&log_wait))
  989 + if (__get_cpu_var(printk_pending)) {
  990 + __get_cpu_var(printk_pending) = 0;
988 991 wake_up_interruptible(&log_wait);
  992 + }
  993 +}
  994 +
  995 +int printk_needs_cpu(int cpu)
  996 +{
  997 + return per_cpu(printk_pending, cpu);
  998 +}
  999 +
  1000 +void wake_up_klogd(void)
  1001 +{
  1002 + if (waitqueue_active(&log_wait))
  1003 + __get_cpu_var(printk_pending) = 1;
989 1004 }
990 1005  
991 1006 /**
kernel/time/tick-sched.c
... ... @@ -255,7 +255,7 @@
255 255 next_jiffies = get_next_timer_interrupt(last_jiffies);
256 256 delta_jiffies = next_jiffies - last_jiffies;
257 257  
258   - if (rcu_needs_cpu(cpu))
  258 + if (rcu_needs_cpu(cpu) || printk_needs_cpu(cpu))
259 259 delta_jiffies = 1;
260 260 /*
261 261 * Do not stop the tick, if we are only one off
... ... @@ -978,6 +978,7 @@
978 978 run_local_timers();
979 979 if (rcu_pending(cpu))
980 980 rcu_check_callbacks(cpu, user_tick);
  981 + printk_tick();
981 982 scheduler_tick();
982 983 run_posix_cpu_timers(p);
983 984 }