| From e94445b78dc821e0e9de5a9bf5bd263f5ae2c471 Mon Sep 17 00:00:00 2001 |
| From: Mike Galbraith <mgalbraith@suse.de> |
| Date: Wed, 8 Dec 2010 08:11:50 +0100 |
| Subject: [PATCH] rt: mm: fix kthreadd livelock in drain_local_pages_work |
| |
| commit e94445b78dc821e0e9de5a9bf5bd263f5ae2c471 in tip. |
| |
| In a low memory situation, kthreadd may call schedule_on_each_cpu() while |
| trying to spawn a worker, and the system grinds to a halt as below. |
| |
| [25689.675353] SysRq : Show Blocked State |
| [25689.682919] task PC stack pid father |
| [25689.694781] kthreadd D 00000000ffffffff 0 2 0 0x00000000 |
| [25689.708613] ffff88013fb37810 0000000000000046 0000000000000000 000000000000b3f0 |
| [25689.708616] ffff88013fa93040 ffff88013fa93308 000000023fa93408 0000000000000000 |
| [25689.708619] 0000000000000000 ffff88013faadfd8 ffff88013faadb50 0000000000000004 |
| [25689.709058] Call Trace: |
| [25689.709064] [<ffffffff8236b45c>] ? schedule+0x1c/0x30 |
| [25689.709066] [<ffffffff8236b99d>] ? schedule_timeout+0x26d/0x2b0 |
| [25689.709069] [<ffffffff8203932e>] ? enqueue_task_rt+0x12e/0x290 |
| [25689.709074] [<ffffffff8236a804>] ? wait_for_common+0xc4/0x1a0 |
| [25689.709077] [<ffffffff82040700>] ? default_wake_function+0x0/0x10 |
| [25689.709080] [<ffffffff820b3d90>] ? drain_local_pages_work+0x0/0x10 |
| [25689.709084] [<ffffffff82059c1c>] ? flush_work+0x6c/0xc0 |
| [25689.709086] [<ffffffff82059e40>] ? wq_barrier_func+0x0/0x10 |
| [25689.709088] [<ffffffff82059ccf>] ? __queue_work+0x5f/0x70 |
| [25689.709090] [<ffffffff8205a233>] ? schedule_on_each_cpu+0x113/0x160 |
| [25689.709093] [<ffffffff820b6e5d>] ? __alloc_pages_nodemask+0x61d/0x760 |
| [25689.709095] [<ffffffff820b59f9>] ? __get_free_pages+0x9/0x50 |
| [25689.709098] [<ffffffff820434ea>] ? copy_process+0xea/0x13f0 |
| [25689.709101] [<ffffffff82033da0>] ? enqueue_task+0x60/0x70 |
| [25689.709103] [<ffffffff82033eb4>] ? activate_task+0x24/0x30 |
| [25689.709105] [<ffffffff8204488b>] ? do_fork+0x9b/0x3d0 |
| [25689.709107] [<ffffffff820354ae>] ? update_curr+0xae/0x140 |
| [25689.709111] [<ffffffff8200178b>] ? __switch_to+0xeb/0x350 |
| [25689.709114] [<ffffffff8200b5bc>] ? kernel_thread+0x7c/0x90 |
| [25689.709117] [<ffffffff8205d9d0>] ? kthread+0x0/0xa0 |
| [25689.709119] [<ffffffff82003e20>] ? kernel_thread_helper+0x0/0x10 |
| [25689.709121] [<ffffffff8236b45c>] ? schedule+0x1c/0x30 |
| [25689.709123] [<ffffffff8205d98f>] ? kthreadd+0x14f/0x190 |
| [25689.709125] [<ffffffff82003e24>] ? kernel_thread_helper+0x4/0x10 |
| [25689.709127] [<ffffffff8205d840>] ? kthreadd+0x0/0x190 |
| [25689.709129] [<ffffffff82003e20>] ? kernel_thread_helper+0x0/0x10 |
| [25689.709147] events/0 D ffff88000d29d1d0 0 211 2 0x00000000 |
| [25689.709150] ffff88013f282080 0000000000000046 0000000000000400 000000000000f540 |
| [25689.709152] ffff88013f231040 ffff88013f231308 000000000000f540 000000000000f540 |
| [25689.709153] 0000000000000008 ffff88013f255fd8 ffff88013f255bf0 ffff88013f255c00 |
| [25689.709155] Call Trace: |
| [25689.709159] [<ffffffff82119190>] ? bdi_sched_wait+0x0/0x10 |
| [25689.709160] [<ffffffff8236b45c>] ? schedule+0x1c/0x30 |
| [25689.709162] [<ffffffff82119199>] ? bdi_sched_wait+0x9/0x10 |
| [25689.709164] [<ffffffff8236bbd0>] ? __wait_on_bit+0x50/0x80 |
| [25689.709166] [<ffffffff82119190>] ? bdi_sched_wait+0x0/0x10 |
| [25689.709167] [<ffffffff8236bc79>] ? out_of_line_wait_on_bit+0x79/0xa0 |
| [25689.709169] [<ffffffff8205de20>] ? wake_bit_function+0x0/0x20 |
| [25689.709171] [<ffffffff82119748>] ? bdi_start_writeback+0xc8/0xd0 |
| [25689.709174] [<ffffffff8211dbda>] ? __sync_filesystem+0x3a/0x90 |
| [25689.709177] [<ffffffff8211ddea>] ? sync_filesystem+0x2a/0x50 |
| [25689.709180] [<ffffffff820fa8d1>] ? generic_shutdown_super+0x21/0x110 |
| [25689.709182] [<ffffffff820faa19>] ? kill_anon_super+0x9/0x50 |
| [25689.709192] [<ffffffffa044cded>] ? nfs_kill_super+0x1d/0x40 [nfs] |
| [25689.709194] [<ffffffff820fb2b3>] ? deactivate_super+0x83/0xb0 |
| [25689.709197] [<ffffffff82112e0b>] ? release_mounts+0xab/0xd0 |
| [25689.709199] [<ffffffff82112ffa>] ? mark_mounts_for_expiry+0x11a/0x130 |
| [25689.709207] [<ffffffffa0456c00>] ? nfs_expire_automounts+0x0/0x40 [nfs] |
| [25689.709215] [<ffffffffa0456c10>] ? nfs_expire_automounts+0x10/0x40 [nfs] |
| [25689.709217] [<ffffffff820597dc>] ? worker_thread+0x15c/0x230 |
| [25689.709219] [<ffffffff8205ddf0>] ? autoremove_wake_function+0x0/0x30 |
| [25689.709221] [<ffffffff82059680>] ? worker_thread+0x0/0x230 |
| [25689.709223] [<ffffffff8205da66>] ? kthread+0x96/0xa0 |
| [25689.709225] [<ffffffff8203dd1a>] ? finish_task_switch+0x4a/0x100 |
| [25689.709227] [<ffffffff82003e24>] ? kernel_thread_helper+0x4/0x10 |
| [25689.709229] [<ffffffff8205d9d0>] ? kthread+0x0/0xa0 |
| [25689.709231] [<ffffffff82003e20>] ? kernel_thread_helper+0x0/0x10 |
| [25689.709234] bdi-default D 0000000000000000 0 233 2 0x00000000 |
| [25689.709236] ffffffff8260e020 0000000000000046 0000000000000000 000000000000b3f0 |
| [25689.709238] ffff88013f282080 ffff88013f282348 000000000000f540 0000000000000000 |
| [25689.709240] 0000000000000000 ffff88013f36bfd8 ffff88013f36bd38 0000000000000004 |
| [25689.709242] Call Trace: |
| [25689.709243] [<ffffffff8236b45c>] ? schedule+0x1c/0x30 |
| [25689.709245] [<ffffffff8236b99d>] ? schedule_timeout+0x26d/0x2b0 |
| [25689.709247] [<ffffffff8236a804>] ? wait_for_common+0xc4/0x1a0 |
| [25689.709250] [<ffffffff82040700>] ? default_wake_function+0x0/0x10 |
| [25689.709252] [<ffffffff8203dd1a>] ? finish_task_switch+0x4a/0x100 |
| [25689.709254] [<ffffffff8205dc28>] ? kthread_create+0x98/0x130 |
| [25689.709256] [<ffffffff820c5540>] ? bdi_start_fn+0x0/0xf0 |
| [25689.709260] [<ffffffff82051f50>] ? process_timeout+0x0/0x10 |
| [25689.709262] [<ffffffff820c53aa>] ? bdi_forker_task+0x19a/0x330 |
| [25689.709263] [<ffffffff8236ada6>] ? __schedule+0x426/0x960 |
| [25689.709265] [<ffffffff820c5210>] ? bdi_forker_task+0x0/0x330 |
| [25689.709268] [<ffffffff8205da66>] ? kthread+0x96/0xa0 |
| [25689.709270] [<ffffffff8203dd1a>] ? finish_task_switch+0x4a/0x100 |
| [25689.709272] [<ffffffff82003e24>] ? kernel_thread_helper+0x4/0x10 |
| [25689.709274] [<ffffffff8205d9d0>] ? kthread+0x0/0xa0 |
| [25689.709276] [<ffffffff82003e20>] ? kernel_thread_helper+0x0/0x10 |
| etc etc etc... |
| |
| Signed-off-by: Mike Galbraith <mgalbraith@suse.de> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Acked-by: Peter Zijlstra <peterz@infradead.org> |
| |
| diff --git a/mm/page_alloc.c b/mm/page_alloc.c |
| index bde9ea1..81f9359 100644 |
| --- a/mm/page_alloc.c |
| +++ b/mm/page_alloc.c |
| @@ -1121,6 +1121,15 @@ static void drain_local_pages_work(struct work_struct *wrk) |
| } |
| #endif |
| |
| +#ifdef CONFIG_PREEMPT_RT |
| +extern struct task_struct *kthreadd_task; |
| + |
| +static inline int is_kthreadd(struct task_struct *p) |
| +{ |
| + return p == kthreadd_task; |
| +} |
| +#endif |
| + |
| /* |
| * Spill all the per-cpu pages from all CPUs back into the buddy allocator |
| */ |
| @@ -1146,7 +1155,7 @@ void drain_all_pages(void) |
| * |
| * And yes, this is one big hack. Please fix ;-) |
| */ |
| - if (sizeof(void *)*nr_cpu_ids < PAGE_SIZE) |
| + if (!is_kthreadd(current) && sizeof(void *)*nr_cpu_ids < PAGE_SIZE) |
| schedule_on_each_cpu(drain_local_pages_work); |
| else { |
| static int once; |
| -- |
| 1.7.1.1 |
| |