diff options
| author | Christian Brauner <brauner@kernel.org> | 2026-09-10 17:48:10 +0200 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-09-14 15:58:07 +0200 |
| commit | b9ae29c235dc7ccfcd17bcbf025608514d51ef57 (patch) | |
| tree | 7e7885bbfd99534b4e1d92bb3a228e66439d8167 | |
| parent | 605270eed1871ddc863641747ed2c4c0d00d15d6 (diff) | |
| download | linux-next-b9ae29c235dc7ccfcd17bcbf025608514d51ef57.tar.gz linux-next-b9ae29c235dc7ccfcd17bcbf025608514d51ef57.zip | |
coredump: replace the startup completion with a thread count
coredump_wait() sets core_state->nr_threads to the number of tasks
killed and waits for the last thread to enter coredump_task_exit() to
signal completion. Let's just wait on the count directly. The exiting
tasks can use atomic_dec_and_wake_up() and the dumping task sleeps in
wait_var_event_state().
The dumping task must remain freezable since commit f5d39b020809
("freezer,sched: Rewrite core freezer logic"). So keep the wait
TASK_UNINTERRUPTIBLE|TASK_FREEZABLE.
Drop the completion and rename nr_threads to threads_remaining.
No functional changes.
Suggested-by: NeilBrown <neilb@ownmail.net>
Link: https://lore.kernel.org/178899497961.207413.10554121774377911612@noble.neil.brown.name
Link: https://patch.msgid.link/20260910-work-coredump-unlock-self-v4-12-a5c1800dc930@kernel.org
Reviewed-by: NeilBrown <neil@brown.name>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
| -rw-r--r-- | fs/coredump.c | 9 | ||||
| -rw-r--r-- | include/linux/sched/signal.h | 4 | ||||
| -rw-r--r-- | kernel/exit.c | 6 |
3 files changed, 10 insertions, 9 deletions
diff --git a/fs/coredump.c b/fs/coredump.c index b75b79c8245b..5c293e890ae6 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -39,6 +39,7 @@ #include <linux/oom.h> #include <linux/compat.h> #include <linux/fs.h> +#include <linux/wait_bit.h> #include <linux/path.h> #include <linux/timekeeping.h> #include <linux/sysctl.h> @@ -512,7 +513,7 @@ static int zap_threads(struct task_struct *tsk, nr = zap_process(signal, exit_code); clear_tsk_thread_flag(tsk, TIF_SIGPENDING); tsk->flags |= PF_DUMPCORE; - atomic_set(&core_state->nr_threads, nr); + atomic_set(&core_state->threads_remaining, nr); } spin_unlock_irq(&tsk->sighand->siglock); return nr; @@ -523,15 +524,15 @@ static int coredump_wait(int exit_code, struct core_state *core_state) struct task_struct *tsk = current; int core_waiters = -EBUSY; - init_completion(&core_state->startup); core_state->tasks = NULL; core_waiters = zap_threads(tsk, core_state, exit_code); if (core_waiters > 0) { struct core_thread *ptr; - wait_for_completion_state(&core_state->startup, - TASK_UNINTERRUPTIBLE|TASK_FREEZABLE); + wait_var_event_state(&core_state->threads_remaining, + !atomic_read_acquire(&core_state->threads_remaining), + TASK_UNINTERRUPTIBLE|TASK_FREEZABLE); /* * Wait for all the threads to become inactive, so that * all the thread context (extended register state, like diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 14b55d00d605..e039e29cd8c5 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -79,9 +79,9 @@ struct core_thread { }; struct core_state { - atomic_t nr_threads; + /* Threads the dumper still waits for. */ + atomic_t threads_remaining; struct core_thread *tasks; - struct completion startup; }; /* diff --git a/kernel/exit.c b/kernel/exit.c index 3df1fffc6674..55dbea3b242e 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/capability.h> #include <linux/completion.h> +#include <linux/wait_bit.h> #include <linux/personality.h> #include <linux/tty.h> #include <linux/iocontext.h> @@ -442,8 +443,7 @@ static void coredump_task_exit(struct task_struct *tsk, * Implies mb(), the result of xchg() must be visible * to the dumper. */ - if (atomic_dec_and_test(&core_state->nr_threads)) - complete(&core_state->startup); + atomic_dec_and_wake_up(&core_state->threads_remaining); for (;;) { set_current_state(TASK_IDLE|TASK_FREEZABLE); @@ -917,7 +917,7 @@ static void synchronize_group_exit(struct task_struct *tsk, long code) * Serialize with any possible pending coredump. * We must hold siglock around checking core_state * and setting PF_POSTCOREDUMP. The core-inducing thread - * will increment ->nr_threads for each thread in the + * will increment ->threads_remaining for each thread in the * group without PF_POSTCOREDUMP set. */ tsk->flags |= PF_POSTCOREDUMP; |
