Commit 093a8e8a authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Linus Torvalds

[PATCH] taskstats_tgid_free: fix usage

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: default avatarOleg 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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 05d5bcd6
...@@ -49,17 +49,8 @@ static inline void taskstats_tgid_alloc(struct signal_struct *sig) ...@@ -49,17 +49,8 @@ static inline void taskstats_tgid_alloc(struct signal_struct *sig)
static inline void taskstats_tgid_free(struct signal_struct *sig) static inline void taskstats_tgid_free(struct signal_struct *sig)
{ {
struct taskstats *stats = NULL; if (sig->stats)
unsigned long flags; kmem_cache_free(taskstats_cache, sig->stats);
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);
} }
extern void taskstats_exit_alloc(struct taskstats **, unsigned int *); extern void taskstats_exit_alloc(struct taskstats **, unsigned int *);
......
...@@ -128,6 +128,7 @@ static void __exit_signal(struct task_struct *tsk) ...@@ -128,6 +128,7 @@ static void __exit_signal(struct task_struct *tsk)
flush_sigqueue(&tsk->pending); flush_sigqueue(&tsk->pending);
if (sig) { if (sig) {
flush_sigqueue(&sig->shared_pending); flush_sigqueue(&sig->shared_pending);
taskstats_tgid_free(sig);
__cleanup_signal(sig); __cleanup_signal(sig);
} }
} }
......
...@@ -897,7 +897,6 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts ...@@ -897,7 +897,6 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts
void __cleanup_signal(struct signal_struct *sig) void __cleanup_signal(struct signal_struct *sig)
{ {
exit_thread_group_keys(sig); exit_thread_group_keys(sig);
taskstats_tgid_free(sig);
kmem_cache_free(signal_cachep, sig); kmem_cache_free(signal_cachep, sig);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment