diff options
| -rw-r--r-- | include/linux/cgroup.h | 33 | ||||
| -rw-r--r-- | kernel/cgroup.c | 132 |
2 files changed, 162 insertions, 3 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index ad2a14680b7f..af6211c7a42b 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
| @@ -192,6 +192,7 @@ struct cgroup { | |||
| 192 | struct list_head css_sets; | 192 | struct list_head css_sets; |
| 193 | 193 | ||
| 194 | struct list_head allcg_node; /* cgroupfs_root->allcg_list */ | 194 | struct list_head allcg_node; /* cgroupfs_root->allcg_list */ |
| 195 | struct list_head cft_q_node; /* used during cftype add/rm */ | ||
| 195 | 196 | ||
| 196 | /* | 197 | /* |
| 197 | * Linked list running through all cgroups that can | 198 | * Linked list running through all cgroups that can |
| @@ -277,11 +278,17 @@ struct cgroup_map_cb { | |||
| 277 | * - the 'cftype' of the file is file->f_dentry->d_fsdata | 278 | * - the 'cftype' of the file is file->f_dentry->d_fsdata |
| 278 | */ | 279 | */ |
| 279 | 280 | ||
| 280 | #define MAX_CFTYPE_NAME 64 | 281 | /* cftype->flags */ |
| 282 | #define CFTYPE_ONLY_ON_ROOT (1U << 0) /* only create on root cg */ | ||
| 283 | #define CFTYPE_NOT_ON_ROOT (1U << 1) /* don't create onp root cg */ | ||
| 284 | |||
| 285 | #define MAX_CFTYPE_NAME 64 | ||
| 286 | |||
| 281 | struct cftype { | 287 | struct cftype { |
| 282 | /* | 288 | /* |
| 283 | * By convention, the name should begin with the name of the | 289 | * By convention, the name should begin with the name of the |
| 284 | * subsystem, followed by a period | 290 | * subsystem, followed by a period. Zero length string indicates |
| 291 | * end of cftype array. | ||
| 285 | */ | 292 | */ |
| 286 | char name[MAX_CFTYPE_NAME]; | 293 | char name[MAX_CFTYPE_NAME]; |
| 287 | int private; | 294 | int private; |
| @@ -297,6 +304,9 @@ struct cftype { | |||
| 297 | */ | 304 | */ |
| 298 | size_t max_write_len; | 305 | size_t max_write_len; |
| 299 | 306 | ||
| 307 | /* CFTYPE_* flags */ | ||
| 308 | unsigned int flags; | ||
| 309 | |||
| 300 | int (*open)(struct inode *inode, struct file *file); | 310 | int (*open)(struct inode *inode, struct file *file); |
| 301 | ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft, | 311 | ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft, |
| 302 | struct file *file, | 312 | struct file *file, |
| @@ -375,6 +385,16 @@ struct cftype { | |||
| 375 | struct eventfd_ctx *eventfd); | 385 | struct eventfd_ctx *eventfd); |
| 376 | }; | 386 | }; |
| 377 | 387 | ||
| 388 | /* | ||
| 389 | * cftype_sets describe cftypes belonging to a subsystem and are chained at | ||
| 390 | * cgroup_subsys->cftsets. Each cftset points to an array of cftypes | ||
| 391 | * terminated by zero length name. | ||
| 392 | */ | ||
| 393 | struct cftype_set { | ||
| 394 | struct list_head node; /* chained at subsys->cftsets */ | ||
| 395 | const struct cftype *cfts; | ||
| 396 | }; | ||
| 397 | |||
| 378 | struct cgroup_scanner { | 398 | struct cgroup_scanner { |
| 379 | struct cgroup *cg; | 399 | struct cgroup *cg; |
| 380 | int (*test_task)(struct task_struct *p, struct cgroup_scanner *scan); | 400 | int (*test_task)(struct task_struct *p, struct cgroup_scanner *scan); |
| @@ -400,6 +420,8 @@ int cgroup_add_files(struct cgroup *cgrp, | |||
| 400 | const struct cftype cft[], | 420 | const struct cftype cft[], |
| 401 | int count); | 421 | int count); |
| 402 | 422 | ||
| 423 | int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts); | ||
| 424 | |||
| 403 | int cgroup_is_removed(const struct cgroup *cgrp); | 425 | int cgroup_is_removed(const struct cgroup *cgrp); |
| 404 | 426 | ||
| 405 | int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen); | 427 | int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen); |
| @@ -502,6 +524,13 @@ struct cgroup_subsys { | |||
| 502 | struct idr idr; | 524 | struct idr idr; |
| 503 | spinlock_t id_lock; | 525 | spinlock_t id_lock; |
| 504 | 526 | ||
| 527 | /* list of cftype_sets */ | ||
| 528 | struct list_head cftsets; | ||
| 529 | |||
| 530 | /* base cftypes, automatically [de]registered with subsys itself */ | ||
| 531 | struct cftype *base_cftypes; | ||
| 532 | struct cftype_set base_cftset; | ||
| 533 | |||
| 505 | /* should be defined only by modular subsystems */ | 534 | /* should be defined only by modular subsystems */ |
| 506 | struct module *module; | 535 | struct module *module; |
| 507 | }; | 536 | }; |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index db4319c030d0..df8fb82ef350 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -2623,8 +2623,14 @@ int cgroup_add_file(struct cgroup *cgrp, | |||
| 2623 | struct dentry *dentry; | 2623 | struct dentry *dentry; |
| 2624 | int error; | 2624 | int error; |
| 2625 | umode_t mode; | 2625 | umode_t mode; |
| 2626 | |||
| 2627 | char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 }; | 2626 | char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 }; |
| 2627 | |||
| 2628 | /* does @cft->flags tell us to skip creation on @cgrp? */ | ||
| 2629 | if ((cft->flags & CFTYPE_NOT_ON_ROOT) && !cgrp->parent) | ||
| 2630 | return 0; | ||
| 2631 | if ((cft->flags & CFTYPE_ONLY_ON_ROOT) && cgrp->parent) | ||
| 2632 | return 0; | ||
| 2633 | |||
| 2628 | if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) { | 2634 | if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) { |
| 2629 | strcpy(name, subsys->name); | 2635 | strcpy(name, subsys->name); |
| 2630 | strcat(name, "."); | 2636 | strcat(name, "."); |
| @@ -2660,6 +2666,95 @@ int cgroup_add_files(struct cgroup *cgrp, | |||
| 2660 | } | 2666 | } |
| 2661 | EXPORT_SYMBOL_GPL(cgroup_add_files); | 2667 | EXPORT_SYMBOL_GPL(cgroup_add_files); |
| 2662 | 2668 | ||
| 2669 | static DEFINE_MUTEX(cgroup_cft_mutex); | ||
| 2670 | |||
| 2671 | static void cgroup_cfts_prepare(void) | ||
| 2672 | __acquires(&cgroup_cft_mutex) __acquires(&cgroup_mutex) | ||
| 2673 | { | ||
| 2674 | /* | ||
| 2675 | * Thanks to the entanglement with vfs inode locking, we can't walk | ||
| 2676 | * the existing cgroups under cgroup_mutex and create files. | ||
| 2677 | * Instead, we increment reference on all cgroups and build list of | ||
| 2678 | * them using @cgrp->cft_q_node. Grab cgroup_cft_mutex to ensure | ||
| 2679 | * exclusive access to the field. | ||
| 2680 | */ | ||
| 2681 | mutex_lock(&cgroup_cft_mutex); | ||
| 2682 | mutex_lock(&cgroup_mutex); | ||
| 2683 | } | ||
| 2684 | |||
| 2685 | static void cgroup_cfts_commit(struct cgroup_subsys *ss, | ||
| 2686 | const struct cftype *cfts) | ||
| 2687 | __releases(&cgroup_mutex) __releases(&cgroup_cft_mutex) | ||
| 2688 | { | ||
| 2689 | LIST_HEAD(pending); | ||
| 2690 | struct cgroup *cgrp, *n; | ||
| 2691 | int count = 0; | ||
| 2692 | |||
| 2693 | while (cfts[count].name[0] != '\0') | ||
| 2694 | count++; | ||
| 2695 | |||
| 2696 | /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */ | ||
| 2697 | if (cfts && ss->root != &rootnode) { | ||
| 2698 | list_for_each_entry(cgrp, &ss->root->allcg_list, allcg_node) { | ||
| 2699 | dget(cgrp->dentry); | ||
| 2700 | list_add_tail(&cgrp->cft_q_node, &pending); | ||
| 2701 | } | ||
| 2702 | } | ||
| 2703 | |||
| 2704 | mutex_unlock(&cgroup_mutex); | ||
| 2705 | |||
| 2706 | /* | ||
| 2707 | * All new cgroups will see @cfts update on @ss->cftsets. Add/rm | ||
| 2708 | * files for all cgroups which were created before. | ||
| 2709 | */ | ||
| 2710 | list_for_each_entry_safe(cgrp, n, &pending, cft_q_node) { | ||
| 2711 | struct inode *inode = cgrp->dentry->d_inode; | ||
| 2712 | |||
| 2713 | mutex_lock(&inode->i_mutex); | ||
| 2714 | mutex_lock(&cgroup_mutex); | ||
| 2715 | if (!cgroup_is_removed(cgrp)) | ||
| 2716 | cgroup_add_files(cgrp, ss, cfts, count); | ||
| 2717 | mutex_unlock(&cgroup_mutex); | ||
| 2718 | mutex_unlock(&inode->i_mutex); | ||
| 2719 | |||
| 2720 | list_del_init(&cgrp->cft_q_node); | ||
| 2721 | dput(cgrp->dentry); | ||
| 2722 | } | ||
| 2723 | |||
| 2724 | mutex_unlock(&cgroup_cft_mutex); | ||
| 2725 | } | ||
| 2726 | |||
| 2727 | /** | ||
| 2728 | * cgroup_add_cftypes - add an array of cftypes to a subsystem | ||
| 2729 | * @ss: target cgroup subsystem | ||
| 2730 | * @cfts: zero-length name terminated array of cftypes | ||
| 2731 | * | ||
| 2732 | * Register @cfts to @ss. Files described by @cfts are created for all | ||
| 2733 | * existing cgroups to which @ss is attached and all future cgroups will | ||
| 2734 | * have them too. This function can be called anytime whether @ss is | ||
| 2735 | * attached or not. | ||
| 2736 | * | ||
| 2737 | * Returns 0 on successful registration, -errno on failure. Note that this | ||
| 2738 | * function currently returns 0 as long as @cfts registration is successful | ||
| 2739 | * even if some file creation attempts on existing cgroups fail. | ||
| 2740 | */ | ||
| 2741 | int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts) | ||
| 2742 | { | ||
| 2743 | struct cftype_set *set; | ||
| 2744 | |||
| 2745 | set = kzalloc(sizeof(*set), GFP_KERNEL); | ||
| 2746 | if (!set) | ||
| 2747 | return -ENOMEM; | ||
| 2748 | |||
| 2749 | cgroup_cfts_prepare(); | ||
| 2750 | set->cfts = cfts; | ||
| 2751 | list_add_tail(&set->node, &ss->cftsets); | ||
| 2752 | cgroup_cfts_commit(ss, cfts); | ||
| 2753 | |||
| 2754 | return 0; | ||
| 2755 | } | ||
| 2756 | EXPORT_SYMBOL_GPL(cgroup_add_cftypes); | ||
| 2757 | |||
| 2663 | /** | 2758 | /** |
| 2664 | * cgroup_task_count - count the number of tasks in a cgroup. | 2759 | * cgroup_task_count - count the number of tasks in a cgroup. |
| 2665 | * @cgrp: the cgroup in question | 2760 | * @cgrp: the cgroup in question |
| @@ -3660,10 +3755,25 @@ static int cgroup_populate_dir(struct cgroup *cgrp) | |||
| 3660 | return err; | 3755 | return err; |
| 3661 | } | 3756 | } |
| 3662 | 3757 | ||
| 3758 | /* process cftsets of each subsystem */ | ||
| 3663 | for_each_subsys(cgrp->root, ss) { | 3759 | for_each_subsys(cgrp->root, ss) { |
| 3760 | struct cftype_set *set; | ||
| 3761 | |||
| 3664 | if (ss->populate && (err = ss->populate(ss, cgrp)) < 0) | 3762 | if (ss->populate && (err = ss->populate(ss, cgrp)) < 0) |
| 3665 | return err; | 3763 | return err; |
| 3764 | |||
| 3765 | list_for_each_entry(set, &ss->cftsets, node) { | ||
| 3766 | const struct cftype *cft; | ||
| 3767 | |||
| 3768 | for (cft = set->cfts; cft->name[0] != '\0'; cft++) { | ||
| 3769 | err = cgroup_add_file(cgrp, ss, cft); | ||
| 3770 | if (err) | ||
| 3771 | pr_warning("cgroup_populate_dir: failed to create %s, err=%d\n", | ||
| 3772 | cft->name, err); | ||
| 3773 | } | ||
| 3774 | } | ||
| 3666 | } | 3775 | } |
| 3776 | |||
| 3667 | /* This cgroup is ready now */ | 3777 | /* This cgroup is ready now */ |
| 3668 | for_each_subsys(cgrp->root, ss) { | 3778 | for_each_subsys(cgrp->root, ss) { |
| 3669 | struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; | 3779 | struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; |
| @@ -4034,12 +4144,29 @@ again: | |||
| 4034 | return 0; | 4144 | return 0; |
| 4035 | } | 4145 | } |
| 4036 | 4146 | ||
| 4147 | static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss) | ||
| 4148 | { | ||
| 4149 | INIT_LIST_HEAD(&ss->cftsets); | ||
| 4150 | |||
| 4151 | /* | ||
| 4152 | * base_cftset is embedded in subsys itself, no need to worry about | ||
| 4153 | * deregistration. | ||
| 4154 | */ | ||
| 4155 | if (ss->base_cftypes) { | ||
| 4156 | ss->base_cftset.cfts = ss->base_cftypes; | ||
| 4157 | list_add_tail(&ss->base_cftset.node, &ss->cftsets); | ||
| 4158 | } | ||
| 4159 | } | ||
| 4160 | |||
| 4037 | static void __init cgroup_init_subsys(struct cgroup_subsys *ss) | 4161 | static void __init cgroup_init_subsys(struct cgroup_subsys *ss) |
| 4038 | { | 4162 | { |
| 4039 | struct cgroup_subsys_state *css; | 4163 | struct cgroup_subsys_state *css; |
| 4040 | 4164 | ||
| 4041 | printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name); | 4165 | printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name); |
| 4042 | 4166 | ||
| 4167 | /* init base cftset */ | ||
| 4168 | cgroup_init_cftsets(ss); | ||
| 4169 | |||
| 4043 | /* Create the top cgroup state for this subsystem */ | 4170 | /* Create the top cgroup state for this subsystem */ |
| 4044 | list_add(&ss->sibling, &rootnode.subsys_list); | 4171 | list_add(&ss->sibling, &rootnode.subsys_list); |
| 4045 | ss->root = &rootnode; | 4172 | ss->root = &rootnode; |
| @@ -4109,6 +4236,9 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) | |||
| 4109 | return 0; | 4236 | return 0; |
| 4110 | } | 4237 | } |
| 4111 | 4238 | ||
| 4239 | /* init base cftset */ | ||
| 4240 | cgroup_init_cftsets(ss); | ||
| 4241 | |||
| 4112 | /* | 4242 | /* |
| 4113 | * need to register a subsys id before anything else - for example, | 4243 | * need to register a subsys id before anything else - for example, |
| 4114 | * init_cgroup_css needs it. | 4244 | * init_cgroup_css needs it. |
