diff options
Diffstat (limited to 'kernel/taskstats.c')
-rw-r--r-- | kernel/taskstats.c | 55 |
1 files changed, 28 insertions, 27 deletions
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 7d793d6b1e90..d2a41339f37b 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
@@ -343,6 +343,25 @@ static int parse(struct nlattr *na, cpumask_t *mask) | |||
343 | return ret; | 343 | return ret; |
344 | } | 344 | } |
345 | 345 | ||
346 | static int mk_reply(struct sk_buff *skb, int type, u32 pid, struct taskstats *stats) | ||
347 | { | ||
348 | struct nlattr *na; | ||
349 | int aggr; | ||
350 | |||
351 | aggr = TASKSTATS_TYPE_AGGR_TGID; | ||
352 | if (type == TASKSTATS_TYPE_PID) | ||
353 | aggr = TASKSTATS_TYPE_AGGR_PID; | ||
354 | |||
355 | na = nla_nest_start(skb, aggr); | ||
356 | NLA_PUT_U32(skb, type, pid); | ||
357 | NLA_PUT_TYPE(skb, struct taskstats, TASKSTATS_TYPE_STATS, *stats); | ||
358 | nla_nest_end(skb, na); | ||
359 | |||
360 | return 0; | ||
361 | nla_put_failure: | ||
362 | return -1; | ||
363 | } | ||
364 | |||
346 | static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | 365 | static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) |
347 | { | 366 | { |
348 | int rc = 0; | 367 | int rc = 0; |
@@ -350,7 +369,6 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | |||
350 | struct taskstats stats; | 369 | struct taskstats stats; |
351 | void *reply; | 370 | void *reply; |
352 | size_t size; | 371 | size_t size; |
353 | struct nlattr *na; | ||
354 | cpumask_t mask; | 372 | cpumask_t mask; |
355 | 373 | ||
356 | rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], &mask); | 374 | rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], &mask); |
@@ -382,27 +400,21 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | |||
382 | if (rc < 0) | 400 | if (rc < 0) |
383 | goto err; | 401 | goto err; |
384 | 402 | ||
385 | na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID); | 403 | if (mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid, &stats)) |
386 | NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, pid); | 404 | goto nla_put_failure; |
387 | NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, | ||
388 | stats); | ||
389 | } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) { | 405 | } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) { |
390 | u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]); | 406 | u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]); |
391 | rc = fill_tgid(tgid, NULL, &stats); | 407 | rc = fill_tgid(tgid, NULL, &stats); |
392 | if (rc < 0) | 408 | if (rc < 0) |
393 | goto err; | 409 | goto err; |
394 | 410 | ||
395 | na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID); | 411 | if (mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid, &stats)) |
396 | NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, tgid); | 412 | goto nla_put_failure; |
397 | NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, | ||
398 | stats); | ||
399 | } else { | 413 | } else { |
400 | rc = -EINVAL; | 414 | rc = -EINVAL; |
401 | goto err; | 415 | goto err; |
402 | } | 416 | } |
403 | 417 | ||
404 | nla_nest_end(rep_skb, na); | ||
405 | |||
406 | return send_reply(rep_skb, info->snd_pid); | 418 | return send_reply(rep_skb, info->snd_pid); |
407 | 419 | ||
408 | nla_put_failure: | 420 | nla_put_failure: |
@@ -446,7 +458,6 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) | |||
446 | void *reply; | 458 | void *reply; |
447 | size_t size; | 459 | size_t size; |
448 | int is_thread_group; | 460 | int is_thread_group; |
449 | struct nlattr *na; | ||
450 | 461 | ||
451 | if (!family_registered) | 462 | if (!family_registered) |
452 | return; | 463 | return; |
@@ -481,27 +492,17 @@ void taskstats_exit(struct task_struct *tsk, int group_dead) | |||
481 | if (rc < 0) | 492 | if (rc < 0) |
482 | goto err_skb; | 493 | goto err_skb; |
483 | 494 | ||
484 | na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID); | 495 | if (mk_reply(rep_skb, TASKSTATS_TYPE_PID, tsk->pid, tidstats)) |
485 | NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, (u32)tsk->pid); | 496 | goto nla_put_failure; |
486 | NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, | ||
487 | *tidstats); | ||
488 | nla_nest_end(rep_skb, na); | ||
489 | |||
490 | if (!is_thread_group) | ||
491 | goto send; | ||
492 | 497 | ||
493 | /* | 498 | /* |
494 | * Doesn't matter if tsk is the leader or the last group member leaving | 499 | * Doesn't matter if tsk is the leader or the last group member leaving |
495 | */ | 500 | */ |
496 | if (!group_dead) | 501 | if (!is_thread_group || !group_dead) |
497 | goto send; | 502 | goto send; |
498 | 503 | ||
499 | na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID); | 504 | if (mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tsk->tgid, tsk->signal->stats)) |
500 | NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, (u32)tsk->tgid); | 505 | goto nla_put_failure; |
501 | /* No locking needed for tsk->signal->stats since group is dead */ | ||
502 | NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, | ||
503 | *tsk->signal->stats); | ||
504 | nla_nest_end(rep_skb, na); | ||
505 | 506 | ||
506 | send: | 507 | send: |
507 | send_cpu_listeners(rep_skb, listeners); | 508 | send_cpu_listeners(rep_skb, listeners); |