Messages in this thread Patch in this message | | | Subject | [PATCH] printk: robustify printk | From | Peter Zijlstra <> | Date | Fri, 08 Aug 2008 20:14:28 +0200 |
| |
Avoid deadlocks against rq->lock and xtime_lock by using RCU to defer the klogd wakeup.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Steven Rostedt <srostedt@redhat.com> --- diff --git a/kernel/printk.c b/kernel/printk.c index b51b156..8870c2e 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -32,6 +32,7 @@ #include <linux/security.h> #include <linux/bootmem.h> #include <linux/syscalls.h> +#include <linux/rcupdate.h> #include <asm/uaccess.h> @@ -982,10 +983,37 @@ int is_console_locked(void) return console_locked; } +struct klogd_wakeup_state { + struct rcu_head head; + int pending; +}; + +DEFINE_PER_CPU(struct klogd_wakeup_state, kws); + +void __wake_up_klogd(struct rcu_head *head) +{ + struct klogd_wakeup_state *kws = + container_of(head, struct klogd_wakeup_state, head); + + wake_up_interruptible(&log_wait); + kws->pending = 0; +} + void wake_up_klogd(void) { - if (!oops_in_progress && waitqueue_active(&log_wait)) - wake_up_interruptible(&log_wait); + unsigned long flags; + struct klogd_wakeup_state *kws; + + if (!waitqueue_active(&log_wait)) + return; + + local_irq_save(flags); + kws = &__get_cpu_var(kws); + if (!kws->pending) { + kws->pending = 1; + call_rcu(&kws->head, __wake_up_klogd); + } + local_irq_restore(flags); } /**
| |