Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b564daf8 authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Linus Torvalds
Browse files

coredump: construct the list of coredumping threads at startup time



binfmt->core_dump() has to iterate over the all threads in system in order
to find the coredumping threads and construct the list using the
GFP_ATOMIC allocations.

With this patch each thread allocates the list node on exit_mm()'s stack and
adds itself to the list.

This allows us to do further changes:

	- simplify ->core_dump()

	- change exit_mm() to clear ->mm first, then wait for ->core_done.
	  this makes the coredumping process visible to oom_kill

	- kill mm->core_done

Signed-off-by: default avatarOleg Nesterov <oleg@tv-sign.ru>
Acked-by: default avatarRoland McGrath <roland@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 9d5b327b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1604,6 +1604,8 @@ static int coredump_wait(int exit_code, struct core_state *core_state)

	init_completion(&mm->core_done);
	init_completion(&core_state->startup);
	core_state->dumper.task = tsk;
	core_state->dumper.next = NULL;
	core_waiters = zap_threads(tsk, mm, core_state, exit_code);
	up_write(&mm->mmap_sem);

+6 −0
Original line number Diff line number Diff line
@@ -159,8 +159,14 @@ struct vm_area_struct {
#endif
};

struct core_thread {
	struct task_struct *task;
	struct core_thread *next;
};

struct core_state {
	atomic_t nr_threads;
	struct core_thread dumper;
	struct completion startup;
};

+12 −3
Original line number Diff line number Diff line
@@ -664,6 +664,7 @@ void mm_update_next_owner(struct mm_struct *mm)
static void exit_mm(struct task_struct * tsk)
{
	struct mm_struct *mm = tsk->mm;
	struct core_state *core_state;

	mm_release(tsk, mm);
	if (!mm)
@@ -676,11 +677,19 @@ static void exit_mm(struct task_struct * tsk)
	 * group with ->mm != NULL.
	 */
	down_read(&mm->mmap_sem);
	if (mm->core_state) {
	core_state = mm->core_state;
	if (core_state) {
		struct core_thread self;
		up_read(&mm->mmap_sem);

		if (atomic_dec_and_test(&mm->core_state->nr_threads))
			complete(&mm->core_state->startup);
		self.task = tsk;
		self.next = xchg(&core_state->dumper.next, &self);
		/*
		 * Implies mb(), the result of xchg() must be visible
		 * to core_state->dumper.
		 */
		if (atomic_dec_and_test(&core_state->nr_threads))
			complete(&core_state->startup);

		wait_for_completion(&mm->core_done);
		down_read(&mm->mmap_sem);