diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/exit.c | 8 | ||||
-rw-r--r-- | kernel/taskstats.c | 41 |
2 files changed, 17 insertions, 32 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index 06de6c4e8ca3..4e3f919edc48 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -850,9 +850,7 @@ static void exit_notify(struct task_struct *tsk) | |||
850 | fastcall NORET_TYPE void do_exit(long code) | 850 | fastcall NORET_TYPE void do_exit(long code) |
851 | { | 851 | { |
852 | struct task_struct *tsk = current; | 852 | struct task_struct *tsk = current; |
853 | struct taskstats *tidstats; | ||
854 | int group_dead; | 853 | int group_dead; |
855 | unsigned int mycpu; | ||
856 | 854 | ||
857 | profile_task_exit(tsk); | 855 | profile_task_exit(tsk); |
858 | 856 | ||
@@ -890,8 +888,6 @@ fastcall NORET_TYPE void do_exit(long code) | |||
890 | current->comm, current->pid, | 888 | current->comm, current->pid, |
891 | preempt_count()); | 889 | preempt_count()); |
892 | 890 | ||
893 | taskstats_exit_alloc(&tidstats, &mycpu); | ||
894 | |||
895 | acct_update_integrals(tsk); | 891 | acct_update_integrals(tsk); |
896 | if (tsk->mm) { | 892 | if (tsk->mm) { |
897 | update_hiwater_rss(tsk->mm); | 893 | update_hiwater_rss(tsk->mm); |
@@ -911,8 +907,8 @@ fastcall NORET_TYPE void do_exit(long code) | |||
911 | #endif | 907 | #endif |
912 | if (unlikely(tsk->audit_context)) | 908 | if (unlikely(tsk->audit_context)) |
913 | audit_free(tsk); | 909 | audit_free(tsk); |
914 | taskstats_exit_send(tsk, tidstats, group_dead, mycpu); | 910 | |
915 | taskstats_exit_free(tidstats); | 911 | taskstats_exit(tsk, group_dead); |
916 | 912 | ||
917 | exit_mm(tsk); | 913 | exit_mm(tsk); |
918 | 914 | ||
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index d9d7c3576238..2654886fe058 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
@@ -119,10 +119,10 @@ static int send_reply(struct sk_buff *skb, pid_t pid) | |||
119 | /* | 119 | /* |
120 | * Send taskstats data in @skb to listeners registered for @cpu's exit data | 120 | * Send taskstats data in @skb to listeners registered for @cpu's exit data |
121 | */ | 121 | */ |
122 | static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) | 122 | static void send_cpu_listeners(struct sk_buff *skb, |
123 | struct listener_list *listeners) | ||
123 | { | 124 | { |
124 | struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); | 125 | struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); |
125 | struct listener_list *listeners; | ||
126 | struct listener *s, *tmp; | 126 | struct listener *s, *tmp; |
127 | struct sk_buff *skb_next, *skb_cur = skb; | 127 | struct sk_buff *skb_next, *skb_cur = skb; |
128 | void *reply = genlmsg_data(genlhdr); | 128 | void *reply = genlmsg_data(genlhdr); |
@@ -135,7 +135,6 @@ static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) | |||
135 | } | 135 | } |
136 | 136 | ||
137 | rc = 0; | 137 | rc = 0; |
138 | listeners = &per_cpu(listener_array, cpu); | ||
139 | down_read(&listeners->sem); | 138 | down_read(&listeners->sem); |
140 | list_for_each_entry(s, &listeners->list, list) { | 139 | list_for_each_entry(s, &listeners->list, list) { |
141 | skb_next = NULL; | 140 | skb_next = NULL; |
@@ -413,28 +412,12 @@ err: | |||
413 | return rc; | 412 | return rc; |
414 | } | 413 | } |
415 | 414 | ||
416 | void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu) | ||
417 | { | ||
418 | struct listener_list *listeners; | ||
419 | /* | ||
420 | * This is the cpu on which the task is exiting currently and will | ||
421 | * be the one for which the exit event is sent, even if the cpu | ||
422 | * on which this function is running changes later. | ||
423 | */ | ||
424 | *mycpu = raw_smp_processor_id(); | ||
425 | |||
426 | listeners = &per_cpu(listener_array, *mycpu); | ||
427 | |||
428 | *ptidstats = NULL; | ||
429 | if (!list_empty(&listeners->list)) | ||
430 | *ptidstats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL); | ||
431 | } | ||
432 | |||
433 | /* Send pid data out on exit */ | 415 | /* Send pid data out on exit */ |
434 | void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, | 416 | void taskstats_exit(struct task_struct *tsk, int group_dead) |
435 | int group_dead, unsigned int mycpu) | ||
436 | { | 417 | { |
437 | int rc; | 418 | int rc; |
419 | struct listener_list *listeners; | ||
420 | struct taskstats *tidstats; | ||
438 | struct sk_buff *rep_skb; | 421 | struct sk_buff *rep_skb; |
439 | void *reply; | 422 | void *reply; |
440 | size_t size; | 423 | size_t size; |
@@ -458,12 +441,17 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, | |||
458 | fill_tgid_exit(tsk); | 441 | fill_tgid_exit(tsk); |
459 | } | 442 | } |
460 | 443 | ||
444 | listeners = &__raw_get_cpu_var(listener_array); | ||
445 | if (list_empty(&listeners->list)) | ||
446 | return; | ||
447 | |||
448 | tidstats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL); | ||
461 | if (!tidstats) | 449 | if (!tidstats) |
462 | return; | 450 | return; |
463 | 451 | ||
464 | rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); | 452 | rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); |
465 | if (rc < 0) | 453 | if (rc < 0) |
466 | goto ret; | 454 | goto free_stats; |
467 | 455 | ||
468 | rc = fill_pid(tsk->pid, tsk, tidstats); | 456 | rc = fill_pid(tsk->pid, tsk, tidstats); |
469 | if (rc < 0) | 457 | if (rc < 0) |
@@ -492,15 +480,16 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, | |||
492 | nla_nest_end(rep_skb, na); | 480 | nla_nest_end(rep_skb, na); |
493 | 481 | ||
494 | send: | 482 | send: |
495 | send_cpu_listeners(rep_skb, mycpu); | 483 | send_cpu_listeners(rep_skb, listeners); |
484 | free_stats: | ||
485 | kmem_cache_free(taskstats_cache, tidstats); | ||
496 | return; | 486 | return; |
497 | 487 | ||
498 | nla_put_failure: | 488 | nla_put_failure: |
499 | genlmsg_cancel(rep_skb, reply); | 489 | genlmsg_cancel(rep_skb, reply); |
500 | err_skb: | 490 | err_skb: |
501 | nlmsg_free(rep_skb); | 491 | nlmsg_free(rep_skb); |
502 | ret: | 492 | goto free_stats; |
503 | return; | ||
504 | } | 493 | } |
505 | 494 | ||
506 | static struct genl_ops taskstats_ops = { | 495 | static struct genl_ops taskstats_ops = { |