[PATCH] taskstats_tgid_free: fix usage
authorOleg Nesterov <oleg@tv-sign.ru>
Sat, 28 Oct 2006 17:38:51 +0000 (10:38 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 28 Oct 2006 18:30:54 +0000 (11:30 -0700)
taskstats_tgid_free() is called on copy_process's error path. This is wrong.

IF (clone_flags & CLONE_THREAD)
We should not clear ->signal->taskstats, current uses it,
it probably has a valid accumulated info.
ELSE
taskstats_tgid_init() set ->signal->taskstats = NULL,
there is nothing to free.

Move the callsite to __exit_signal(). We don't need any locking, entire
thread group is exiting, nobody should have a reference to soon to be
released ->signal.

Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Shailabh Nagar <nagar@watson.ibm.com>
Cc: Balbir Singh <balbir@in.ibm.com>
Cc: Jay Lan <jlan@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
include/linux/taskstats_kern.h
kernel/exit.c
kernel/fork.c

index 16894b7..a437ca0 100644 (file)
@@ -49,17 +49,8 @@ static inline void taskstats_tgid_alloc(struct signal_struct *sig)
 
 static inline void taskstats_tgid_free(struct signal_struct *sig)
 {
-       struct taskstats *stats = NULL;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sig->stats_lock, flags);
-       if (sig->stats) {
-               stats = sig->stats;
-               sig->stats = NULL;
-       }
-       spin_unlock_irqrestore(&sig->stats_lock, flags);
-       if (stats)
-               kmem_cache_free(taskstats_cache, stats);
+       if (sig->stats)
+               kmem_cache_free(taskstats_cache, sig->stats);
 }
 
 extern void taskstats_exit_alloc(struct taskstats **, unsigned int *);
index f250a5e..06de6c4 100644 (file)
@@ -128,6 +128,7 @@ static void __exit_signal(struct task_struct *tsk)
        flush_sigqueue(&tsk->pending);
        if (sig) {
                flush_sigqueue(&sig->shared_pending);
+               taskstats_tgid_free(sig);
                __cleanup_signal(sig);
        }
 }
index 29ebb30..2133266 100644 (file)
@@ -897,7 +897,6 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
 void __cleanup_signal(struct signal_struct *sig)
 {
        exit_thread_group_keys(sig);
-       taskstats_tgid_free(sig);
        kmem_cache_free(signal_cachep, sig);
 }