aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/taskstats.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/taskstats.c')
-rw-r--r--kernel/taskstats.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index abb59e323544..f45179ce028e 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -51,6 +51,7 @@ __read_mostly = {
51struct listener { 51struct listener {
52 struct list_head list; 52 struct list_head list;
53 pid_t pid; 53 pid_t pid;
54 char valid;
54}; 55};
55 56
56struct listener_list { 57struct listener_list {
@@ -127,7 +128,7 @@ static int send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
127 struct listener *s, *tmp; 128 struct listener *s, *tmp;
128 struct sk_buff *skb_next, *skb_cur = skb; 129 struct sk_buff *skb_next, *skb_cur = skb;
129 void *reply = genlmsg_data(genlhdr); 130 void *reply = genlmsg_data(genlhdr);
130 int rc, ret; 131 int rc, ret, delcount = 0;
131 132
132 rc = genlmsg_end(skb, reply); 133 rc = genlmsg_end(skb, reply);
133 if (rc < 0) { 134 if (rc < 0) {
@@ -137,7 +138,7 @@ static int send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
137 138
138 rc = 0; 139 rc = 0;
139 listeners = &per_cpu(listener_array, cpu); 140 listeners = &per_cpu(listener_array, cpu);
140 down_write(&listeners->sem); 141 down_read(&listeners->sem);
141 list_for_each_entry_safe(s, tmp, &listeners->list, list) { 142 list_for_each_entry_safe(s, tmp, &listeners->list, list) {
142 skb_next = NULL; 143 skb_next = NULL;
143 if (!list_is_last(&s->list, &listeners->list)) { 144 if (!list_is_last(&s->list, &listeners->list)) {
@@ -150,14 +151,26 @@ static int send_cpu_listeners(struct sk_buff *skb, unsigned int cpu)
150 } 151 }
151 ret = genlmsg_unicast(skb_cur, s->pid); 152 ret = genlmsg_unicast(skb_cur, s->pid);
152 if (ret == -ECONNREFUSED) { 153 if (ret == -ECONNREFUSED) {
153 list_del(&s->list); 154 s->valid = 0;
154 kfree(s); 155 delcount++;
155 rc = ret; 156 rc = ret;
156 } 157 }
157 skb_cur = skb_next; 158 skb_cur = skb_next;
158 } 159 }
159 up_write(&listeners->sem); 160 up_read(&listeners->sem);
161
162 if (!delcount)
163 return rc;
160 164
165 /* Delete invalidated entries */
166 down_write(&listeners->sem);
167 list_for_each_entry_safe(s, tmp, &listeners->list, list) {
168 if (!s->valid) {
169 list_del(&s->list);
170 kfree(s);
171 }
172 }
173 up_write(&listeners->sem);
161 return rc; 174 return rc;
162} 175}
163 176
@@ -290,6 +303,7 @@ static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd)
290 goto cleanup; 303 goto cleanup;
291 s->pid = pid; 304 s->pid = pid;
292 INIT_LIST_HEAD(&s->list); 305 INIT_LIST_HEAD(&s->list);
306 s->valid = 1;
293 307
294 listeners = &per_cpu(listener_array, cpu); 308 listeners = &per_cpu(listener_array, cpu);
295 down_write(&listeners->sem); 309 down_write(&listeners->sem);