The only place where kernel_execve() is called without a way to return to the caller of kernel_thread() callback is kernel_post(). Reorganize kernel_init()/kernel_post() - instead of the former calling the latter in the end (and getting freed by it), have the latter *begin* with calling the former (and turn the latter into kernel_thread() callback, of course).
Unified · Split
| @@ -794,11 +794,11 @@ static void run_init_process(const char *init_filename) · 793 unmodified lines | ||
| 794 | 794 | kernel_execve(init_filename, argv_init, envp_init); |
| 795 | 795 | } |
| 796 | 796 | |
| 797 | −/* This is a non __init function. Force it to be noinline otherwise gcc | |
| 798 | − * makes it inline to init() and it becomes part of init.text section | |
| 799 | − */ | |
| 800 | −static noinline int init_post(void) | |
| 797 | +static void __init kernel_init_freeable(void); | |
| 798 | + | |
| 799 | +static int __ref kernel_init(void *unused) | |
| 801 | 800 | { |
| 801 | + kernel_init_freeable(); | |
| 802 | 802 | /* need to finish all async __init code before freeing the memory */ |
| 803 | 803 | async_synchronize_full(); |
| 804 | 804 | free_initmem(); |
| @@ -835,7 +835,7 @@ static noinline int init_post(void) · 30 unmodified lines | ||
| 835 | 835 | "See Linux Documentation/init.txt for guidance."); |
| 836 | 836 | } |
| 837 | 837 | |
| 838 | −static int __init kernel_init(void * unused) | |
| 838 | +static void __init kernel_init_freeable(void) | |
| 839 | 839 | { |
| 840 | 840 | /* |
| 841 | 841 | * Wait until kthreadd is all set-up. |
| @@ -890,7 +890,4 @@ static int __init kernel_init(void * unused) · 48 unmodified lines | ||
| 890 | 890 | * we're essentially up and running. Get rid of the |
| 891 | 891 | * initmem segments and start the user-mode stuff.. |
| 892 | 892 | */ |
| 893 | − | |
| 894 | − init_post(); | |
| 895 | − return 0; | |
| 896 | 893 | } |