diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/taskstats.c | 118 |
1 files changed, 78 insertions, 40 deletions
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 5a651aa63d61..9970cae04f15 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
| @@ -430,39 +430,46 @@ err: | |||
| 430 | return rc; | 430 | return rc; |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | 433 | static int cmd_attr_register_cpumask(struct genl_info *info) |
| 434 | { | 434 | { |
| 435 | int rc; | ||
| 436 | struct sk_buff *rep_skb; | ||
| 437 | struct taskstats *stats; | ||
| 438 | size_t size; | ||
| 439 | cpumask_var_t mask; | 435 | cpumask_var_t mask; |
| 436 | int rc; | ||
| 440 | 437 | ||
| 441 | if (!alloc_cpumask_var(&mask, GFP_KERNEL)) | 438 | if (!alloc_cpumask_var(&mask, GFP_KERNEL)) |
| 442 | return -ENOMEM; | 439 | return -ENOMEM; |
| 443 | |||
| 444 | rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], mask); | 440 | rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], mask); |
| 445 | if (rc < 0) | 441 | if (rc < 0) |
| 446 | goto free_return_rc; | 442 | goto out; |
| 447 | if (rc == 0) { | 443 | rc = add_del_listener(info->snd_pid, mask, REGISTER); |
| 448 | rc = add_del_listener(info->snd_pid, mask, REGISTER); | 444 | out: |
| 449 | goto free_return_rc; | 445 | free_cpumask_var(mask); |
| 450 | } | 446 | return rc; |
| 447 | } | ||
| 451 | 448 | ||
| 449 | static int cmd_attr_deregister_cpumask(struct genl_info *info) | ||
| 450 | { | ||
| 451 | cpumask_var_t mask; | ||
| 452 | int rc; | ||
| 453 | |||
| 454 | if (!alloc_cpumask_var(&mask, GFP_KERNEL)) | ||
| 455 | return -ENOMEM; | ||
| 452 | rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], mask); | 456 | rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], mask); |
| 453 | if (rc < 0) | 457 | if (rc < 0) |
| 454 | goto free_return_rc; | 458 | goto out; |
| 455 | if (rc == 0) { | 459 | rc = add_del_listener(info->snd_pid, mask, DEREGISTER); |
| 456 | rc = add_del_listener(info->snd_pid, mask, DEREGISTER); | 460 | out: |
| 457 | free_return_rc: | ||
| 458 | free_cpumask_var(mask); | ||
| 459 | return rc; | ||
| 460 | } | ||
| 461 | free_cpumask_var(mask); | 461 | free_cpumask_var(mask); |
| 462 | return rc; | ||
| 463 | } | ||
| 464 | |||
| 465 | static int cmd_attr_pid(struct genl_info *info) | ||
| 466 | { | ||
| 467 | struct taskstats *stats; | ||
| 468 | struct sk_buff *rep_skb; | ||
| 469 | size_t size; | ||
| 470 | u32 pid; | ||
| 471 | int rc; | ||
| 462 | 472 | ||
| 463 | /* | ||
| 464 | * Size includes space for nested attributes | ||
| 465 | */ | ||
| 466 | size = nla_total_size(sizeof(u32)) + | 473 | size = nla_total_size(sizeof(u32)) + |
| 467 | nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); | 474 | nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); |
| 468 | 475 | ||
| @@ -471,33 +478,64 @@ free_return_rc: | |||
| 471 | return rc; | 478 | return rc; |
| 472 | 479 | ||
| 473 | rc = -EINVAL; | 480 | rc = -EINVAL; |
| 474 | if (info->attrs[TASKSTATS_CMD_ATTR_PID]) { | 481 | pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]); |
| 475 | u32 pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]); | 482 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid); |
| 476 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_PID, pid); | 483 | if (!stats) |
| 477 | if (!stats) | 484 | goto err; |
| 478 | goto err; | 485 | |
| 479 | 486 | rc = fill_pid(pid, NULL, stats); | |
| 480 | rc = fill_pid(pid, NULL, stats); | 487 | if (rc < 0) |
| 481 | if (rc < 0) | 488 | goto err; |
| 482 | goto err; | 489 | return send_reply(rep_skb, info); |
| 483 | } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) { | 490 | err: |
| 484 | u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]); | 491 | nlmsg_free(rep_skb); |
| 485 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid); | 492 | return rc; |
| 486 | if (!stats) | 493 | } |
| 487 | goto err; | 494 | |
| 488 | 495 | static int cmd_attr_tgid(struct genl_info *info) | |
| 489 | rc = fill_tgid(tgid, NULL, stats); | 496 | { |
| 490 | if (rc < 0) | 497 | struct taskstats *stats; |
| 491 | goto err; | 498 | struct sk_buff *rep_skb; |
| 492 | } else | 499 | size_t size; |
| 500 | u32 tgid; | ||
| 501 | int rc; | ||
| 502 | |||
| 503 | size = nla_total_size(sizeof(u32)) + | ||
| 504 | nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); | ||
| 505 | |||
| 506 | rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size); | ||
| 507 | if (rc < 0) | ||
| 508 | return rc; | ||
| 509 | |||
| 510 | rc = -EINVAL; | ||
| 511 | tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]); | ||
| 512 | stats = mk_reply(rep_skb, TASKSTATS_TYPE_TGID, tgid); | ||
| 513 | if (!stats) | ||
| 493 | goto err; | 514 | goto err; |
| 494 | 515 | ||
| 516 | rc = fill_tgid(tgid, NULL, stats); | ||
| 517 | if (rc < 0) | ||
| 518 | goto err; | ||
| 495 | return send_reply(rep_skb, info); | 519 | return send_reply(rep_skb, info); |
| 496 | err: | 520 | err: |
| 497 | nlmsg_free(rep_skb); | 521 | nlmsg_free(rep_skb); |
| 498 | return rc; | 522 | return rc; |
| 499 | } | 523 | } |
| 500 | 524 | ||
| 525 | static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | ||
| 526 | { | ||
| 527 | if (info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK]) | ||
| 528 | return cmd_attr_register_cpumask(info); | ||
| 529 | else if (info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK]) | ||
| 530 | return cmd_attr_deregister_cpumask(info); | ||
| 531 | else if (info->attrs[TASKSTATS_CMD_ATTR_PID]) | ||
| 532 | return cmd_attr_pid(info); | ||
| 533 | else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) | ||
| 534 | return cmd_attr_tgid(info); | ||
| 535 | else | ||
| 536 | return -EINVAL; | ||
| 537 | } | ||
| 538 | |||
| 501 | static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk) | 539 | static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk) |
| 502 | { | 540 | { |
| 503 | struct signal_struct *sig = tsk->signal; | 541 | struct signal_struct *sig = tsk->signal; |
