Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b2c903b8790467ae400f6992ac01bc8913b49e19
Commit:     b2c903b8790467ae400f6992ac01bc8913b49e19
Parent:     0840a90d943bcde2fbfeabd3c256236eed2273cd
Author:     Oleg Nesterov <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 16 23:27:22 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Wed Oct 17 08:42:53 2007 -0700

    exec: simplify the new ->sighand allocation
    
    de_thread() pre-allocates newsighand to make sure that exec() can't fail 
after
    killing all sub-threads. Imho, this buys nothing, but complicates the code:
    
        - this is (mostly) needed to handle CLONE_SIGHAND without CLONE_THREAD
          tasks, this is very unlikely (if ever used) case
    
        - unless we already have some serious problems, GFP_KERNEL allocation
          should not fail
    
        - ENOMEM still can happen after de_thread(), ->sighand is not the last
          object we have to allocate
    
    Change the code to allocate the new ->sighand on demand.
    
    Signed-off-by: Oleg Nesterov <[EMAIL PROTECTED]>
    Cc: Roland McGrath <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/exec.c |   24 +++++++++---------------
 1 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index 7f325df..c6e91c3 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -747,7 +747,7 @@ static int exec_mmap(struct mm_struct *mm)
 static int de_thread(struct task_struct *tsk)
 {
        struct signal_struct *sig = tsk->signal;
-       struct sighand_struct *newsighand, *oldsighand = tsk->sighand;
+       struct sighand_struct *oldsighand = tsk->sighand;
        spinlock_t *lock = &oldsighand->siglock;
        struct task_struct *leader = NULL;
        int count;
@@ -761,10 +761,6 @@ static int de_thread(struct task_struct *tsk)
                return 0;
        }
 
-       newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
-       if (!newsighand)
-               return -ENOMEM;
-
        if (thread_group_empty(tsk))
                goto no_thread_group;
 
@@ -781,7 +777,6 @@ static int de_thread(struct task_struct *tsk)
                 */
                spin_unlock_irq(lock);
                read_unlock(&tasklist_lock);
-               kmem_cache_free(sighand_cachep, newsighand);
                return -EAGAIN;
        }
 
@@ -899,17 +894,16 @@ no_thread_group:
        if (leader)
                release_task(leader);
 
-       if (atomic_read(&oldsighand->count) == 1) {
-               /*
-                * Now that we nuked the rest of the thread group,
-                * it turns out we are not sharing sighand any more either.
-                * So we can just keep it.
-                */
-               kmem_cache_free(sighand_cachep, newsighand);
-       } else {
+       if (atomic_read(&oldsighand->count) != 1) {
+               struct sighand_struct *newsighand;
                /*
-                * Move our state over to newsighand and switch it in.
+                * This ->sighand is shared with the CLONE_SIGHAND
+                * but not CLONE_THREAD task, switch to the new one.
                 */
+               newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);
+               if (!newsighand)
+                       return -ENOMEM;
+
                atomic_set(&newsighand->count, 1);
                memcpy(newsighand->action, oldsighand->action,
                       sizeof(newsighand->action));
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to