Pavel V. Panteleev reported that a WARN_ON_ONCE(p->migrate_disable <= 0) triggered in 3.14.79-rt85 during boot from radix_tree_insert(). The problem is that radix_tree_insert() allocates memory and SLUB does not enable interrupts in allocate_slab(). They can't be be enabled unconditionally because early in the boot process they have to remain off. Enabling them at the "SYSTEM_RUNNING" state is too late. The earliest point is once we have scheduling working that is once the kthread is running. In newer -RT (v4.11+) there is the check if (system_state > SYSTEM_BOOTING) to enable interrupts in the allocator which is what this patch intends: Once scheduling is working enable interrupts in the allocator path so we can take sleeping locks. Reported-by: "Pavel V. Panteleev" <panteleev_p@xxxxxxx> Tested-by: "Pavel V. Panteleev" <panteleev_p@xxxxxxx> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx> --- init/main.c | 2 ++ mm/slub.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/init/main.c b/init/main.c index 6470deef01c9..362761effeac 100644 --- a/init/main.c +++ b/init/main.c @@ -379,6 +379,7 @@ static void __init setup_command_line(char *command_line) */ static __initdata DECLARE_COMPLETION(kthreadd_done); +extern bool slab_do_irq_on; static noinline void __ref rest_init(void) { @@ -396,6 +397,7 @@ static noinline void __ref rest_init(void) rcu_read_lock(); kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); rcu_read_unlock(); + slab_do_irq_on = true; complete(&kthreadd_done); /* diff --git a/mm/slub.c b/mm/slub.c index 67eb368b9314..22ec805130e5 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -1527,6 +1527,7 @@ static inline bool shuffle_freelist(struct kmem_cache *s, struct page *page) return false; } #endif /* CONFIG_SLAB_FREELIST_RANDOM */ +bool slab_do_irq_on; static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) { @@ -1543,7 +1544,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) if (gfpflags_allow_blocking(flags)) enableirqs = true; #ifdef CONFIG_PREEMPT_RT_FULL - if (system_state == SYSTEM_RUNNING) + if (slab_do_irq_on) enableirqs = true; #endif if (enableirqs) -- 2.15.0 -- To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html