aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/taskstats_kern.h17
-rw-r--r--kernel/exit.c8
-rw-r--r--kernel/taskstats.c41
3 files changed, 19 insertions, 47 deletions
diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h
index ce8a912e5426..f1261a532496 100644
--- a/include/linux/taskstats_kern.h
+++ b/include/linux/taskstats_kern.h
@@ -15,12 +15,6 @@
15extern struct kmem_cache *taskstats_cache; 15extern struct kmem_cache *taskstats_cache;
16extern struct mutex taskstats_exit_mutex; 16extern struct mutex taskstats_exit_mutex;
17 17
18static inline void taskstats_exit_free(struct taskstats *tidstats)
19{
20 if (tidstats)
21 kmem_cache_free(taskstats_cache, tidstats);
22}
23
24static inline void taskstats_tgid_init(struct signal_struct *sig) 18static inline void taskstats_tgid_init(struct signal_struct *sig)
25{ 19{
26 sig->stats = NULL; 20 sig->stats = NULL;
@@ -54,17 +48,10 @@ static inline void taskstats_tgid_free(struct signal_struct *sig)
54 kmem_cache_free(taskstats_cache, sig->stats); 48 kmem_cache_free(taskstats_cache, sig->stats);
55} 49}
56 50
57extern void taskstats_exit_alloc(struct taskstats **, unsigned int *); 51extern void taskstats_exit(struct task_struct *, int group_dead);
58extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int);
59extern void taskstats_init_early(void); 52extern void taskstats_init_early(void);
60#else 53#else
61static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu) 54static inline void taskstats_exit(struct task_struct *tsk, int group_dead)
62{}
63static inline void taskstats_exit_free(struct taskstats *ptidstats)
64{}
65static inline void taskstats_exit_send(struct task_struct *tsk,
66 struct taskstats *tidstats,
67 int group_dead, unsigned int cpu)
68{} 55{}
69static inline void taskstats_tgid_init(struct signal_struct *sig) 56static inline void taskstats_tgid_init(struct signal_struct *sig)
70{} 57{}
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)
850fastcall NORET_TYPE void do_exit(long code) 850fastcall 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 */
122static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) 122static 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
416void 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 */
434void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, 416void 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
494send: 482send:
495 send_cpu_listeners(rep_skb, mycpu); 483 send_cpu_listeners(rep_skb, listeners);
484free_stats:
485 kmem_cache_free(taskstats_cache, tidstats);
496 return; 486 return;
497 487
498nla_put_failure: 488nla_put_failure:
499 genlmsg_cancel(rep_skb, reply); 489 genlmsg_cancel(rep_skb, reply);
500err_skb: 490err_skb:
501 nlmsg_free(rep_skb); 491 nlmsg_free(rep_skb);
502ret: 492 goto free_stats;
503 return;
504} 493}
505 494
506static struct genl_ops taskstats_ops = { 495static struct genl_ops taskstats_ops = {