diff options
Diffstat (limited to 'kernel/taskstats.c')
| -rw-r--r-- | kernel/taskstats.c | 15 | 
1 files changed, 12 insertions, 3 deletions
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 9ffea360a77..fc0f2200541 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c @@ -285,16 +285,18 @@ ret:  static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)  {  	struct listener_list *listeners; -	struct listener *s, *tmp; +	struct listener *s, *tmp, *s2;  	unsigned int cpu;  	if (!cpumask_subset(mask, cpu_possible_mask))  		return -EINVAL; +	s = NULL;  	if (isadd == REGISTER) {  		for_each_cpu(cpu, mask) { -			s = kmalloc_node(sizeof(struct listener), GFP_KERNEL, -					 cpu_to_node(cpu)); +			if (!s) +				s = kmalloc_node(sizeof(struct listener), +						 GFP_KERNEL, cpu_to_node(cpu));  			if (!s)  				goto cleanup;  			s->pid = pid; @@ -303,9 +305,16 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)  			listeners = &per_cpu(listener_array, cpu);  			down_write(&listeners->sem); +			list_for_each_entry_safe(s2, tmp, &listeners->list, list) { +				if (s2->pid == pid) +					goto next_cpu; +			}  			list_add(&s->list, &listeners->list); +			s = NULL; +next_cpu:  			up_write(&listeners->sem);  		} +		kfree(s);  		return 0;  	}  |