diff options
author | Oleg Nesterov <oleg@redhat.com> | 2011-08-03 19:21:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-03 20:25:20 -0400 |
commit | dfc428b656c4693a2334a8d9865b430beddb562a (patch) | |
tree | ad8aa91d2e3c5e9cedc5f4efb2e04a86b4a0784e /kernel | |
parent | 12b3e038e5bb4860c17d001e92a6fa9964c0a7b9 (diff) |
taskstats: add_del_listener() shouldn't use the wrong node
1. Commit 26c4caea9d69 "don't allow duplicate entries in listener mode"
changed add_del_listener(REGISTER) so that "next_cpu:" can reuse the
listener allocated for the previous cpu, this doesn't look exactly
right even if minor.
Change the code to kfree() in the already-registered case, this case
is unlikely anyway so the extra kmalloc_node() shouldn't hurt but
looke more correct and clean.
2. use the plain list_for_each_entry() instead of _safe() to scan
listeners->list.
3. Remove the unneeded INIT_LIST_HEAD(&s->list), we are going to
list_add(&s->list).
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Vasiliy Kulikov <segoon@openwall.com>
Cc: Balbir Singh <bsingharora@gmail.com>
Reviewed-by: Jerome Marchand <jmarchan@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/taskstats.c | 16 |
1 files changed, 7 insertions, 9 deletions
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index d1db2880d1cf..a09a54936f19 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
@@ -291,30 +291,28 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd) | |||
291 | if (!cpumask_subset(mask, cpu_possible_mask)) | 291 | if (!cpumask_subset(mask, cpu_possible_mask)) |
292 | return -EINVAL; | 292 | return -EINVAL; |
293 | 293 | ||
294 | s = NULL; | ||
295 | if (isadd == REGISTER) { | 294 | if (isadd == REGISTER) { |
296 | for_each_cpu(cpu, mask) { | 295 | for_each_cpu(cpu, mask) { |
297 | if (!s) | 296 | s = kmalloc_node(sizeof(struct listener), |
298 | s = kmalloc_node(sizeof(struct listener), | 297 | GFP_KERNEL, cpu_to_node(cpu)); |
299 | GFP_KERNEL, cpu_to_node(cpu)); | ||
300 | if (!s) | 298 | if (!s) |
301 | goto cleanup; | 299 | goto cleanup; |
300 | |||
302 | s->pid = pid; | 301 | s->pid = pid; |
303 | INIT_LIST_HEAD(&s->list); | ||
304 | s->valid = 1; | 302 | s->valid = 1; |
305 | 303 | ||
306 | listeners = &per_cpu(listener_array, cpu); | 304 | listeners = &per_cpu(listener_array, cpu); |
307 | down_write(&listeners->sem); | 305 | down_write(&listeners->sem); |
308 | list_for_each_entry_safe(s2, tmp, &listeners->list, list) { | 306 | list_for_each_entry(s2, &listeners->list, list) { |
309 | if (s2->pid == pid) | 307 | if (s2->pid == pid) |
310 | goto next_cpu; | 308 | goto exists; |
311 | } | 309 | } |
312 | list_add(&s->list, &listeners->list); | 310 | list_add(&s->list, &listeners->list); |
313 | s = NULL; | 311 | s = NULL; |
314 | next_cpu: | 312 | exists: |
315 | up_write(&listeners->sem); | 313 | up_write(&listeners->sem); |
314 | kfree(s); /* nop if NULL */ | ||
316 | } | 315 | } |
317 | kfree(s); | ||
318 | return 0; | 316 | return 0; |
319 | } | 317 | } |
320 | 318 | ||