From 0983a88b9f0ceffb2116ce92c7b273ce2aec7b93 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 4 Feb 2008 22:31:08 -0800 Subject: uml: install panic notifier earlier It turns out that if there's a panic early enough, UML will just sit there in the LED-blinking loop because the panic notifier hadn't been installed yet. This patch installs it earlier. It also fixes the problem which exposed the hang, namely that if you give UML a zero-sized initrd, it will ask alloc_bootmem for zero bytes, and that will cause the panic. While I was in initrd.c, I gave it a style makeover. Prompted by checkpatch, I moved a couple extern declarations of uml_exitcode to kern_util.h. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/kern_util.h | 2 ++ arch/um/kernel/initrd.c | 29 ++++++++++++++++++++--------- arch/um/kernel/um_arch.c | 41 ++++++++++++++++++++--------------------- arch/um/os-Linux/main.c | 2 -- 4 files changed, 42 insertions(+), 32 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 625ca2924a56..715ffb5b95c1 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -9,6 +9,8 @@ #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" +extern int uml_exitcode; + extern int ncpus; extern int kmalloc_ok; extern int nsyscalls; diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c index ae31c62f0323..fa015565001b 100644 --- a/arch/um/kernel/initrd.c +++ b/arch/um/kernel/initrd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -20,18 +20,27 @@ static int __init read_initrd(void) long long size; int err; - if(initrd == NULL) + if (initrd == NULL) return 0; err = os_file_size(initrd, &size); - if(err) + if (err) return 0; + /* + * This is necessary because alloc_bootmem craps out if you + * ask for no memory. + */ + if (size == 0) { + printk(KERN_ERR "\"%\" is a zero-size initrd\n"); + return 0; + } + area = alloc_bootmem(size); - if(area == NULL) + if (area == NULL) return 0; - if(load_initrd(initrd, area, size) == -1) + if (load_initrd(initrd, area, size) == -1) return 0; initrd_start = (unsigned long) area; @@ -58,13 +67,15 @@ int load_initrd(char *filename, void *buf, int size) int fd, n; fd = os_open_file(filename, of_read(OPENFLAGS()), 0); - if(fd < 0){ - printk("Opening '%s' failed - err = %d\n", filename, -fd); + if (fd < 0) { + printk(KERN_ERR "Opening '%s' failed - err = %d\n", filename, + -fd); return -1; } n = os_read_file(fd, buf, size); - if(n != size){ - printk("Read of %d bytes from '%s' failed, err = %d\n", size, + if (n != size) { + printk(KERN_ERR "Read of %d bytes from '%s' failed, " + "err = %d\n", size, filename, -n); return -1; } diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 9ba39ab5f4bd..cb7eef833bc8 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -223,6 +223,23 @@ static void __init uml_postsetup(void) return; } +static int panic_exit(struct notifier_block *self, unsigned long unused1, + void *unused2) +{ + bust_spinlocks(1); + show_regs(&(current->thread.regs)); + bust_spinlocks(0); + uml_exitcode = 1; + os_dump_core(); + return 0; +} + +static struct notifier_block panic_exit_notifier = { + .notifier_call = panic_exit, + .next = NULL, + .priority = 0 +}; + /* Set during early boot */ unsigned long brk_start; unsigned long end_iomem; @@ -327,6 +344,9 @@ int __init linux_main(int argc, char **argv) printf("Kernel virtual memory size shrunk to %lu bytes\n", virtmem_size); + atomic_notifier_chain_register(&panic_notifier_list, + &panic_exit_notifier); + uml_postsetup(); stack_protections((unsigned long) &init_thread_info); @@ -335,29 +355,8 @@ int __init linux_main(int argc, char **argv) return start_uml(); } -extern int uml_exitcode; - -static int panic_exit(struct notifier_block *self, unsigned long unused1, - void *unused2) -{ - bust_spinlocks(1); - show_regs(&(current->thread.regs)); - bust_spinlocks(0); - uml_exitcode = 1; - os_dump_core(); - return 0; -} - -static struct notifier_block panic_exit_notifier = { - .notifier_call = panic_exit, - .next = NULL, - .priority = 0 -}; - void __init setup_arch(char **cmdline_p) { - atomic_notifier_chain_register(&panic_notifier_list, - &panic_exit_notifier); paging_init(); strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index de664e7ff310..abb9b0ffd960 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -111,8 +111,6 @@ static void setup_env_path(void) } } -extern int uml_exitcode; - extern void scan_elf_aux( char **envp); int __init main(int argc, char **argv, char **envp) -- cgit v1.2.1