1c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar/*
2c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * taskstats.c - Export per-task statistics to userland
3c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar *
4c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * Copyright (C) Shailabh Nagar, IBM Corp. 2006
5c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar *           (C) Balbir Singh,   IBM Corp. 2006
6c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar *
7c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * This program is free software; you can redistribute it and/or modify
8c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * it under the terms of the GNU General Public License as published by
9c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * the Free Software Foundation; either version 2 of the License, or
10c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * (at your option) any later version.
11c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar *
12c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * This program is distributed in the hope that it will be useful,
13c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * GNU General Public License for more details.
16c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar *
17c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar */
18c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
19c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar#include <linux/kernel.h>
20c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar#include <linux/taskstats_kern.h>
21f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan#include <linux/tsacct_kern.h>
226f44993fe1d7b2b097f6ac60cd5835c6f5ca0874Shailabh Nagar#include <linux/delayacct.h>
23f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar#include <linux/cpumask.h>
24f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar#include <linux/percpu.h>
255a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
26846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh#include <linux/cgroupstats.h>
27846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh#include <linux/cgroup.h>
28846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh#include <linux/fs.h>
29846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh#include <linux/file.h>
304bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman#include <linux/pid_namespace.h>
31c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar#include <net/genetlink.h>
3260063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h>
33c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
34f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar/*
35f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar * Maximum length of a cpumask that can be specified in
36f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar * the TASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK attribute
37f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar */
38f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar#define TASKSTATS_CPUMASK_MAXLEN	(100+6*NR_CPUS)
39f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
40b81f3ea92ba1fa676775677679889dc2a7f03c8bVegard Nossumstatic DEFINE_PER_CPU(__u32, taskstats_seqnum);
41c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagarstatic int family_registered;
42e18b890bb0881bbab6f4f1a6cd20d9c60d66b003Christoph Lameterstruct kmem_cache *taskstats_cache;
43c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
44c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagarstatic struct genl_family family = {
45c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	.id		= GENL_ID_GENERATE,
46c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	.name		= TASKSTATS_GENL_NAME,
47c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	.version	= TASKSTATS_GENL_VERSION,
48c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	.maxattr	= TASKSTATS_CMD_ATTR_MAX,
49c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar};
50c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
51b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] = {
52c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	[TASKSTATS_CMD_ATTR_PID]  = { .type = NLA_U32 },
53c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	[TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 },
54f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING },
55f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },};
56f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
57b54452b07a7b1b8cc1385edba3ef2ef6d4679d5aAlexey Dobriyanstatic const struct nla_policy cgroupstats_cmd_get_policy[CGROUPSTATS_CMD_ATTR_MAX+1] = {
58846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	[CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 },
59846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh};
60846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
61f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagarstruct listener {
62f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	struct list_head list;
63f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	pid_t pid;
64bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar	char valid;
65c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar};
66c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
67f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagarstruct listener_list {
68f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	struct rw_semaphore sem;
69f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	struct list_head list;
70f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar};
71f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagarstatic DEFINE_PER_CPU(struct listener_list, listener_array);
72f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
73f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagarenum actions {
74f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	REGISTER,
75f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	DEREGISTER,
76f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	CPU_DONT_CARE
77f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar};
78c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
79c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagarstatic int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp,
8037167485302c8876cb0303af113696e88c2945aaOleg Nesterov				size_t size)
81c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar{
82c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	struct sk_buff *skb;
83c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	void *reply;
84c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
85c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	/*
86c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 * If new attributes are added, please revisit this allocation
87c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 */
883dabc7157859e706770c825aa229f8943db4e0e1Thomas Graf	skb = genlmsg_new(size, GFP_KERNEL);
89c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	if (!skb)
90c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		return -ENOMEM;
91c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
92c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	if (!info) {
93cd85fc58cd71bf6b89612efafb9a84e655ed7d66Christoph Lameter		int seq = this_cpu_inc_return(taskstats_seqnum) - 1;
94c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
9517c157c889f4b07258af6bfec9e4e9dcf3c00178Thomas Graf		reply = genlmsg_put(skb, 0, seq, &family, 0, cmd);
96c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	} else
9717c157c889f4b07258af6bfec9e4e9dcf3c00178Thomas Graf		reply = genlmsg_put_reply(skb, info, &family, 0, cmd);
98c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	if (reply == NULL) {
99c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		nlmsg_free(skb);
100c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		return -EINVAL;
101c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	}
102c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
103c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	*skbp = skb;
104c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	return 0;
105c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar}
106c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
107f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar/*
108f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar * Send taskstats data in @skb to listener with nl_pid @pid
109f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar */
110134e63756d5f3d0f7604dfcca847b09d1b14fd66Johannes Bergstatic int send_reply(struct sk_buff *skb, struct genl_info *info)
111c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar{
112b529ccf2799c14346d1518e9bdf1f88f03643e99Arnaldo Carvalho de Melo	struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
113f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	void *reply = genlmsg_data(genlhdr);
114c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	int rc;
115c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
116c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	rc = genlmsg_end(skb, reply);
117c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	if (rc < 0) {
118c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		nlmsg_free(skb);
119c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		return rc;
120c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	}
121c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
122134e63756d5f3d0f7604dfcca847b09d1b14fd66Johannes Berg	return genlmsg_reply(skb, info);
123c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar}
124c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
125f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar/*
126f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar * Send taskstats data in @skb to listeners registered for @cpu's exit data
127f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar */
128115085ea0794c0f339be8f9d25505c7f9861d824Oleg Nesterovstatic void send_cpu_listeners(struct sk_buff *skb,
129115085ea0794c0f339be8f9d25505c7f9861d824Oleg Nesterov					struct listener_list *listeners)
130f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar{
131b529ccf2799c14346d1518e9bdf1f88f03643e99Arnaldo Carvalho de Melo	struct genlmsghdr *genlhdr = nlmsg_data(nlmsg_hdr(skb));
132f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	struct listener *s, *tmp;
133f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	struct sk_buff *skb_next, *skb_cur = skb;
134f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	void *reply = genlmsg_data(genlhdr);
135d94a041519f3ab1ac023bf917619cd8c4a7d3c01Shailabh Nagar	int rc, delcount = 0;
136f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
137f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	rc = genlmsg_end(skb, reply);
138f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	if (rc < 0) {
139f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		nlmsg_free(skb);
140d94a041519f3ab1ac023bf917619cd8c4a7d3c01Shailabh Nagar		return;
141f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	}
142f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
143f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	rc = 0;
144bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar	down_read(&listeners->sem);
145d94a041519f3ab1ac023bf917619cd8c4a7d3c01Shailabh Nagar	list_for_each_entry(s, &listeners->list, list) {
146f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		skb_next = NULL;
147f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		if (!list_is_last(&s->list, &listeners->list)) {
148f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar			skb_next = skb_clone(skb_cur, GFP_KERNEL);
149d94a041519f3ab1ac023bf917619cd8c4a7d3c01Shailabh Nagar			if (!skb_next)
150f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar				break;
151f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		}
152134e63756d5f3d0f7604dfcca847b09d1b14fd66Johannes Berg		rc = genlmsg_unicast(&init_net, skb_cur, s->pid);
153d94a041519f3ab1ac023bf917619cd8c4a7d3c01Shailabh Nagar		if (rc == -ECONNREFUSED) {
154bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar			s->valid = 0;
155bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar			delcount++;
156f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		}
157f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		skb_cur = skb_next;
158f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	}
159bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar	up_read(&listeners->sem);
160f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
161d94a041519f3ab1ac023bf917619cd8c4a7d3c01Shailabh Nagar	if (skb_cur)
162d94a041519f3ab1ac023bf917619cd8c4a7d3c01Shailabh Nagar		nlmsg_free(skb_cur);
163d94a041519f3ab1ac023bf917619cd8c4a7d3c01Shailabh Nagar
164bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar	if (!delcount)
165d94a041519f3ab1ac023bf917619cd8c4a7d3c01Shailabh Nagar		return;
166bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar
167bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar	/* Delete invalidated entries */
168bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar	down_write(&listeners->sem);
169bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar	list_for_each_entry_safe(s, tmp, &listeners->list, list) {
170bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar		if (!s->valid) {
171bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar			list_del(&s->list);
172bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar			kfree(s);
173bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar		}
174bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar	}
175bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar	up_write(&listeners->sem);
176f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar}
177f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
1784bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biedermanstatic void fill_stats(struct user_namespace *user_ns,
1794bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman		       struct pid_namespace *pid_ns,
1804bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman		       struct task_struct *tsk, struct taskstats *stats)
181c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar{
18251de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	memset(stats, 0, sizeof(*stats));
183c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	/*
184c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 * Each accounting subsystem adds calls to its functions to
185c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 * fill in relevant parts of struct taskstsats as follows
186c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 *
1877d94dddd438bcba97db44f120da39bb001b5249fShailabh Nagar	 *	per-task-foo(stats, tsk);
188c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 */
189c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
1907d94dddd438bcba97db44f120da39bb001b5249fShailabh Nagar	delayacct_add_tsk(stats, tsk);
191f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan
192f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	/* fill in basic acct fields */
1936f44993fe1d7b2b097f6ac60cd5835c6f5ca0874Shailabh Nagar	stats->version = TASKSTATS_VERSION;
194b663a79c191508f27cd885224b592a878c0ba0f6Maxim Uvarov	stats->nvcsw = tsk->nvcsw;
195b663a79c191508f27cd885224b592a878c0ba0f6Maxim Uvarov	stats->nivcsw = tsk->nivcsw;
1964bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	bacct_add_tsk(user_ns, pid_ns, stats, tsk);
1976f44993fe1d7b2b097f6ac60cd5835c6f5ca0874Shailabh Nagar
1989acc1853519a0473620d424105f9d49ea5b4e62eJay Lan	/* fill in extended acct fields */
1999acc1853519a0473620d424105f9d49ea5b4e62eJay Lan	xacct_add_tsk(stats, tsk);
2003d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu}
2019acc1853519a0473620d424105f9d49ea5b4e62eJay Lan
2023d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheustatic int fill_stats_for_pid(pid_t pid, struct taskstats *stats)
2033d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu{
2043d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	struct task_struct *tsk;
205c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
2063d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	rcu_read_lock();
2073d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	tsk = find_task_by_vpid(pid);
2083d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	if (tsk)
2093d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu		get_task_struct(tsk);
2103d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	rcu_read_unlock();
2113d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	if (!tsk)
2123d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu		return -ESRCH;
2134bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	fill_stats(current_user_ns(), task_active_pid_ns(current), tsk, stats);
2143d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	put_task_struct(tsk);
2153d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	return 0;
216c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar}
217c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
2183d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheustatic int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
219c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar{
2203d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	struct task_struct *tsk, *first;
221ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	unsigned long flags;
222a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	int rc = -ESRCH;
223c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
224ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	/*
225ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 * Add additional stats from live tasks except zombie thread group
226ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 * leaders who are already counted with the dead tasks
227ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 */
228a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	rcu_read_lock();
2293d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	first = find_task_by_vpid(tgid);
230ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar
231a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	if (!first || !lock_task_sighand(first, &flags))
232a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov		goto out;
233ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar
234a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	if (first->signal->stats)
235a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov		memcpy(stats, first->signal->stats, sizeof(*stats));
23651de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	else
23751de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov		memset(stats, 0, sizeof(*stats));
238fca178c0c6e8d52a1875be36b070f30884ebfae9Oleg Nesterov
239a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	tsk = first;
240c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	do {
241d7c3f5f231c60d7e6ada5770b536df2b3ec1bd08Oleg Nesterov		if (tsk->exit_state)
242ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar			continue;
243c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		/*
244ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar		 * Accounting subsystem can call its functions here to
245c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		 * fill in relevant parts of struct taskstsats as follows
246c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		 *
247ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar		 *	per-task-foo(stats, tsk);
248c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		 */
249ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar		delayacct_add_tsk(stats, tsk);
2506f44993fe1d7b2b097f6ac60cd5835c6f5ca0874Shailabh Nagar
251b663a79c191508f27cd885224b592a878c0ba0f6Maxim Uvarov		stats->nvcsw += tsk->nvcsw;
252b663a79c191508f27cd885224b592a878c0ba0f6Maxim Uvarov		stats->nivcsw += tsk->nivcsw;
253c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	} while_each_thread(first, tsk);
2546f44993fe1d7b2b097f6ac60cd5835c6f5ca0874Shailabh Nagar
255a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	unlock_task_sighand(first, &flags);
256a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	rc = 0;
257a98b6094261c0112e9c455c96995972181bff049Oleg Nesterovout:
258a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	rcu_read_unlock();
259a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov
260a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	stats->version = TASKSTATS_VERSION;
261c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	/*
2623a4fa0a25da81600ea0bcd75692ae8ca6050d165Robert P. J. Day	 * Accounting subsystems can also add calls here to modify
263ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 * fields of taskstats.
264c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 */
265a98b6094261c0112e9c455c96995972181bff049Oleg Nesterov	return rc;
266ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar}
267ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar
268ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagarstatic void fill_tgid_exit(struct task_struct *tsk)
269ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar{
270ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	unsigned long flags;
271ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar
272b8534d7bd89df0cd41cd47bcd6733a05ea9a691aOleg Nesterov	spin_lock_irqsave(&tsk->sighand->siglock, flags);
273ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	if (!tsk->signal->stats)
274ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar		goto ret;
275ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar
276ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	/*
277ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 * Each accounting subsystem calls its functions here to
278ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 * accumalate its per-task stats for tsk, into the per-tgid structure
279ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 *
280ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 *	per-task-foo(tsk->signal->stats, tsk);
281ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 */
282ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	delayacct_add_tsk(tsk->signal->stats, tsk);
283ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagarret:
284b8534d7bd89df0cd41cd47bcd6733a05ea9a691aOleg Nesterov	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
285ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	return;
286c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar}
287c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
28841c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russellstatic int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
289f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar{
290f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	struct listener_list *listeners;
29126c4caea9d697043cc5a458b96411b86d7f6babdVasiliy Kulikov	struct listener *s, *tmp, *s2;
292f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	unsigned int cpu;
2930d20633b041041ecda39ae562e62087acf0092f1Chen Gang	int ret = 0;
294ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar
29541c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell	if (!cpumask_subset(mask, cpu_possible_mask))
296f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		return -EINVAL;
297f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
2984bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	if (current_user_ns() != &init_user_ns)
2994bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman		return -EINVAL;
3004bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman
3014bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	if (task_active_pid_ns(current) != &init_pid_ns)
3024bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman		return -EINVAL;
3034bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman
304f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	if (isadd == REGISTER) {
30541c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell		for_each_cpu(cpu, mask) {
306dfc428b656c4693a2334a8d9865b430beddb562aOleg Nesterov			s = kmalloc_node(sizeof(struct listener),
307dfc428b656c4693a2334a8d9865b430beddb562aOleg Nesterov					GFP_KERNEL, cpu_to_node(cpu));
3080d20633b041041ecda39ae562e62087acf0092f1Chen Gang			if (!s) {
3090d20633b041041ecda39ae562e62087acf0092f1Chen Gang				ret = -ENOMEM;
310f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar				goto cleanup;
3110d20633b041041ecda39ae562e62087acf0092f1Chen Gang			}
312f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar			s->pid = pid;
313bb129994c3bff9c5e8df91f05d7e9b6402fbd83fShailabh Nagar			s->valid = 1;
314f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
315f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar			listeners = &per_cpu(listener_array, cpu);
316f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar			down_write(&listeners->sem);
317dfc428b656c4693a2334a8d9865b430beddb562aOleg Nesterov			list_for_each_entry(s2, &listeners->list, list) {
318a7295898a1d2e501427f557111c2b4bdfc90b1edOleg Nesterov				if (s2->pid == pid && s2->valid)
319dfc428b656c4693a2334a8d9865b430beddb562aOleg Nesterov					goto exists;
32026c4caea9d697043cc5a458b96411b86d7f6babdVasiliy Kulikov			}
321f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar			list_add(&s->list, &listeners->list);
32226c4caea9d697043cc5a458b96411b86d7f6babdVasiliy Kulikov			s = NULL;
323dfc428b656c4693a2334a8d9865b430beddb562aOleg Nesterovexists:
324f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar			up_write(&listeners->sem);
325dfc428b656c4693a2334a8d9865b430beddb562aOleg Nesterov			kfree(s); /* nop if NULL */
326f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		}
327f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		return 0;
328f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	}
329f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
330f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	/* Deregister or cleanup */
331f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagarcleanup:
33241c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell	for_each_cpu(cpu, mask) {
333f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		listeners = &per_cpu(listener_array, cpu);
334f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		down_write(&listeners->sem);
335f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		list_for_each_entry_safe(s, tmp, &listeners->list, list) {
336f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar			if (s->pid == pid) {
337f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar				list_del(&s->list);
338f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar				kfree(s);
339f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar				break;
340f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar			}
341f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		}
342f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		up_write(&listeners->sem);
343f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	}
3440d20633b041041ecda39ae562e62087acf0092f1Chen Gang	return ret;
345f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar}
346f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
34741c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russellstatic int parse(struct nlattr *na, struct cpumask *mask)
348f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar{
349f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	char *data;
350f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	int len;
351f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	int ret;
352f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
353f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	if (na == NULL)
354f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		return 1;
355f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	len = nla_len(na);
356f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	if (len > TASKSTATS_CPUMASK_MAXLEN)
357f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		return -E2BIG;
358f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	if (len < 1)
359f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		return -EINVAL;
360f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	data = kmalloc(len, GFP_KERNEL);
361f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	if (!data)
362f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		return -ENOMEM;
363f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	nla_strlcpy(data, na, len);
36429c0177e6a4ac094302bed54a1d4bbb6b740a9efRusty Russell	ret = cpulist_parse(data, mask);
365f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	kfree(data);
366f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	return ret;
367f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar}
368f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
3699ab020cf07e457a8b425bf5af17e704f90f86d8bJeff Mahoney#if defined(CONFIG_64BIT) && !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
3704be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney#define TASKSTATS_NEEDS_PADDING 1
3714be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney#endif
3724be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney
37351de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterovstatic struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid)
37468062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov{
37551de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	struct nlattr *na, *ret;
37668062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov	int aggr;
37768062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov
37837167485302c8876cb0303af113696e88c2945aaOleg Nesterov	aggr = (type == TASKSTATS_TYPE_PID)
37937167485302c8876cb0303af113696e88c2945aaOleg Nesterov			? TASKSTATS_TYPE_AGGR_PID
38037167485302c8876cb0303af113696e88c2945aaOleg Nesterov			: TASKSTATS_TYPE_AGGR_TGID;
38168062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov
3824be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	/*
3834be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * The taskstats structure is internally aligned on 8 byte
3844be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * boundaries but the layout of the aggregrate reply, with
3854be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * two NLA headers and the pid (each 4 bytes), actually
3864be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * force the entire structure to be unaligned. This causes
3874be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * the kernel to issue unaligned access warnings on some
3884be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * architectures like ia64. Unfortunately, some software out there
3894be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * doesn't properly unroll the NLA packet and assumes that the start
3904be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * of the taskstats structure will always be 20 bytes from the start
3914be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * of the netlink payload. Aligning the start of the taskstats
3924be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * structure breaks this software, which we don't want. So, for now
3934be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * the alignment only happens on architectures that require it
3944be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * and those users will have to update to fixed versions of those
3954be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * packages. Space is reserved in the packet only when needed.
3964be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * This ifdef should be removed in several years e.g. 2012 once
3974be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * we can be confident that fixed versions are installed on most
3984be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * systems. We add the padding before the aggregate since the
3994be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 * aggregate is already a defined type.
4004be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	 */
4014be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney#ifdef TASKSTATS_NEEDS_PADDING
4024be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	if (nla_put(skb, TASKSTATS_TYPE_NULL, 0, NULL) < 0)
4034be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney		goto err;
4044be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney#endif
40568062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov	na = nla_nest_start(skb, aggr);
40637167485302c8876cb0303af113696e88c2945aaOleg Nesterov	if (!na)
40737167485302c8876cb0303af113696e88c2945aaOleg Nesterov		goto err;
4084be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney
4093fa582663129330d57d15b97ae534dc1203fc3aaChen Gang	if (nla_put(skb, type, sizeof(pid), &pid) < 0) {
4103fa582663129330d57d15b97ae534dc1203fc3aaChen Gang		nla_nest_cancel(skb, na);
41151de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov		goto err;
4123fa582663129330d57d15b97ae534dc1203fc3aaChen Gang	}
41351de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	ret = nla_reserve(skb, TASKSTATS_TYPE_STATS, sizeof(struct taskstats));
4143fa582663129330d57d15b97ae534dc1203fc3aaChen Gang	if (!ret) {
4153fa582663129330d57d15b97ae534dc1203fc3aaChen Gang		nla_nest_cancel(skb, na);
41651de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov		goto err;
4173fa582663129330d57d15b97ae534dc1203fc3aaChen Gang	}
41868062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov	nla_nest_end(skb, na);
41968062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov
42051de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	return nla_data(ret);
42151de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesteroverr:
42251de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	return NULL;
42368062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov}
42468062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov
425846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singhstatic int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
426846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh{
427846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	int rc = 0;
428846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	struct sk_buff *rep_skb;
429846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	struct cgroupstats *stats;
430846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	struct nlattr *na;
431846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	size_t size;
432846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	u32 fd;
4332903ff019b346ab8d36ebbf54853c3aaf6590608Al Viro	struct fd f;
434846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
435846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	na = info->attrs[CGROUPSTATS_CMD_ATTR_FD];
436846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	if (!na)
437846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh		return -EINVAL;
438846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
439846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]);
4402903ff019b346ab8d36ebbf54853c3aaf6590608Al Viro	f = fdget(fd);
4412903ff019b346ab8d36ebbf54853c3aaf6590608Al Viro	if (!f.file)
442f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk		return 0;
443846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
444f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk	size = nla_total_size(sizeof(struct cgroupstats));
445846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
446f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk	rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb,
447f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk				size);
448f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk	if (rc < 0)
449f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk		goto err;
450846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
451f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk	na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS,
452f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk				sizeof(struct cgroupstats));
45325353b3377d5a75d4b830477bb90a3691155de72Alan Cox	if (na == NULL) {
4540324b5a450f8a58304e93c5d886add24ca3527bcJesper Juhl		nlmsg_free(rep_skb);
45525353b3377d5a75d4b830477bb90a3691155de72Alan Cox		rc = -EMSGSIZE;
45625353b3377d5a75d4b830477bb90a3691155de72Alan Cox		goto err;
45725353b3377d5a75d4b830477bb90a3691155de72Alan Cox	}
45825353b3377d5a75d4b830477bb90a3691155de72Alan Cox
459f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk	stats = nla_data(na);
460f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk	memset(stats, 0, sizeof(*stats));
461846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
4622903ff019b346ab8d36ebbf54853c3aaf6590608Al Viro	rc = cgroupstats_build(stats, f.file->f_dentry);
463f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk	if (rc < 0) {
464f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk		nlmsg_free(rep_skb);
465f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk		goto err;
466846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	}
467846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
468134e63756d5f3d0f7604dfcca847b09d1b14fd66Johannes Berg	rc = send_reply(rep_skb, info);
469f96159840bc5f605aca5113ab2d24308d3dc2effAdrian Bunk
470846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singherr:
4712903ff019b346ab8d36ebbf54853c3aaf6590608Al Viro	fdput(f);
472846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh	return rc;
473846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh}
474846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
4759323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheustatic int cmd_attr_register_cpumask(struct genl_info *info)
476c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar{
47741c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell	cpumask_var_t mask;
4789323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	int rc;
47941c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell
48041c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
48141c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell		return -ENOMEM;
48241c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell	rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], mask);
483f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	if (rc < 0)
4849323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		goto out;
48515e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman	rc = add_del_listener(info->snd_portid, mask, REGISTER);
4869323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheuout:
4879323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	free_cpumask_var(mask);
4889323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	return rc;
4899323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu}
4909323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu
4919323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheustatic int cmd_attr_deregister_cpumask(struct genl_info *info)
4929323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu{
4939323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	cpumask_var_t mask;
4949323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	int rc;
495f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
4969323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
4979323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		return -ENOMEM;
49841c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell	rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], mask);
499f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	if (rc < 0)
5009323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		goto out;
50115e473046cb6e5d18a4d0057e61d76315230382bEric W. Biederman	rc = add_del_listener(info->snd_portid, mask, DEREGISTER);
5029323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheuout:
50341c7bb9588904eb060a95bcad47bd3804a1ece25Rusty Russell	free_cpumask_var(mask);
5049323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	return rc;
5059323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu}
5069323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu
5074be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoneystatic size_t taskstats_packet_size(void)
5084be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney{
5094be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	size_t size;
5104be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney
5114be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	size = nla_total_size(sizeof(u32)) +
5124be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney		nla_total_size(sizeof(struct taskstats)) + nla_total_size(0);
5134be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney#ifdef TASKSTATS_NEEDS_PADDING
5144be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	size += nla_total_size(0); /* Padding for alignment */
5154be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney#endif
5164be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	return size;
5174be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney}
5184be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney
5199323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheustatic int cmd_attr_pid(struct genl_info *info)
5209323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu{
5219323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	struct taskstats *stats;
5229323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	struct sk_buff *rep_skb;
5239323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	size_t size;
5249323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	u32 pid;
5259323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	int rc;
526c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
5274be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	size = taskstats_packet_size();
528c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
52937167485302c8876cb0303af113696e88c2945aaOleg Nesterov	rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);
530c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	if (rc < 0)
531c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		return rc;
532c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
53351de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	rc = -EINVAL;
5349323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]);
5359323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid);
5369323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	if (!stats)
537c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		goto err;
538c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
5393d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	rc = fill_stats_for_pid(pid, stats);
5409323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	if (rc < 0)
5419323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		goto err;
542134e63756d5f3d0f7604dfcca847b09d1b14fd66Johannes Berg	return send_reply(rep_skb, info);
543c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagarerr:
544c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	nlmsg_free(rep_skb);
545c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	return rc;
546c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar}
547c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
5489323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheustatic int cmd_attr_tgid(struct genl_info *info)
5499323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu{
5509323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	struct taskstats *stats;
5519323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	struct sk_buff *rep_skb;
5529323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	size_t size;
5539323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	u32 tgid;
5549323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	int rc;
5559323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu
5564be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	size = taskstats_packet_size();
5579323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu
5589323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);
5599323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	if (rc < 0)
5609323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		return rc;
5619323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu
5629323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	rc = -EINVAL;
5639323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]);
5649323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid);
5659323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	if (!stats)
5669323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		goto err;
5679323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu
5683d9e0cf1fe007b88db55d43dfdb6839e1a029ca5Michael Holzheu	rc = fill_stats_for_tgid(tgid, stats);
5699323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	if (rc < 0)
5709323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		goto err;
5719323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	return send_reply(rep_skb, info);
5729323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheuerr:
5739323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	nlmsg_free(rep_skb);
5749323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	return rc;
5759323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu}
5769323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu
5779323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheustatic int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
5789323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu{
5799323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	if (info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK])
5809323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		return cmd_attr_register_cpumask(info);
5819323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	else if (info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK])
5829323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		return cmd_attr_deregister_cpumask(info);
5839323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	else if (info->attrs[TASKSTATS_CMD_ATTR_PID])
5849323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		return cmd_attr_pid(info);
5859323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	else if (info->attrs[TASKSTATS_CMD_ATTR_TGID])
5869323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		return cmd_attr_tgid(info);
5879323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu	else
5889323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu		return -EINVAL;
5899323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu}
5909323312592cca636d7c2580dc85fa4846efa86a2Michael Holzheu
59134ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterovstatic struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk)
59234ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov{
59334ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	struct signal_struct *sig = tsk->signal;
59434ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	struct taskstats *stats;
59534ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov
59634ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	if (sig->stats || thread_group_empty(tsk))
59734ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov		goto ret;
59834ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov
59934ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	/* No problem if kmem_cache_zalloc() fails */
60034ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
60134ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov
60234ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	spin_lock_irq(&tsk->sighand->siglock);
60334ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	if (!sig->stats) {
60434ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov		sig->stats = stats;
60534ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov		stats = NULL;
60634ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	}
60734ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	spin_unlock_irq(&tsk->sighand->siglock);
60834ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov
60934ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	if (stats)
61034ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov		kmem_cache_free(taskstats_cache, stats);
61134ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterovret:
61234ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	return sig->stats;
61334ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov}
61434ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov
615c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar/* Send pid data out on exit */
616115085ea0794c0f339be8f9d25505c7f9861d824Oleg Nesterovvoid taskstats_exit(struct task_struct *tsk, int group_dead)
617c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar{
618c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	int rc;
619115085ea0794c0f339be8f9d25505c7f9861d824Oleg Nesterov	struct listener_list *listeners;
62051de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	struct taskstats *stats;
621c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	struct sk_buff *rep_skb;
622c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	size_t size;
623c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	int is_thread_group;
624c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
6254a279ff1ea1cf325775ada983035123fcdc8e986Oleg Nesterov	if (!family_registered)
626c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		return;
627c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
628c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	/*
629c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 * Size includes space for nested attributes
630c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 */
6314be2c95d1f7706ca0e74499f2bd118e1cee19669Jeff Mahoney	size = taskstats_packet_size();
632c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
63334ec12349c8a9505adc59d72f92b4595bc2483ffOleg Nesterov	is_thread_group = !!taskstats_tgid_alloc(tsk);
6344a279ff1ea1cf325775ada983035123fcdc8e986Oleg Nesterov	if (is_thread_group) {
6354a279ff1ea1cf325775ada983035123fcdc8e986Oleg Nesterov		/* PID + STATS + TGID + STATS */
6364a279ff1ea1cf325775ada983035123fcdc8e986Oleg Nesterov		size = 2 * size;
6374a279ff1ea1cf325775ada983035123fcdc8e986Oleg Nesterov		/* fill the tsk->signal->stats structure */
6384a279ff1ea1cf325775ada983035123fcdc8e986Oleg Nesterov		fill_tgid_exit(tsk);
6394a279ff1ea1cf325775ada983035123fcdc8e986Oleg Nesterov	}
6404a279ff1ea1cf325775ada983035123fcdc8e986Oleg Nesterov
6414a32fea9d78f2d2315c0072757b197d5a304dc8bChristoph Lameter	listeners = raw_cpu_ptr(&listener_array);
642115085ea0794c0f339be8f9d25505c7f9861d824Oleg Nesterov	if (list_empty(&listeners->list))
643115085ea0794c0f339be8f9d25505c7f9861d824Oleg Nesterov		return;
644115085ea0794c0f339be8f9d25505c7f9861d824Oleg Nesterov
64537167485302c8876cb0303af113696e88c2945aaOleg Nesterov	rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, size);
646c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	if (rc < 0)
64751de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov		return;
648c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
6494bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID,
6504bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman			 task_pid_nr_ns(tsk, &init_pid_ns));
65151de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	if (!stats)
65237167485302c8876cb0303af113696e88c2945aaOleg Nesterov		goto err;
653c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
6544bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	fill_stats(&init_user_ns, &init_pid_ns, tsk, stats);
655c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
656c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	/*
657ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	 * Doesn't matter if tsk is the leader or the last group member leaving
658c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	 */
65968062b86fc0f480b806d270a8278709a5a41bb67Oleg Nesterov	if (!is_thread_group || !group_dead)
660ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar		goto send;
661c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
6624bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID,
6634bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman			 task_tgid_nr_ns(tsk, &init_pid_ns));
66451de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	if (!stats)
66537167485302c8876cb0303af113696e88c2945aaOleg Nesterov		goto err;
66651de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov
66751de4d90852ba4cfa5743594ec4a7f158b52dc43Oleg Nesterov	memcpy(stats, tsk->signal->stats, sizeof(*stats));
668c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
669ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagarsend:
670115085ea0794c0f339be8f9d25505c7f9861d824Oleg Nesterov	send_cpu_listeners(rep_skb, listeners);
671ad4ecbcba72855a2b5319b96e2a3a65ed1ca3bfdShailabh Nagar	return;
67237167485302c8876cb0303af113696e88c2945aaOleg Nesteroverr:
673c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	nlmsg_free(rep_skb);
674c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar}
675c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
6764534de8305b3f1460a527a0cda0e3dc2224c6f0cJohannes Bergstatic const struct genl_ops taskstats_ops[] = {
67788d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg	{
67888d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg		.cmd		= TASKSTATS_CMD_GET,
67988d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg		.doit		= taskstats_user_cmd,
68088d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg		.policy		= taskstats_cmd_get_policy,
68188d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg		.flags		= GENL_ADMIN_PERM,
68288d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg	},
68388d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg	{
68488d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg		.cmd		= CGROUPSTATS_CMD_GET,
68588d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg		.doit		= cgroupstats_user_cmd,
68688d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg		.policy		= cgroupstats_cmd_get_policy,
68788d36a9949513419de3a506e7fca8b82d1dc972aJohannes Berg	},
688846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh};
689846c7bb055747989891f5cd2bb6e8d56243ba1e7Balbir Singh
690c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar/* Needed early in initialization */
691c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagarvoid __init taskstats_init_early(void)
692c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar{
693f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	unsigned int i;
694f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar
6950a31bd5f2bbb6473ef9d24f0063ca91cfa678b64Christoph Lameter	taskstats_cache = KMEM_CACHE(taskstats, SLAB_PANIC);
696f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	for_each_possible_cpu(i) {
697f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		INIT_LIST_HEAD(&(per_cpu(listener_array, i).list));
698f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar		init_rwsem(&(per_cpu(listener_array, i).sem));
699f9fd8914c1acca0d98b69d831b128d5b52f03c51Shailabh Nagar	}
700c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar}
701c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
702c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagarstatic int __init taskstats_init(void)
703c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar{
704c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	int rc;
705c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
706c53ed7423619b4e8108914a9f31b426dd58ad591Johannes Berg	rc = genl_register_family_with_ops(&family, taskstats_ops);
707c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	if (rc)
708c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar		return rc;
709c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
710c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	family_registered = 1;
711f9b182e24ecb2b3bb33340f053ba31c8c4e1d895Mandeep Singh Baines	pr_info("registered taskstats version %d\n", TASKSTATS_GENL_VERSION);
712c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar	return 0;
713c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar}
714c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar
715c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar/*
716c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * late initcall ensures initialization of statistics collection
717c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar * mechanisms precedes initialization of the taskstats interface
718c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagar */
719c757249af152c59fd74b85e52e8c090acb33d9c0Shailabh Nagarlate_initcall(taskstats_init);
720