public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch] delay panic during startup of kernel
@ 2009-10-21 23:38 Michael Sundius
  2009-10-26  8:41 ` Andi Kleen
  0 siblings, 1 reply; 2+ messages in thread
From: Michael Sundius @ 2009-10-21 23:38 UTC (permalink / raw)
  To: linux-kernel, msundius, msundius

We've been, from time to time,  running into various problems early on
the initialization of the kernel, encountering situations where we really
should panic, but we can't because its too early to do so.
(see * if you care to know why this is a problem for us). Anyhow, I've
created this patch to have a little better way of orderly finishing the
bring-up to the point where we can panic safely. Any comments?


*One reason this often happens to us is that we have added hooks
for our drivers to allocate contiguous blocks of memory very early and
our driver team doesn't always communicate when changes have been
made.

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index f4e3184..b2e7bac 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -163,6 +163,10 @@ extern struct atomic_notifier_head panic_notifier_list;
 extern long (*panic_blink)(long time);
 NORET_TYPE void panic(const char * fmt, ...)
        __attribute__ ((NORET_AND format (printf, 1, 2))) __cold;
+extern void panic_later(const char * fmt, ...)
+       __attribute__ ((format (printf, 1, 2)));
+extern void panic_later_complete(void);
+extern bool panic_later_pending(void);
 extern void oops_enter(void);
 extern void oops_exit(void);
 extern int oops_may_print(void);
diff --git a/init/main.c b/init/main.c
index 5988deb..2a9347a 100644
--- a/init/main.c
+++ b/init/main.c
@@ -185,7 +185,6 @@ __setup("reset_devices", set_reset_devices);

 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
-static const char *panic_later, *panic_param;

 extern struct obs_kernel_param __setup_start[], __setup_end[];

@@ -281,7 +280,7 @@ static int __init unknown_bootoption(char *param, 
char *val)
                return 0;
        }

-       if (panic_later)
+       if (panic_later_pending())
                return 0;

        if (val) {
@@ -289,8 +288,7 @@ static int __init unknown_bootoption(char *param, 
char *val)
                unsigned int i;
                for (i = 0; envp_init[i]; i++) {
                        if (i == MAX_INIT_ENVS) {
-                               panic_later = "Too many boot env vars at 
`%s'";
-                               panic_param = param;
+                               panic_later("Too many boot env vars at 
`%s'", param);
                        }
                        if (!strncmp(param, envp_init[i], val - param))
                                break;
@@ -301,8 +299,7 @@ static int __init unknown_bootoption(char *param, 
char *val)
                unsigned int i;
                for (i = 0; argv_init[i]; i++) {
                        if (i == MAX_INIT_ARGS) {
-                               panic_later = "Too many boot init vars 
at `%s'";
-                               panic_param = param;
+                               panic_later("Too many boot init vars at 
`%s'", param);
                        }
                }
                argv_init[i] = param;
@@ -621,8 +618,7 @@ asmlinkage void __init start_kernel(void)
         * this. But we do want output early, in case something goes wrong.
         */
        console_init();
-       if (panic_later)
-               panic(panic_later, panic_param);
+       panic_later_complete();

        lockdep_info();

diff --git a/kernel/panic.c b/kernel/panic.c
index 96b45d0..092bb46 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -23,6 +23,9 @@
 #include <linux/nmi.h>
 #include <linux/dmi.h>

+#define MAX_PANIC_LATER_LEN    1024
+static char panic_later_msg[MAX_PANIC_LATER_LEN];
+
 int panic_on_oops;
 static unsigned long tainted_mask;
 static int pause_on_oops;
@@ -40,6 +43,28 @@ static long no_blink(long time)
        return 0;
 }

+void panic_later(const char *fmt, ...)
+{
+       va_list args;
+
+       if (!panic_later_pending()) {
+               va_start(args, fmt);
+               vsnprintf(panic_later_msg, sizeof(panic_later_msg), fmt, 
args);
+               va_end(args);
+       }
+}
+
+bool panic_later_pending()
+{
+       return panic_later_msg[0] != 0;
+}
+
+void panic_later_complete()
+{
+       if (panic_later_pending())
+               panic("%s", panic_later_msg);
+}
+
 /* Returns how long it waited in ms */
 long (*panic_blink)(long time);
 EXPORT_SYMBOL(panic_blink);

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-10-26  8:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-21 23:38 [patch] delay panic during startup of kernel Michael Sundius
2009-10-26  8:41 ` Andi Kleen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox