aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorLi Zefan <lizefan@huawei.com>2013-06-18 06:48:37 -0400
committerTejun Heo <tj@kernel.org>2013-06-18 14:14:22 -0400
commite8c82d20a9f729cf4b9f73043f7fd4e0872bebfd (patch)
treefc45f039baee86a1b867d6c55cb05ea7e8c47288 /kernel/cgroup.c
parent794611a1dfcb055d7d41ce133378dd8197d73e38 (diff)
cgroup: convert cgroup_cft_commit() to use cgroup_for_each_descendant_pre()
We used root->allcg_list to iterate cgroup hierarchy because at that time cgroup_for_each_descendant_pre() hasn't been invented. tj: In cgroup_cfts_commit(), s/@serial_nr/@update_upto/, move the assignment right above releasing cgroup_mutex and explain what's going on there. Signed-off-by: Li Zefan <lizefan@huawei.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c80
1 files changed, 44 insertions, 36 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index e6571ca822a0..0ed7d8db6508 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1399,7 +1399,6 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
1399 INIT_LIST_HEAD(&cgrp->children); 1399 INIT_LIST_HEAD(&cgrp->children);
1400 INIT_LIST_HEAD(&cgrp->files); 1400 INIT_LIST_HEAD(&cgrp->files);
1401 INIT_LIST_HEAD(&cgrp->cset_links); 1401 INIT_LIST_HEAD(&cgrp->cset_links);
1402 INIT_LIST_HEAD(&cgrp->allcg_node);
1403 INIT_LIST_HEAD(&cgrp->release_list); 1402 INIT_LIST_HEAD(&cgrp->release_list);
1404 INIT_LIST_HEAD(&cgrp->pidlists); 1403 INIT_LIST_HEAD(&cgrp->pidlists);
1405 mutex_init(&cgrp->pidlist_mutex); 1404 mutex_init(&cgrp->pidlist_mutex);
@@ -1414,12 +1413,10 @@ static void init_cgroup_root(struct cgroupfs_root *root)
1414 1413
1415 INIT_LIST_HEAD(&root->subsys_list); 1414 INIT_LIST_HEAD(&root->subsys_list);
1416 INIT_LIST_HEAD(&root->root_list); 1415 INIT_LIST_HEAD(&root->root_list);
1417 INIT_LIST_HEAD(&root->allcg_list);
1418 root->number_of_cgroups = 1; 1416 root->number_of_cgroups = 1;
1419 cgrp->root = root; 1417 cgrp->root = root;
1420 cgrp->name = &root_cgroup_name; 1418 cgrp->name = &root_cgroup_name;
1421 init_cgroup_housekeeping(cgrp); 1419 init_cgroup_housekeeping(cgrp);
1422 list_add_tail(&cgrp->allcg_node, &root->allcg_list);
1423} 1420}
1424 1421
1425static int cgroup_init_root_id(struct cgroupfs_root *root) 1422static int cgroup_init_root_id(struct cgroupfs_root *root)
@@ -2785,65 +2782,78 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
2785 return ret; 2782 return ret;
2786} 2783}
2787 2784
2788static DEFINE_MUTEX(cgroup_cft_mutex);
2789
2790static void cgroup_cfts_prepare(void) 2785static void cgroup_cfts_prepare(void)
2791 __acquires(&cgroup_cft_mutex) __acquires(&cgroup_mutex) 2786 __acquires(&cgroup_mutex)
2792{ 2787{
2793 /* 2788 /*
2794 * Thanks to the entanglement with vfs inode locking, we can't walk 2789 * Thanks to the entanglement with vfs inode locking, we can't walk
2795 * the existing cgroups under cgroup_mutex and create files. 2790 * the existing cgroups under cgroup_mutex and create files.
2796 * Instead, we increment reference on all cgroups and build list of 2791 * Instead, we use cgroup_for_each_descendant_pre() and drop RCU
2797 * them using @cgrp->cft_q_node. Grab cgroup_cft_mutex to ensure 2792 * read lock before calling cgroup_addrm_files().
2798 * exclusive access to the field.
2799 */ 2793 */
2800 mutex_lock(&cgroup_cft_mutex);
2801 mutex_lock(&cgroup_mutex); 2794 mutex_lock(&cgroup_mutex);
2802} 2795}
2803 2796
2804static void cgroup_cfts_commit(struct cgroup_subsys *ss, 2797static void cgroup_cfts_commit(struct cgroup_subsys *ss,
2805 struct cftype *cfts, bool is_add) 2798 struct cftype *cfts, bool is_add)
2806 __releases(&cgroup_mutex) __releases(&cgroup_cft_mutex) 2799 __releases(&cgroup_mutex)
2807{ 2800{
2808 LIST_HEAD(pending); 2801 LIST_HEAD(pending);
2809 struct cgroup *cgrp, *n; 2802 struct cgroup *cgrp, *root = &ss->root->top_cgroup;
2810 struct super_block *sb = ss->root->sb; 2803 struct super_block *sb = ss->root->sb;
2804 struct dentry *prev = NULL;
2805 struct inode *inode;
2806 u64 update_upto;
2811 2807
2812 /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */ 2808 /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */
2813 if (cfts && ss->root != &rootnode && 2809 if (!cfts || ss->root == &rootnode ||
2814 atomic_inc_not_zero(sb->s_active)) { 2810 !atomic_inc_not_zero(&sb->s_active)) {
2815 list_for_each_entry(cgrp, &ss->root->allcg_list, allcg_node) { 2811 mutex_unlock(&cgroup_mutex);
2816 dget(cgrp->dentry); 2812 return;
2817 list_add_tail(&cgrp->cft_q_node, &pending);
2818 }
2819 } else {
2820 sb = NULL;
2821 } 2813 }
2822 2814
2823 mutex_unlock(&cgroup_mutex);
2824
2825 /* 2815 /*
2826 * All new cgroups will see @cfts update on @ss->cftsets. Add/rm 2816 * All cgroups which are created after we drop cgroup_mutex will
2827 * files for all cgroups which were created before. 2817 * have the updated set of files, so we only need to update the
2818 * cgroups created before the current @cgroup_serial_nr_cursor.
2828 */ 2819 */
2829 list_for_each_entry_safe(cgrp, n, &pending, cft_q_node) { 2820 update_upto = atomic64_read(&cgroup_serial_nr_cursor);
2830 struct inode *inode = cgrp->dentry->d_inode; 2821
2822 mutex_unlock(&cgroup_mutex);
2823
2824 /* @root always needs to be updated */
2825 inode = root->dentry->d_inode;
2826 mutex_lock(&inode->i_mutex);
2827 mutex_lock(&cgroup_mutex);
2828 cgroup_addrm_files(root, ss, cfts, is_add);
2829 mutex_unlock(&cgroup_mutex);
2830 mutex_unlock(&inode->i_mutex);
2831
2832 /* add/rm files for all cgroups created before */
2833 rcu_read_lock();
2834 cgroup_for_each_descendant_pre(cgrp, root) {
2835 if (cgroup_is_dead(cgrp))
2836 continue;
2837
2838 inode = cgrp->dentry->d_inode;
2839 dget(cgrp->dentry);
2840 rcu_read_unlock();
2841
2842 dput(prev);
2843 prev = cgrp->dentry;
2831 2844
2832 mutex_lock(&inode->i_mutex); 2845 mutex_lock(&inode->i_mutex);
2833 mutex_lock(&cgroup_mutex); 2846 mutex_lock(&cgroup_mutex);
2834 if (!cgroup_is_dead(cgrp)) 2847 if (cgrp->serial_nr <= update_upto && !cgroup_is_dead(cgrp))
2835 cgroup_addrm_files(cgrp, ss, cfts, is_add); 2848 cgroup_addrm_files(cgrp, ss, cfts, is_add);
2836 mutex_unlock(&cgroup_mutex); 2849 mutex_unlock(&cgroup_mutex);
2837 mutex_unlock(&inode->i_mutex); 2850 mutex_unlock(&inode->i_mutex);
2838 2851
2839 list_del_init(&cgrp->cft_q_node); 2852 rcu_read_lock();
2840 dput(cgrp->dentry);
2841 } 2853 }
2842 2854 rcu_read_unlock();
2843 if (sb) 2855 dput(prev);
2844 deactivate_super(sb); 2856 deactivate_super(sb);
2845
2846 mutex_unlock(&cgroup_cft_mutex);
2847} 2857}
2848 2858
2849/** 2859/**
@@ -4320,7 +4330,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
4320 cgrp->serial_nr = atomic64_inc_return(&cgroup_serial_nr_cursor); 4330 cgrp->serial_nr = atomic64_inc_return(&cgroup_serial_nr_cursor);
4321 4331
4322 /* allocation complete, commit to creation */ 4332 /* allocation complete, commit to creation */
4323 list_add_tail(&cgrp->allcg_node, &root->allcg_list);
4324 list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children); 4333 list_add_tail_rcu(&cgrp->sibling, &cgrp->parent->children);
4325 root->number_of_cgroups++; 4334 root->number_of_cgroups++;
4326 4335
@@ -4559,7 +4568,6 @@ static void cgroup_offline_fn(struct work_struct *work)
4559 4568
4560 /* delete this cgroup from parent->children */ 4569 /* delete this cgroup from parent->children */
4561 list_del_rcu(&cgrp->sibling); 4570 list_del_rcu(&cgrp->sibling);
4562 list_del_init(&cgrp->allcg_node);
4563 4571
4564 dput(d); 4572 dput(d);
4565 4573