diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-07-25 04:47:46 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:40 -0400 |
commit | a94e2d408eaedbd85aae259621d46fafc10479a2 (patch) | |
tree | d853f7b2e183875c6ad90fb6ab38e084b037d043 /fs/exec.c | |
parent | 182c515fd2a942623aed4e4e0e0b37fe96571b05 (diff) |
coredump: kill mm->core_done
Now that we have core_state->dumper list we can use it to wake up the
sub-threads waiting for the coredump completion.
This uglifies the code and .text grows by 47 bytes, but otoh mm_struct
lessens by sizeof(struct completion). Also, with this change we can
decouple exit_mm() from the coredumping code.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 25 |
1 files changed, 22 insertions, 3 deletions
@@ -1602,7 +1602,6 @@ static int coredump_wait(int exit_code, struct core_state *core_state) | |||
1602 | struct completion *vfork_done; | 1602 | struct completion *vfork_done; |
1603 | int core_waiters; | 1603 | int core_waiters; |
1604 | 1604 | ||
1605 | init_completion(&mm->core_done); | ||
1606 | init_completion(&core_state->startup); | 1605 | init_completion(&core_state->startup); |
1607 | core_state->dumper.task = tsk; | 1606 | core_state->dumper.task = tsk; |
1608 | core_state->dumper.next = NULL; | 1607 | core_state->dumper.next = NULL; |
@@ -1628,6 +1627,27 @@ fail: | |||
1628 | return core_waiters; | 1627 | return core_waiters; |
1629 | } | 1628 | } |
1630 | 1629 | ||
1630 | static void coredump_finish(struct mm_struct *mm) | ||
1631 | { | ||
1632 | struct core_thread *curr, *next; | ||
1633 | struct task_struct *task; | ||
1634 | |||
1635 | next = mm->core_state->dumper.next; | ||
1636 | while ((curr = next) != NULL) { | ||
1637 | next = curr->next; | ||
1638 | task = curr->task; | ||
1639 | /* | ||
1640 | * see exit_mm(), curr->task must not see | ||
1641 | * ->task == NULL before we read ->next. | ||
1642 | */ | ||
1643 | smp_mb(); | ||
1644 | curr->task = NULL; | ||
1645 | wake_up_process(task); | ||
1646 | } | ||
1647 | |||
1648 | mm->core_state = NULL; | ||
1649 | } | ||
1650 | |||
1631 | /* | 1651 | /* |
1632 | * set_dumpable converts traditional three-value dumpable to two flags and | 1652 | * set_dumpable converts traditional three-value dumpable to two flags and |
1633 | * stores them into mm->flags. It modifies lower two bits of mm->flags, but | 1653 | * stores them into mm->flags. It modifies lower two bits of mm->flags, but |
@@ -1812,8 +1832,7 @@ fail_unlock: | |||
1812 | argv_free(helper_argv); | 1832 | argv_free(helper_argv); |
1813 | 1833 | ||
1814 | current->fsuid = fsuid; | 1834 | current->fsuid = fsuid; |
1815 | complete_all(&mm->core_done); | 1835 | coredump_finish(mm); |
1816 | mm->core_state = NULL; | ||
1817 | fail: | 1836 | fail: |
1818 | return retval; | 1837 | return retval; |
1819 | } | 1838 | } |