Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

init: make init failures more explicit

This patch proposes to make init failures more explicit.

Before this, the "No init found" message didn't help much. It could
sometimes be misleading and actually mean "No *working* init found".

This message could hide many different issues:
- no init program candidates found at all
- some init program candidates exist but can't be executed (missing
execute permissions, failed to load shared libraries, executable
compiled for an unknown architecture...)

This patch notifies the kernel user when a candidate init program is found
but can't be executed. In each failure situation, the error code is
displayed, to quickly find the root cause. "No init found" is also
replaced by "No working init found", which is more correct.

This will help embedded Linux developers (especially the newcomers),
regularly making and debugging new root filesystems.

Credits to Geert Uytterhoeven and Janne Karhunen for their improvement
suggestions.

Signed-off-by: Michael Opdenacker <michael.opdenacker@free-electrons.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Tested-by: Janne Karhunen <Janne.Karhunen@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Michael Opdenacker and committed by
Linus Torvalds
ba24762b df3ef3af

+29 -10
+29 -10
init/main.c
··· 810 810 (const char __user *const __user *)envp_init); 811 811 } 812 812 813 + static int try_to_run_init_process(const char *init_filename) 814 + { 815 + int ret; 816 + 817 + ret = run_init_process(init_filename); 818 + 819 + if (ret && ret != -ENOENT) { 820 + pr_err("Starting init: %s exists but couldn't execute it (error %d)\n", 821 + init_filename, ret); 822 + } 823 + 824 + return ret; 825 + } 826 + 813 827 static noinline void __init kernel_init_freeable(void); 814 828 815 829 static int __ref kernel_init(void *unused) 816 830 { 831 + int ret; 832 + 817 833 kernel_init_freeable(); 818 834 /* need to finish all async __init code before freeing the memory */ 819 835 async_synchronize_full(); ··· 841 825 flush_delayed_fput(); 842 826 843 827 if (ramdisk_execute_command) { 844 - if (!run_init_process(ramdisk_execute_command)) 828 + ret = run_init_process(ramdisk_execute_command); 829 + if (!ret) 845 830 return 0; 846 - pr_err("Failed to execute %s\n", ramdisk_execute_command); 831 + pr_err("Failed to execute %s (error %d)\n", 832 + ramdisk_execute_command, ret); 847 833 } 848 834 849 835 /* ··· 855 837 * trying to recover a really broken machine. 856 838 */ 857 839 if (execute_command) { 858 - if (!run_init_process(execute_command)) 840 + ret = run_init_process(execute_command); 841 + if (!ret) 859 842 return 0; 860 - pr_err("Failed to execute %s. Attempting defaults...\n", 861 - execute_command); 843 + pr_err("Failed to execute %s (error %d). Attempting defaults...\n", 844 + execute_command, ret); 862 845 } 863 - if (!run_init_process("/sbin/init") || 864 - !run_init_process("/etc/init") || 865 - !run_init_process("/bin/init") || 866 - !run_init_process("/bin/sh")) 846 + if (!try_to_run_init_process("/sbin/init") || 847 + !try_to_run_init_process("/etc/init") || 848 + !try_to_run_init_process("/bin/init") || 849 + !try_to_run_init_process("/bin/sh")) 867 850 return 0; 868 851 869 - panic("No init found. Try passing init= option to kernel. " 852 + panic("No working init found. Try passing init= option to kernel. " 870 853 "See Linux Documentation/init.txt for guidance."); 871 854 } 872 855