aboutsummaryrefslogtreecommitdiffstats
path: root/init/main.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 15:52:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 15:52:42 -0400
commit31a67102f4762df5544bc2dfb34a931233d2a5b2 (patch)
tree5ab348c520d60e331fb9e469cd592ee411f3850f /init/main.c
parente47b65b032f2997aa0a7392ecdf656c86d4d7561 (diff)
Fix blocking allocations called very early during bootup
During early boot, when the scheduler hasn't really been fully set up, we really can't do blocking allocations because with certain (dubious) configurations the "might_resched()" calls can actually result in scheduling events. We could just make such users always use GFP_ATOMIC, but quite often the code that does the allocation isn't really aware of the fact that the scheduler isn't up yet, and forcing that kind of random knowledge on the initialization code is just annoying and not good for anybody. And we actually have a the 'gfp_allowed_mask' exactly for this reason: it's just that the kernel init sequence happens to set it to allow blocking allocations much too early. So move the 'gfp_allowed_mask' initialization from 'start_kernel()' (which is some of the earliest init code, and runs with preemption disabled for good reasons) into 'kernel_init()'. kernel_init() is run in the newly created thread that will become the 'init' process, as opposed to the early startup code that runs within the context of what will be the first idle thread. So by the time we reach 'kernel_init()', we know that the scheduler must be at least limping along, because we've already scheduled from the idle thread into the init thread. Reported-by: Steven Rostedt <rostedt@goodmis.org> Cc: David Rientjes <rientjes@google.com> Cc: stable@vger.kernel.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'init/main.c')
-rw-r--r--init/main.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/init/main.c b/init/main.c
index 44b2433334c7..cb54cd3dbf05 100644
--- a/init/main.c
+++ b/init/main.c
@@ -560,9 +560,6 @@ asmlinkage void __init start_kernel(void)
560 early_boot_irqs_disabled = false; 560 early_boot_irqs_disabled = false;
561 local_irq_enable(); 561 local_irq_enable();
562 562
563 /* Interrupts are enabled now so all GFP allocations are safe. */
564 gfp_allowed_mask = __GFP_BITS_MASK;
565
566 kmem_cache_init_late(); 563 kmem_cache_init_late();
567 564
568 /* 565 /*
@@ -842,6 +839,10 @@ static int __init kernel_init(void * unused)
842 * Wait until kthreadd is all set-up. 839 * Wait until kthreadd is all set-up.
843 */ 840 */
844 wait_for_completion(&kthreadd_done); 841 wait_for_completion(&kthreadd_done);
842
843 /* Now the scheduler is fully set up and can do blocking allocations */
844 gfp_allowed_mask = __GFP_BITS_MASK;
845
845 /* 846 /*
846 * init can allocate pages on any node 847 * init can allocate pages on any node
847 */ 848 */