diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-07-25 04:47:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:38 -0400 |
commit | e4901f92a8dbe843e76651a50f7a2a6dd3d53474 (patch) | |
tree | 4cfd5edd17fcf1fe5e4372611c561928a99107d0 /fs | |
parent | 2b201a9eddf509e8e935b45e573648e36f4b623f (diff) |
coredump: zap_threads: comments && use while_each_thread()
No changes in fs/exec.o
The for_each_process() loop in zap_threads() is very subtle, it is not
clear why we don't race with fork/exit/exec. Add the fat comment.
Also, change the code to use while_each_thread().
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Acked-by: 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')
-rw-r--r-- | fs/exec.c | 39 |
1 files changed, 32 insertions, 7 deletions
@@ -1517,7 +1517,7 @@ static void zap_process(struct task_struct *start) | |||
1517 | sigaddset(&t->pending.signal, SIGKILL); | 1517 | sigaddset(&t->pending.signal, SIGKILL); |
1518 | signal_wake_up(t, 1); | 1518 | signal_wake_up(t, 1); |
1519 | } | 1519 | } |
1520 | } while ((t = next_thread(t)) != start); | 1520 | } while_each_thread(start, t); |
1521 | } | 1521 | } |
1522 | 1522 | ||
1523 | static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, | 1523 | static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, |
@@ -1539,7 +1539,36 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, | |||
1539 | 1539 | ||
1540 | if (atomic_read(&mm->mm_users) == mm->core_waiters + 1) | 1540 | if (atomic_read(&mm->mm_users) == mm->core_waiters + 1) |
1541 | goto done; | 1541 | goto done; |
1542 | 1542 | /* | |
1543 | * We should find and kill all tasks which use this mm, and we should | ||
1544 | * count them correctly into mm->core_waiters. We don't take tasklist | ||
1545 | * lock, but this is safe wrt: | ||
1546 | * | ||
1547 | * fork: | ||
1548 | * None of sub-threads can fork after zap_process(leader). All | ||
1549 | * processes which were created before this point should be | ||
1550 | * visible to zap_threads() because copy_process() adds the new | ||
1551 | * process to the tail of init_task.tasks list, and lock/unlock | ||
1552 | * of ->siglock provides a memory barrier. | ||
1553 | * | ||
1554 | * do_exit: | ||
1555 | * The caller holds mm->mmap_sem. This means that the task which | ||
1556 | * uses this mm can't pass exit_mm(), so it can't exit or clear | ||
1557 | * its ->mm. | ||
1558 | * | ||
1559 | * de_thread: | ||
1560 | * It does list_replace_rcu(&leader->tasks, ¤t->tasks), | ||
1561 | * we must see either old or new leader, this does not matter. | ||
1562 | * However, it can change p->sighand, so lock_task_sighand(p) | ||
1563 | * must be used. Since p->mm != NULL and we hold ->mmap_sem | ||
1564 | * it can't fail. | ||
1565 | * | ||
1566 | * Note also that "g" can be the old leader with ->mm == NULL | ||
1567 | * and already unhashed and thus removed from ->thread_group. | ||
1568 | * This is OK, __unhash_process()->list_del_rcu() does not | ||
1569 | * clear the ->next pointer, we will find the new leader via | ||
1570 | * next_thread(). | ||
1571 | */ | ||
1543 | rcu_read_lock(); | 1572 | rcu_read_lock(); |
1544 | for_each_process(g) { | 1573 | for_each_process(g) { |
1545 | if (g == tsk->group_leader) | 1574 | if (g == tsk->group_leader) |
@@ -1549,17 +1578,13 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, | |||
1549 | do { | 1578 | do { |
1550 | if (p->mm) { | 1579 | if (p->mm) { |
1551 | if (p->mm == mm) { | 1580 | if (p->mm == mm) { |
1552 | /* | ||
1553 | * p->sighand can't disappear, but | ||
1554 | * may be changed by de_thread() | ||
1555 | */ | ||
1556 | lock_task_sighand(p, &flags); | 1581 | lock_task_sighand(p, &flags); |
1557 | zap_process(p); | 1582 | zap_process(p); |
1558 | unlock_task_sighand(p, &flags); | 1583 | unlock_task_sighand(p, &flags); |
1559 | } | 1584 | } |
1560 | break; | 1585 | break; |
1561 | } | 1586 | } |
1562 | } while ((p = next_thread(p)) != g); | 1587 | } while_each_thread(g, p); |
1563 | } | 1588 | } |
1564 | rcu_read_unlock(); | 1589 | rcu_read_unlock(); |
1565 | done: | 1590 | done: |