aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-cgroup.c2
-rw-r--r--include/linux/cgroup.h8
-rw-r--r--kernel/cgroup.c78
3 files changed, 51 insertions, 37 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 79fd9f4fadb7..34063739745b 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1128,7 +1128,7 @@ void blkcg_policy_unregister(struct blkcg_policy *pol)
1128 1128
1129 /* kill the intf files first */ 1129 /* kill the intf files first */
1130 if (pol->cftypes) 1130 if (pol->cftypes)
1131 cgroup_rm_cftypes(&blkio_subsys, pol->cftypes); 1131 cgroup_rm_cftypes(pol->cftypes);
1132 1132
1133 /* unregister and update blkgs */ 1133 /* unregister and update blkgs */
1134 blkcg_policy[pol->plid] = NULL; 1134 blkcg_policy[pol->plid] = NULL;
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 9c2b9dd9121d..5db8138a0482 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -429,6 +429,12 @@ struct cftype {
429 /* CFTYPE_* flags */ 429 /* CFTYPE_* flags */
430 unsigned int flags; 430 unsigned int flags;
431 431
432 /*
433 * The subsys this file belongs to. Initialized automatically
434 * during registration. NULL for cgroup core files.
435 */
436 struct cgroup_subsys *ss;
437
432 int (*open)(struct inode *inode, struct file *file); 438 int (*open)(struct inode *inode, struct file *file);
433 ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft, 439 ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft,
434 struct file *file, 440 struct file *file,
@@ -542,7 +548,7 @@ static inline const char *cgroup_name(const struct cgroup *cgrp)
542} 548}
543 549
544int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); 550int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
545int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); 551int cgroup_rm_cftypes(struct cftype *cfts);
546 552
547bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor); 553bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor);
548 554
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 271d9a5cde5f..c4bc8dac3b1d 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -219,8 +219,8 @@ static struct cftype cgroup_base_files[];
219 219
220static void cgroup_offline_fn(struct work_struct *work); 220static void cgroup_offline_fn(struct work_struct *work);
221static int cgroup_destroy_locked(struct cgroup *cgrp); 221static int cgroup_destroy_locked(struct cgroup *cgrp);
222static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, 222static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
223 struct cftype cfts[], bool is_add); 223 bool is_add);
224 224
225/* convenient tests for these bits */ 225/* convenient tests for these bits */
226static inline bool cgroup_is_dead(const struct cgroup *cgrp) 226static inline bool cgroup_is_dead(const struct cgroup *cgrp)
@@ -974,7 +974,7 @@ static void cgroup_clear_dir(struct cgroup *cgrp, unsigned long subsys_mask)
974 if (!test_bit(i, &subsys_mask)) 974 if (!test_bit(i, &subsys_mask))
975 continue; 975 continue;
976 list_for_each_entry(set, &ss->cftsets, node) 976 list_for_each_entry(set, &ss->cftsets, node)
977 cgroup_addrm_files(cgrp, NULL, set->cfts, false); 977 cgroup_addrm_files(cgrp, set->cfts, false);
978 } 978 }
979} 979}
980 980
@@ -1623,7 +1623,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
1623 */ 1623 */
1624 cred = override_creds(&init_cred); 1624 cred = override_creds(&init_cred);
1625 1625
1626 ret = cgroup_addrm_files(root_cgrp, NULL, cgroup_base_files, true); 1626 ret = cgroup_addrm_files(root_cgrp, cgroup_base_files, true);
1627 if (ret) 1627 if (ret)
1628 goto rm_base_files; 1628 goto rm_base_files;
1629 1629
@@ -1681,7 +1681,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
1681 1681
1682 rm_base_files: 1682 rm_base_files:
1683 free_cgrp_cset_links(&tmp_links); 1683 free_cgrp_cset_links(&tmp_links);
1684 cgroup_addrm_files(&root->top_cgroup, NULL, cgroup_base_files, false); 1684 cgroup_addrm_files(&root->top_cgroup, cgroup_base_files, false);
1685 revert_creds(cred); 1685 revert_creds(cred);
1686 unlock_drop: 1686 unlock_drop:
1687 cgroup_exit_root_id(root); 1687 cgroup_exit_root_id(root);
@@ -2694,8 +2694,7 @@ static umode_t cgroup_file_mode(const struct cftype *cft)
2694 return mode; 2694 return mode;
2695} 2695}
2696 2696
2697static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys, 2697static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft)
2698 struct cftype *cft)
2699{ 2698{
2700 struct dentry *dir = cgrp->dentry; 2699 struct dentry *dir = cgrp->dentry;
2701 struct cgroup *parent = __d_cgrp(dir); 2700 struct cgroup *parent = __d_cgrp(dir);
@@ -2705,8 +2704,8 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
2705 umode_t mode; 2704 umode_t mode;
2706 char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 }; 2705 char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
2707 2706
2708 if (subsys && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) { 2707 if (cft->ss && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) {
2709 strcpy(name, subsys->name); 2708 strcpy(name, cft->ss->name);
2710 strcat(name, "."); 2709 strcat(name, ".");
2711 } 2710 }
2712 strcat(name, cft->name); 2711 strcat(name, cft->name);
@@ -2743,17 +2742,16 @@ out:
2743/** 2742/**
2744 * cgroup_addrm_files - add or remove files to a cgroup directory 2743 * cgroup_addrm_files - add or remove files to a cgroup directory
2745 * @cgrp: the target cgroup 2744 * @cgrp: the target cgroup
2746 * @subsys: the subsystem of files to be added
2747 * @cfts: array of cftypes to be added 2745 * @cfts: array of cftypes to be added
2748 * @is_add: whether to add or remove 2746 * @is_add: whether to add or remove
2749 * 2747 *
2750 * Depending on @is_add, add or remove files defined by @cfts on @cgrp. 2748 * Depending on @is_add, add or remove files defined by @cfts on @cgrp.
2751 * All @cfts should belong to @subsys. For removals, this function never 2749 * For removals, this function never fails. If addition fails, this
2752 * fails. If addition fails, this function doesn't remove files already 2750 * function doesn't remove files already added. The caller is responsible
2753 * added. The caller is responsible for cleaning up. 2751 * for cleaning up.
2754 */ 2752 */
2755static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, 2753static int cgroup_addrm_files(struct cgroup *cgrp, struct cftype cfts[],
2756 struct cftype cfts[], bool is_add) 2754 bool is_add)
2757{ 2755{
2758 struct cftype *cft; 2756 struct cftype *cft;
2759 int ret; 2757 int ret;
@@ -2771,7 +2769,7 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
2771 continue; 2769 continue;
2772 2770
2773 if (is_add) { 2771 if (is_add) {
2774 ret = cgroup_add_file(cgrp, subsys, cft); 2772 ret = cgroup_add_file(cgrp, cft);
2775 if (ret) { 2773 if (ret) {
2776 pr_warn("cgroup_addrm_files: failed to add %s, err=%d\n", 2774 pr_warn("cgroup_addrm_files: failed to add %s, err=%d\n",
2777 cft->name, ret); 2775 cft->name, ret);
@@ -2796,11 +2794,11 @@ static void cgroup_cfts_prepare(void)
2796 mutex_lock(&cgroup_mutex); 2794 mutex_lock(&cgroup_mutex);
2797} 2795}
2798 2796
2799static int cgroup_cfts_commit(struct cgroup_subsys *ss, 2797static int cgroup_cfts_commit(struct cftype *cfts, bool is_add)
2800 struct cftype *cfts, bool is_add)
2801 __releases(&cgroup_mutex) 2798 __releases(&cgroup_mutex)
2802{ 2799{
2803 LIST_HEAD(pending); 2800 LIST_HEAD(pending);
2801 struct cgroup_subsys *ss = cfts[0].ss;
2804 struct cgroup *cgrp, *root = &ss->root->top_cgroup; 2802 struct cgroup *cgrp, *root = &ss->root->top_cgroup;
2805 struct super_block *sb = ss->root->sb; 2803 struct super_block *sb = ss->root->sb;
2806 struct dentry *prev = NULL; 2804 struct dentry *prev = NULL;
@@ -2828,7 +2826,7 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss,
2828 inode = root->dentry->d_inode; 2826 inode = root->dentry->d_inode;
2829 mutex_lock(&inode->i_mutex); 2827 mutex_lock(&inode->i_mutex);
2830 mutex_lock(&cgroup_mutex); 2828 mutex_lock(&cgroup_mutex);
2831 ret = cgroup_addrm_files(root, ss, cfts, is_add); 2829 ret = cgroup_addrm_files(root, cfts, is_add);
2832 mutex_unlock(&cgroup_mutex); 2830 mutex_unlock(&cgroup_mutex);
2833 mutex_unlock(&inode->i_mutex); 2831 mutex_unlock(&inode->i_mutex);
2834 2832
@@ -2851,7 +2849,7 @@ static int cgroup_cfts_commit(struct cgroup_subsys *ss,
2851 mutex_lock(&inode->i_mutex); 2849 mutex_lock(&inode->i_mutex);
2852 mutex_lock(&cgroup_mutex); 2850 mutex_lock(&cgroup_mutex);
2853 if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp)) 2851 if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp))
2854 ret = cgroup_addrm_files(cgrp, ss, cfts, is_add); 2852 ret = cgroup_addrm_files(cgrp, cfts, is_add);
2855 mutex_unlock(&cgroup_mutex); 2853 mutex_unlock(&cgroup_mutex);
2856 mutex_unlock(&inode->i_mutex); 2854 mutex_unlock(&inode->i_mutex);
2857 2855
@@ -2883,51 +2881,56 @@ out_deact:
2883int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) 2881int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
2884{ 2882{
2885 struct cftype_set *set; 2883 struct cftype_set *set;
2884 struct cftype *cft;
2886 int ret; 2885 int ret;
2887 2886
2888 set = kzalloc(sizeof(*set), GFP_KERNEL); 2887 set = kzalloc(sizeof(*set), GFP_KERNEL);
2889 if (!set) 2888 if (!set)
2890 return -ENOMEM; 2889 return -ENOMEM;
2891 2890
2891 for (cft = cfts; cft->name[0] != '\0'; cft++)
2892 cft->ss = ss;
2893
2892 cgroup_cfts_prepare(); 2894 cgroup_cfts_prepare();
2893 set->cfts = cfts; 2895 set->cfts = cfts;
2894 list_add_tail(&set->node, &ss->cftsets); 2896 list_add_tail(&set->node, &ss->cftsets);
2895 ret = cgroup_cfts_commit(ss, cfts, true); 2897 ret = cgroup_cfts_commit(cfts, true);
2896 if (ret) 2898 if (ret)
2897 cgroup_rm_cftypes(ss, cfts); 2899 cgroup_rm_cftypes(cfts);
2898 return ret; 2900 return ret;
2899} 2901}
2900EXPORT_SYMBOL_GPL(cgroup_add_cftypes); 2902EXPORT_SYMBOL_GPL(cgroup_add_cftypes);
2901 2903
2902/** 2904/**
2903 * cgroup_rm_cftypes - remove an array of cftypes from a subsystem 2905 * cgroup_rm_cftypes - remove an array of cftypes from a subsystem
2904 * @ss: target cgroup subsystem
2905 * @cfts: zero-length name terminated array of cftypes 2906 * @cfts: zero-length name terminated array of cftypes
2906 * 2907 *
2907 * Unregister @cfts from @ss. Files described by @cfts are removed from 2908 * Unregister @cfts. Files described by @cfts are removed from all
2908 * all existing cgroups to which @ss is attached and all future cgroups 2909 * existing cgroups and all future cgroups won't have them either. This
2909 * won't have them either. This function can be called anytime whether @ss 2910 * function can be called anytime whether @cfts' subsys is attached or not.
2910 * is attached or not.
2911 * 2911 *
2912 * Returns 0 on successful unregistration, -ENOENT if @cfts is not 2912 * Returns 0 on successful unregistration, -ENOENT if @cfts is not
2913 * registered with @ss. 2913 * registered.
2914 */ 2914 */
2915int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) 2915int cgroup_rm_cftypes(struct cftype *cfts)
2916{ 2916{
2917 struct cftype_set *set; 2917 struct cftype_set *set;
2918 2918
2919 if (!cfts || !cfts[0].ss)
2920 return -ENOENT;
2921
2919 cgroup_cfts_prepare(); 2922 cgroup_cfts_prepare();
2920 2923
2921 list_for_each_entry(set, &ss->cftsets, node) { 2924 list_for_each_entry(set, &cfts[0].ss->cftsets, node) {
2922 if (set->cfts == cfts) { 2925 if (set->cfts == cfts) {
2923 list_del(&set->node); 2926 list_del(&set->node);
2924 kfree(set); 2927 kfree(set);
2925 cgroup_cfts_commit(ss, cfts, false); 2928 cgroup_cfts_commit(cfts, false);
2926 return 0; 2929 return 0;
2927 } 2930 }
2928 } 2931 }
2929 2932
2930 cgroup_cfts_commit(ss, NULL, false); 2933 cgroup_cfts_commit(NULL, false);
2931 return -ENOENT; 2934 return -ENOENT;
2932} 2935}
2933 2936
@@ -4148,7 +4151,7 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask)
4148 continue; 4151 continue;
4149 4152
4150 list_for_each_entry(set, &ss->cftsets, node) { 4153 list_for_each_entry(set, &ss->cftsets, node) {
4151 ret = cgroup_addrm_files(cgrp, ss, set->cfts, true); 4154 ret = cgroup_addrm_files(cgrp, set->cfts, true);
4152 if (ret < 0) 4155 if (ret < 0)
4153 goto err; 4156 goto err;
4154 } 4157 }
@@ -4377,7 +4380,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4377 4380
4378 idr_replace(&root->cgroup_idr, cgrp, cgrp->id); 4381 idr_replace(&root->cgroup_idr, cgrp, cgrp->id);
4379 4382
4380 err = cgroup_addrm_files(cgrp, NULL, cgroup_base_files, true); 4383 err = cgroup_addrm_files(cgrp, cgroup_base_files, true);
4381 if (err) 4384 if (err)
4382 goto err_destroy; 4385 goto err_destroy;
4383 4386
@@ -4538,7 +4541,7 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
4538 * but we aren't quite done with @cgrp yet, so hold onto it. 4541 * but we aren't quite done with @cgrp yet, so hold onto it.
4539 */ 4542 */
4540 cgroup_clear_dir(cgrp, cgrp->root->subsys_mask); 4543 cgroup_clear_dir(cgrp, cgrp->root->subsys_mask);
4541 cgroup_addrm_files(cgrp, NULL, cgroup_base_files, false); 4544 cgroup_addrm_files(cgrp, cgroup_base_files, false);
4542 dget(d); 4545 dget(d);
4543 cgroup_d_remove_dir(d); 4546 cgroup_d_remove_dir(d);
4544 4547
@@ -4632,6 +4635,11 @@ static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
4632 * deregistration. 4635 * deregistration.
4633 */ 4636 */
4634 if (ss->base_cftypes) { 4637 if (ss->base_cftypes) {
4638 struct cftype *cft;
4639
4640 for (cft = ss->base_cftypes; cft->name[0] != '\0'; cft++)
4641 cft->ss = ss;
4642
4635 ss->base_cftset.cfts = ss->base_cftypes; 4643 ss->base_cftset.cfts = ss->base_cftypes;
4636 list_add_tail(&ss->base_cftset.node, &ss->cftsets); 4644 list_add_tail(&ss->base_cftset.node, &ss->cftsets);
4637 } 4645 }