From 29d66b3902962d0a89408abaf6d24a3df5eef518 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 24 Jul 2024 16:51:52 -0700 Subject: [PATCH] UPSTREAM: exit: Sleep at TASK_IDLE when waiting for application core dump Currently, the coredump_task_exit() function sets the task state to TASK_UNINTERRUPTIBLE|TASK_FREEZABLE, which usually works well. But a combination of large memory and slow (and/or highly contended) mass storage can cause application core dumps to take more than two minutes, which can cause check_hung_task(), which is invoked by check_hung_uninterruptible_tasks(), to produce task-blocked splats. There does not seem to be any reasonable benefit to getting these splats. Furthermore, as Oleg Nesterov points out, TASK_UNINTERRUPTIBLE could be misleading because the task sleeping in coredump_task_exit() really is killable, albeit indirectly. See the check of signal->core_state in prepare_signal() and the check of fatal_signal_pending() in dump_interrupted(), which bypass the normal unkillability of TASK_UNINTERRUPTIBLE, resulting in coredump_finish() invoking wake_up_process() on any threads sleeping in coredump_task_exit(). Therefore, change that TASK_UNINTERRUPTIBLE to TASK_IDLE. Bug: 375106936 (cherry picked from commit b8e753128ed074fcb48e9ceded940752f6b1c19f https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/ master) Reported-by: Anhad Jai Singh Signed-off-by: Paul E. McKenney Acked-by: Oleg Nesterov Cc: Jens Axboe Cc: Christian Brauner Cc: Andrew Morton Cc: "Matthew Wilcox (Oracle)" Cc: Chris Mason Cc: Rik van Riel Change-Id: I2c05f6dd74add156d1541d50d6e3147106c80036 Signed-off-by: Seiya Wang --- kernel/exit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/exit.c b/kernel/exit.c index 151aeaaf2a27..7dded98548e8 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -428,7 +428,7 @@ static void coredump_task_exit(struct task_struct *tsk) complete(&core_state->startup); for (;;) { - set_current_state(TASK_UNINTERRUPTIBLE|TASK_FREEZABLE); + set_current_state(TASK_IDLE|TASK_FREEZABLE); if (!self.task) /* see coredump_finish() */ break; schedule();