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: Oleg Nesterov

include/linux/mm_types.h | 6 ++++++
fs/exec.c | 2 ++
kernel/exit.c | 15 ++++++++++++---
3 files changed, 20 insertions(+), 3 deletions(-)

--- 26-rc2/include/linux/mm_types.h~2_CORE_THREAD 2008-06-16 18:00:08.000000000 +0400
+++ 26-rc2/include/linux/mm_types.h 2008-07-13 18:28:36.000000000 +0400
@@ -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;
};

--- 26-rc2/fs/exec.c~2_CORE_THREAD 2008-07-13 17:47:28.000000000 +0400
+++ 26-rc2/fs/exec.c 2008-07-13 18:43:39.000000000 +0400
@@ -1599,6 +1599,8 @@ static int coredump_wait(int exit_code,

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);

--- 26-rc2/kernel/exit.c~2_CORE_THREAD 2008-07-06 18:10:12.000000000 +0400
+++ 26-rc2/kernel/exit.c 2008-07-13 19:58:19.000000000 +0400
@@ -653,6 +653,7 @@ assign_new_owner:
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)
@@ -665,11 +666,19 @@ static void exit_mm(struct task_struct *
* 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);

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/