diff options
author | Aristeu Rozanski <aris@redhat.com> | 2012-08-23 16:53:29 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2012-08-24 18:55:33 -0400 |
commit | 13af07df9b7e49f1987cf36aa048dc6c49d0f93d (patch) | |
tree | ae726e287583d98c6e3f85a31d574e5d48075861 | |
parent | 38f38657444d15e1a8574eae80ed3de9f501737a (diff) |
cgroup: revise how we re-populate root directory
When remounting cgroupfs with some subsystems added to it and some
removed, cgroup will remove all the files in root directory and then
re-popluate it.
What I'm doing here is, only remove files which belong to subsystems that
are to be unbinded, and only create files for newly-added subsystems.
The purpose is to have all other files untouched.
This is a preparation for cgroup xattr support.
v7:
- checkpatch warnings fixed
v6:
- no changes
v5:
- no changes
v4:
- refactored cgroup_clear_directory() to not use cgroup_rm_file()
- instead of going thru the list of files, get the file list using the
subsystems
- use 'subsys_mask' instead of {added,removed}_bits and made
cgroup_populate_dir() to match the parameters with cgroup_clear_directory()
v3:
- refresh patches after recent refactoring
Original-patch-by: Li Zefan <lizefan@huawei.com>
Cc: Li Zefan <lizefan@huawei.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Hillf Danton <dhillf@gmail.com>
Cc: Lennart Poettering <lpoetter@redhat.com>
Signed-off-by: Li Zefan <lizefan@huawei.com>
Signed-off-by: Aristeu Rozanski <aris@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r-- | kernel/cgroup.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 79818507e444..875a7130647c 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -824,7 +824,8 @@ EXPORT_SYMBOL_GPL(cgroup_unlock); | |||
824 | static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); | 824 | static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); |
825 | static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned int); | 825 | static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned int); |
826 | static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry); | 826 | static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry); |
827 | static int cgroup_populate_dir(struct cgroup *cgrp); | 827 | static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files, |
828 | unsigned long subsys_mask); | ||
828 | static const struct inode_operations cgroup_dir_inode_operations; | 829 | static const struct inode_operations cgroup_dir_inode_operations; |
829 | static const struct file_operations proc_cgroupstats_operations; | 830 | static const struct file_operations proc_cgroupstats_operations; |
830 | 831 | ||
@@ -963,12 +964,29 @@ static int cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft) | |||
963 | return -ENOENT; | 964 | return -ENOENT; |
964 | } | 965 | } |
965 | 966 | ||
966 | static void cgroup_clear_directory(struct dentry *dir) | 967 | /** |
968 | * cgroup_clear_directory - selective removal of base and subsystem files | ||
969 | * @dir: directory containing the files | ||
970 | * @base_files: true if the base files should be removed | ||
971 | * @subsys_mask: mask of the subsystem ids whose files should be removed | ||
972 | */ | ||
973 | static void cgroup_clear_directory(struct dentry *dir, bool base_files, | ||
974 | unsigned long subsys_mask) | ||
967 | { | 975 | { |
968 | struct cgroup *cgrp = __d_cgrp(dir); | 976 | struct cgroup *cgrp = __d_cgrp(dir); |
977 | struct cgroup_subsys *ss; | ||
969 | 978 | ||
970 | while (!list_empty(&cgrp->files)) | 979 | for_each_subsys(cgrp->root, ss) { |
971 | cgroup_rm_file(cgrp, NULL); | 980 | struct cftype_set *set; |
981 | if (!test_bit(ss->subsys_id, &subsys_mask)) | ||
982 | continue; | ||
983 | list_for_each_entry(set, &ss->cftsets, node) | ||
984 | cgroup_rm_file(cgrp, set->cfts); | ||
985 | } | ||
986 | if (base_files) { | ||
987 | while (!list_empty(&cgrp->files)) | ||
988 | cgroup_rm_file(cgrp, NULL); | ||
989 | } | ||
972 | } | 990 | } |
973 | 991 | ||
974 | /* | 992 | /* |
@@ -977,8 +995,9 @@ static void cgroup_clear_directory(struct dentry *dir) | |||
977 | static void cgroup_d_remove_dir(struct dentry *dentry) | 995 | static void cgroup_d_remove_dir(struct dentry *dentry) |
978 | { | 996 | { |
979 | struct dentry *parent; | 997 | struct dentry *parent; |
998 | struct cgroupfs_root *root = dentry->d_sb->s_fs_info; | ||
980 | 999 | ||
981 | cgroup_clear_directory(dentry); | 1000 | cgroup_clear_directory(dentry, true, root->subsys_bits); |
982 | 1001 | ||
983 | parent = dentry->d_parent; | 1002 | parent = dentry->d_parent; |
984 | spin_lock(&parent->d_lock); | 1003 | spin_lock(&parent->d_lock); |
@@ -1339,6 +1358,7 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) | |||
1339 | struct cgroupfs_root *root = sb->s_fs_info; | 1358 | struct cgroupfs_root *root = sb->s_fs_info; |
1340 | struct cgroup *cgrp = &root->top_cgroup; | 1359 | struct cgroup *cgrp = &root->top_cgroup; |
1341 | struct cgroup_sb_opts opts; | 1360 | struct cgroup_sb_opts opts; |
1361 | unsigned long added_bits, removed_bits; | ||
1342 | 1362 | ||
1343 | mutex_lock(&cgrp->dentry->d_inode->i_mutex); | 1363 | mutex_lock(&cgrp->dentry->d_inode->i_mutex); |
1344 | mutex_lock(&cgroup_mutex); | 1364 | mutex_lock(&cgroup_mutex); |
@@ -1354,6 +1374,9 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) | |||
1354 | pr_warning("cgroup: option changes via remount are deprecated (pid=%d comm=%s)\n", | 1374 | pr_warning("cgroup: option changes via remount are deprecated (pid=%d comm=%s)\n", |
1355 | task_tgid_nr(current), current->comm); | 1375 | task_tgid_nr(current), current->comm); |
1356 | 1376 | ||
1377 | added_bits = opts.subsys_bits & ~root->subsys_bits; | ||
1378 | removed_bits = root->subsys_bits & ~opts.subsys_bits; | ||
1379 | |||
1357 | /* Don't allow flags or name to change at remount */ | 1380 | /* Don't allow flags or name to change at remount */ |
1358 | if (opts.flags != root->flags || | 1381 | if (opts.flags != root->flags || |
1359 | (opts.name && strcmp(opts.name, root->name))) { | 1382 | (opts.name && strcmp(opts.name, root->name))) { |
@@ -1369,8 +1392,9 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) | |||
1369 | } | 1392 | } |
1370 | 1393 | ||
1371 | /* clear out any existing files and repopulate subsystem files */ | 1394 | /* clear out any existing files and repopulate subsystem files */ |
1372 | cgroup_clear_directory(cgrp->dentry); | 1395 | cgroup_clear_directory(cgrp->dentry, false, removed_bits); |
1373 | cgroup_populate_dir(cgrp); | 1396 | /* re-populate subsystem files */ |
1397 | cgroup_populate_dir(cgrp, false, added_bits); | ||
1374 | 1398 | ||
1375 | if (opts.release_agent) | 1399 | if (opts.release_agent) |
1376 | strcpy(root->release_agent_path, opts.release_agent); | 1400 | strcpy(root->release_agent_path, opts.release_agent); |
@@ -1669,7 +1693,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, | |||
1669 | BUG_ON(root->number_of_cgroups != 1); | 1693 | BUG_ON(root->number_of_cgroups != 1); |
1670 | 1694 | ||
1671 | cred = override_creds(&init_cred); | 1695 | cred = override_creds(&init_cred); |
1672 | cgroup_populate_dir(root_cgrp); | 1696 | cgroup_populate_dir(root_cgrp, true, root->subsys_bits); |
1673 | revert_creds(cred); | 1697 | revert_creds(cred); |
1674 | mutex_unlock(&cgroup_root_mutex); | 1698 | mutex_unlock(&cgroup_root_mutex); |
1675 | mutex_unlock(&cgroup_mutex); | 1699 | mutex_unlock(&cgroup_mutex); |
@@ -3843,18 +3867,29 @@ static struct cftype files[] = { | |||
3843 | { } /* terminate */ | 3867 | { } /* terminate */ |
3844 | }; | 3868 | }; |
3845 | 3869 | ||
3846 | static int cgroup_populate_dir(struct cgroup *cgrp) | 3870 | /** |
3871 | * cgroup_populate_dir - selectively creation of files in a directory | ||
3872 | * @cgrp: target cgroup | ||
3873 | * @base_files: true if the base files should be added | ||
3874 | * @subsys_mask: mask of the subsystem ids whose files should be added | ||
3875 | */ | ||
3876 | static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files, | ||
3877 | unsigned long subsys_mask) | ||
3847 | { | 3878 | { |
3848 | int err; | 3879 | int err; |
3849 | struct cgroup_subsys *ss; | 3880 | struct cgroup_subsys *ss; |
3850 | 3881 | ||
3851 | err = cgroup_addrm_files(cgrp, NULL, files, true); | 3882 | if (base_files) { |
3852 | if (err < 0) | 3883 | err = cgroup_addrm_files(cgrp, NULL, files, true); |
3853 | return err; | 3884 | if (err < 0) |
3885 | return err; | ||
3886 | } | ||
3854 | 3887 | ||
3855 | /* process cftsets of each subsystem */ | 3888 | /* process cftsets of each subsystem */ |
3856 | for_each_subsys(cgrp->root, ss) { | 3889 | for_each_subsys(cgrp->root, ss) { |
3857 | struct cftype_set *set; | 3890 | struct cftype_set *set; |
3891 | if (!test_bit(ss->subsys_id, &subsys_mask)) | ||
3892 | continue; | ||
3858 | 3893 | ||
3859 | list_for_each_entry(set, &ss->cftsets, node) | 3894 | list_for_each_entry(set, &ss->cftsets, node) |
3860 | cgroup_addrm_files(cgrp, ss, set->cfts, true); | 3895 | cgroup_addrm_files(cgrp, ss, set->cfts, true); |
@@ -3988,7 +4023,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, | |||
3988 | 4023 | ||
3989 | list_add_tail(&cgrp->allcg_node, &root->allcg_list); | 4024 | list_add_tail(&cgrp->allcg_node, &root->allcg_list); |
3990 | 4025 | ||
3991 | err = cgroup_populate_dir(cgrp); | 4026 | err = cgroup_populate_dir(cgrp, true, root->subsys_bits); |
3992 | /* If err < 0, we have a half-filled directory - oh well ;) */ | 4027 | /* If err < 0, we have a half-filled directory - oh well ;) */ |
3993 | 4028 | ||
3994 | mutex_unlock(&cgroup_mutex); | 4029 | mutex_unlock(&cgroup_mutex); |