diff options
Diffstat (limited to 'kernel/taskstats.c')
-rw-r--r-- | kernel/taskstats.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index 7d4d7f9c1bb2..9f360f68aad6 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
@@ -22,6 +22,10 @@ | |||
22 | #include <linux/delayacct.h> | 22 | #include <linux/delayacct.h> |
23 | #include <linux/cpumask.h> | 23 | #include <linux/cpumask.h> |
24 | #include <linux/percpu.h> | 24 | #include <linux/percpu.h> |
25 | #include <linux/cgroupstats.h> | ||
26 | #include <linux/cgroup.h> | ||
27 | #include <linux/fs.h> | ||
28 | #include <linux/file.h> | ||
25 | #include <net/genetlink.h> | 29 | #include <net/genetlink.h> |
26 | #include <asm/atomic.h> | 30 | #include <asm/atomic.h> |
27 | 31 | ||
@@ -49,6 +53,11 @@ __read_mostly = { | |||
49 | [TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING }, | 53 | [TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING }, |
50 | [TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },}; | 54 | [TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },}; |
51 | 55 | ||
56 | static struct nla_policy | ||
57 | cgroupstats_cmd_get_policy[CGROUPSTATS_CMD_ATTR_MAX+1] __read_mostly = { | ||
58 | [CGROUPSTATS_CMD_ATTR_FD] = { .type = NLA_U32 }, | ||
59 | }; | ||
60 | |||
52 | struct listener { | 61 | struct listener { |
53 | struct list_head list; | 62 | struct list_head list; |
54 | pid_t pid; | 63 | pid_t pid; |
@@ -372,6 +381,51 @@ err: | |||
372 | return NULL; | 381 | return NULL; |
373 | } | 382 | } |
374 | 383 | ||
384 | static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | ||
385 | { | ||
386 | int rc = 0; | ||
387 | struct sk_buff *rep_skb; | ||
388 | struct cgroupstats *stats; | ||
389 | struct nlattr *na; | ||
390 | size_t size; | ||
391 | u32 fd; | ||
392 | struct file *file; | ||
393 | int fput_needed; | ||
394 | |||
395 | na = info->attrs[CGROUPSTATS_CMD_ATTR_FD]; | ||
396 | if (!na) | ||
397 | return -EINVAL; | ||
398 | |||
399 | fd = nla_get_u32(info->attrs[CGROUPSTATS_CMD_ATTR_FD]); | ||
400 | file = fget_light(fd, &fput_needed); | ||
401 | if (file) { | ||
402 | size = nla_total_size(sizeof(struct cgroupstats)); | ||
403 | |||
404 | rc = prepare_reply(info, CGROUPSTATS_CMD_NEW, &rep_skb, | ||
405 | size); | ||
406 | if (rc < 0) | ||
407 | goto err; | ||
408 | |||
409 | na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS, | ||
410 | sizeof(struct cgroupstats)); | ||
411 | stats = nla_data(na); | ||
412 | memset(stats, 0, sizeof(*stats)); | ||
413 | |||
414 | rc = cgroupstats_build(stats, file->f_dentry); | ||
415 | if (rc < 0) | ||
416 | goto err; | ||
417 | |||
418 | fput_light(file, fput_needed); | ||
419 | return send_reply(rep_skb, info->snd_pid); | ||
420 | } | ||
421 | |||
422 | err: | ||
423 | if (file) | ||
424 | fput_light(file, fput_needed); | ||
425 | nlmsg_free(rep_skb); | ||
426 | return rc; | ||
427 | } | ||
428 | |||
375 | static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | 429 | static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) |
376 | { | 430 | { |
377 | int rc = 0; | 431 | int rc = 0; |
@@ -522,6 +576,12 @@ static struct genl_ops taskstats_ops = { | |||
522 | .policy = taskstats_cmd_get_policy, | 576 | .policy = taskstats_cmd_get_policy, |
523 | }; | 577 | }; |
524 | 578 | ||
579 | static struct genl_ops cgroupstats_ops = { | ||
580 | .cmd = CGROUPSTATS_CMD_GET, | ||
581 | .doit = cgroupstats_user_cmd, | ||
582 | .policy = cgroupstats_cmd_get_policy, | ||
583 | }; | ||
584 | |||
525 | /* Needed early in initialization */ | 585 | /* Needed early in initialization */ |
526 | void __init taskstats_init_early(void) | 586 | void __init taskstats_init_early(void) |
527 | { | 587 | { |
@@ -546,8 +606,15 @@ static int __init taskstats_init(void) | |||
546 | if (rc < 0) | 606 | if (rc < 0) |
547 | goto err; | 607 | goto err; |
548 | 608 | ||
609 | rc = genl_register_ops(&family, &cgroupstats_ops); | ||
610 | if (rc < 0) | ||
611 | goto err_cgroup_ops; | ||
612 | |||
549 | family_registered = 1; | 613 | family_registered = 1; |
614 | printk("registered taskstats version %d\n", TASKSTATS_GENL_VERSION); | ||
550 | return 0; | 615 | return 0; |
616 | err_cgroup_ops: | ||
617 | genl_unregister_ops(&family, &taskstats_ops); | ||
551 | err: | 618 | err: |
552 | genl_unregister_family(&family); | 619 | genl_unregister_family(&family); |
553 | return rc; | 620 | return rc; |