]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
kdump: fix crash_kexec()/smp_send_stop() race in panic
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>
Wed, 16 Nov 2011 23:41:48 +0000 (10:41 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 17 Nov 2011 02:57:21 +0000 (13:57 +1100)
When two CPUs call panic at the same time there is a possible race
condition that can stop kdump.  The first CPU calls crash_kexec() and the
second CPU calls smp_send_stop() in panic() before crash_kexec() finished
on the first CPU.  So the second CPU stops the first CPU and therefore
kdump fails:

1st CPU:
panic()->crash_kexec()->mutex_trylock(&kexec_mutex)-> do kdump

2nd CPU:
panic()->crash_kexec()->kexec_mutex already held by 1st CPU
       ->smp_send_stop()-> stop 1st CPU (stop kdump)

This patch fixes the problem by introducing a spinlock in panic that
allows only one CPU to process crash_kexec() and the subsequent panic
code.

Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
kernel/panic.c

index 9b7df21d51fb1013a741f2fa7d55d8aba9d2b307..13f8c3eecedad06fc216997c380e1e39fbddcd0f 100644 (file)
@@ -59,6 +59,7 @@ EXPORT_SYMBOL(panic_blink);
  */
 void panic(const char *fmt, ...)
 {
+       static DEFINE_SPINLOCK(panic_lock);
        static char buf[1024];
        va_list args;
        long i, i_next = 0;
@@ -81,6 +82,13 @@ void panic(const char *fmt, ...)
        dump_stack();
 #endif
 
+       /*
+        * Only one CPU is allowed to execute the panic code from here. For
+        * multiple parallel invocations of panic all other CPUs will wait on
+        * the panic_lock. They are stopped afterwards by smp_send_stop().
+        */
+       spin_lock(&panic_lock);
+
        /*
         * If we have crashed and we have a crash kernel loaded let it handle
         * everything else.