[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1541994885-20059-1-git-send-email-chanho.min@lge.com>
Date: Mon, 12 Nov 2018 12:54:45 +0900
From: Chanho Min <chanho.min@....com>
To: "Rafael J. Wysocki" <rjw@...ysocki.net>,
Pavel Machek <pavel@....cz>, Len Brown <len.brown@...el.com>,
Andrew Morton <akpm@...ux-foundation.org>,
"Eric W. Biederman" <ebiederm@...ssion.com>,
Christian Brauner <christian@...uner.io>,
Oleg Nesterov <oleg@...hat.com>,
Anna-Maria Gleixner <anna-maria@...utronix.de>,
Alexander Viro <viro@...iv.linux.org.uk>
Cc: linux-pm@...r.kernel.org, linux-kernel@...r.kernel.org,
linux-fsdevel@...r.kernel.org,
Seungho Park <seungho1.park@....com>,
Inkyu Hwang <inkyu.hwang@....com>,
Donghwan Jung <donghwan.jung@....com>,
Jongsung Kim <neidhard.kim@....com>,
Chanho Min <chanho.min@....com>
Subject: [PATCH v2] exec: make de_thread() freezable
Suspend fails due to the exec family of functions blocking the freezer.
The casue is that de_thread() sleeps in TASK_UNINTERRUPTIBLE waiting for
all sub-threads to die, and we have the deadlock if one of them is frozen.
This also can occur with the schedule() waiting for the group thread leader
to exit if it is frozen.
In our machine, it causes freeze timeout as bellows.
Freezing of tasks failed after 20.010 seconds (1 tasks refusing to freeze, wq_busy=0):
setcpushares-ls D ffffffc00008ed70 0 5817 1483 0x0040000d
Call trace:
[<ffffffc00008ed70>] __switch_to+0x88/0xa0
[<ffffffc000d1c30c>] __schedule+0x1bc/0x720
[<ffffffc000d1ca90>] schedule+0x40/0xa8
[<ffffffc0001cd784>] flush_old_exec+0xdc/0x640
[<ffffffc000220360>] load_elf_binary+0x2a8/0x1090
[<ffffffc0001ccff4>] search_binary_handler+0x9c/0x240
[<ffffffc00021c584>] load_script+0x20c/0x228
[<ffffffc0001ccff4>] search_binary_handler+0x9c/0x240
[<ffffffc0001ce8e0>] do_execveat_common.isra.14+0x4f8/0x6e8
[<ffffffc0001cedd0>] compat_SyS_execve+0x38/0x48
[<ffffffc00008de30>] el0_svc_naked+0x24/0x28
To fix this, make de_thread() freezable. It looks safe and works fine.
Changes in v2:
- changes for the same reason in "if (!thread_group_leader(tsk))" branch.
(reported by Oleg)
Suggested-by: Oleg Nesterov <oleg@...hat.com>
Signed-off-by: Chanho Min <chanho.min@....com>
---
fs/exec.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/exec.c b/fs/exec.c
index 1ebf6e5..6da8745 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -62,6 +62,7 @@
#include <linux/oom.h>
#include <linux/compat.h>
#include <linux/vmalloc.h>
+#include <linux/freezer.h>
#include <linux/uaccess.h>
#include <asm/mmu_context.h>
@@ -1083,7 +1084,7 @@ static int de_thread(struct task_struct *tsk)
while (sig->notify_count) {
__set_current_state(TASK_KILLABLE);
spin_unlock_irq(lock);
- schedule();
+ freezable_schedule();
if (unlikely(__fatal_signal_pending(tsk)))
goto killed;
spin_lock_irq(lock);
@@ -1111,7 +1112,7 @@ static int de_thread(struct task_struct *tsk)
__set_current_state(TASK_KILLABLE);
write_unlock_irq(&tasklist_lock);
cgroup_threadgroup_change_end(tsk);
- schedule();
+ freezable_schedule();
if (unlikely(__fatal_signal_pending(tsk)))
goto killed;
}
--
2.1.4
Powered by blists - more mailing lists