Commit 3417ae1f authored by Tejun Heo's avatar Tejun Heo

cgroup: remove cgroup_root_mutex

cgroup_root_mutex was added to avoid deadlock involving namespace_sem
via cgroup_show_options().  It added a lot of overhead for the small
purpose of it and, because it's nested under cgroup_mutex, it has very
limited usefulness.  The previous patch made cgroup_show_options() not
use cgroup_root_mutex, so nobody needs it anymore.  Remove it.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Acked-by: default avatarLi Zefan <lizefan@huawei.com>
parent 69e943b7
...@@ -70,18 +70,6 @@ ...@@ -70,18 +70,6 @@
/* /*
* cgroup_mutex is the master lock. Any modification to cgroup or its * cgroup_mutex is the master lock. Any modification to cgroup or its
* hierarchy must be performed while holding it. * hierarchy must be performed while holding it.
*
* cgroup_root_mutex nests inside cgroup_mutex and should be held to modify
* cgroupfs_root of any cgroup hierarchy - subsys list, flags,
* release_agent_path and so on. Modifying requires both cgroup_mutex and
* cgroup_root_mutex. Readers can acquire either of the two. This is to
* break the following locking order cycle.
*
* A. cgroup_mutex -> cred_guard_mutex -> s_type->i_mutex_key -> namespace_sem
* B. namespace_sem -> cgroup_mutex
*
* B happens only through cgroup_show_options() and using cgroup_root_mutex
* breaks it.
*/ */
#ifdef CONFIG_PROVE_RCU #ifdef CONFIG_PROVE_RCU
DEFINE_MUTEX(cgroup_mutex); DEFINE_MUTEX(cgroup_mutex);
...@@ -90,8 +78,6 @@ EXPORT_SYMBOL_GPL(cgroup_mutex); /* only for lockdep */ ...@@ -90,8 +78,6 @@ EXPORT_SYMBOL_GPL(cgroup_mutex); /* only for lockdep */
static DEFINE_MUTEX(cgroup_mutex); static DEFINE_MUTEX(cgroup_mutex);
#endif #endif
static DEFINE_MUTEX(cgroup_root_mutex);
/* /*
* Protects cgroup_subsys->release_agent_path. Modifying it also requires * Protects cgroup_subsys->release_agent_path. Modifying it also requires
* cgroup_mutex. Reading requires either cgroup_mutex or this spinlock. * cgroup_mutex. Reading requires either cgroup_mutex or this spinlock.
...@@ -103,14 +89,6 @@ static DEFINE_SPINLOCK(release_agent_path_lock); ...@@ -103,14 +89,6 @@ static DEFINE_SPINLOCK(release_agent_path_lock);
lockdep_is_held(&cgroup_mutex), \ lockdep_is_held(&cgroup_mutex), \
"cgroup_mutex or RCU read lock required"); "cgroup_mutex or RCU read lock required");
#ifdef CONFIG_LOCKDEP
#define cgroup_assert_mutex_or_root_locked() \
WARN_ON_ONCE(debug_locks && (!lockdep_is_held(&cgroup_mutex) && \
!lockdep_is_held(&cgroup_root_mutex)))
#else
#define cgroup_assert_mutex_or_root_locked() do { } while (0)
#endif
/* /*
* cgroup destruction makes heavy use of work items and there can be a lot * cgroup destruction makes heavy use of work items and there can be a lot
* of concurrent destructions. Use a separate workqueue so that cgroup * of concurrent destructions. Use a separate workqueue so that cgroup
...@@ -154,11 +132,7 @@ static struct cgroup * const cgroup_dummy_top = &cgroup_dummy_root.top_cgroup; ...@@ -154,11 +132,7 @@ static struct cgroup * const cgroup_dummy_top = &cgroup_dummy_root.top_cgroup;
static LIST_HEAD(cgroup_roots); static LIST_HEAD(cgroup_roots);
static int cgroup_root_count; static int cgroup_root_count;
/* /* hierarchy ID allocation and mapping, protected by cgroup_mutex */
* Hierarchy ID allocation and mapping. It follows the same exclusion
* rules as other root ops - both cgroup_mutex and cgroup_root_mutex for
* writes, either for reads.
*/
static DEFINE_IDR(cgroup_hierarchy_idr); static DEFINE_IDR(cgroup_hierarchy_idr);
static struct cgroup_name root_cgroup_name = { .name = "/" }; static struct cgroup_name root_cgroup_name = { .name = "/" };
...@@ -973,7 +947,6 @@ static int rebind_subsystems(struct cgroupfs_root *root, ...@@ -973,7 +947,6 @@ static int rebind_subsystems(struct cgroupfs_root *root,
int i, ret; int i, ret;
BUG_ON(!mutex_is_locked(&cgroup_mutex)); BUG_ON(!mutex_is_locked(&cgroup_mutex));
BUG_ON(!mutex_is_locked(&cgroup_root_mutex));
/* Check that any added subsystems are currently free */ /* Check that any added subsystems are currently free */
for_each_subsys(ss, i) for_each_subsys(ss, i)
...@@ -1246,7 +1219,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) ...@@ -1246,7 +1219,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
mutex_lock(&cgrp->dentry->d_inode->i_mutex); mutex_lock(&cgrp->dentry->d_inode->i_mutex);
mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_mutex);
mutex_lock(&cgroup_root_mutex);
/* See what subsystems are wanted */ /* See what subsystems are wanted */
ret = parse_cgroupfs_options(data, &opts); ret = parse_cgroupfs_options(data, &opts);
...@@ -1288,7 +1260,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) ...@@ -1288,7 +1260,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
out_unlock: out_unlock:
kfree(opts.release_agent); kfree(opts.release_agent);
kfree(opts.name); kfree(opts.name);
mutex_unlock(&cgroup_root_mutex);
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
mutex_unlock(&cgrp->dentry->d_inode->i_mutex); mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
return ret; return ret;
...@@ -1331,7 +1302,6 @@ static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end) ...@@ -1331,7 +1302,6 @@ static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end)
int id; int id;
lockdep_assert_held(&cgroup_mutex); lockdep_assert_held(&cgroup_mutex);
lockdep_assert_held(&cgroup_root_mutex);
id = idr_alloc_cyclic(&cgroup_hierarchy_idr, root, start, end, id = idr_alloc_cyclic(&cgroup_hierarchy_idr, root, start, end,
GFP_KERNEL); GFP_KERNEL);
...@@ -1345,7 +1315,6 @@ static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end) ...@@ -1345,7 +1315,6 @@ static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end)
static void cgroup_exit_root_id(struct cgroupfs_root *root) static void cgroup_exit_root_id(struct cgroupfs_root *root)
{ {
lockdep_assert_held(&cgroup_mutex); lockdep_assert_held(&cgroup_mutex);
lockdep_assert_held(&cgroup_root_mutex);
if (root->hierarchy_id) { if (root->hierarchy_id) {
idr_remove(&cgroup_hierarchy_idr, root->hierarchy_id); idr_remove(&cgroup_hierarchy_idr, root->hierarchy_id);
...@@ -1524,7 +1493,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -1524,7 +1493,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_mutex);
mutex_lock(&cgroup_root_mutex);
root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp, root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp,
0, 1, GFP_KERNEL); 0, 1, GFP_KERNEL);
...@@ -1597,7 +1565,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -1597,7 +1565,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
BUG_ON(!list_empty(&root_cgrp->children)); BUG_ON(!list_empty(&root_cgrp->children));
BUG_ON(root->number_of_cgroups != 1); BUG_ON(root->number_of_cgroups != 1);
mutex_unlock(&cgroup_root_mutex);
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
} else { } else {
...@@ -1628,7 +1595,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -1628,7 +1595,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
revert_creds(cred); revert_creds(cred);
unlock_drop: unlock_drop:
cgroup_exit_root_id(root); cgroup_exit_root_id(root);
mutex_unlock(&cgroup_root_mutex);
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
drop_new_super: drop_new_super:
...@@ -1653,7 +1619,6 @@ static void cgroup_kill_sb(struct super_block *sb) ...@@ -1653,7 +1619,6 @@ static void cgroup_kill_sb(struct super_block *sb)
mutex_lock(&cgrp->dentry->d_inode->i_mutex); mutex_lock(&cgrp->dentry->d_inode->i_mutex);
mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_mutex);
mutex_lock(&cgroup_root_mutex);
/* Rebind all subsystems back to the default hierarchy */ /* Rebind all subsystems back to the default hierarchy */
if (root->flags & CGRP_ROOT_SUBSYS_BOUND) { if (root->flags & CGRP_ROOT_SUBSYS_BOUND) {
...@@ -1682,7 +1647,6 @@ static void cgroup_kill_sb(struct super_block *sb) ...@@ -1682,7 +1647,6 @@ static void cgroup_kill_sb(struct super_block *sb)
cgroup_exit_root_id(root); cgroup_exit_root_id(root);
mutex_unlock(&cgroup_root_mutex);
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
mutex_unlock(&cgrp->dentry->d_inode->i_mutex); mutex_unlock(&cgrp->dentry->d_inode->i_mutex);
...@@ -2193,11 +2157,9 @@ static int cgroup_release_agent_write(struct cgroup_subsys_state *css, ...@@ -2193,11 +2157,9 @@ static int cgroup_release_agent_write(struct cgroup_subsys_state *css,
return -EINVAL; return -EINVAL;
if (!cgroup_lock_live_group(css->cgroup)) if (!cgroup_lock_live_group(css->cgroup))
return -ENODEV; return -ENODEV;
mutex_lock(&cgroup_root_mutex);
spin_lock(&release_agent_path_lock); spin_lock(&release_agent_path_lock);
strcpy(css->cgroup->root->release_agent_path, buffer); strcpy(css->cgroup->root->release_agent_path, buffer);
spin_unlock(&release_agent_path_lock); spin_unlock(&release_agent_path_lock);
mutex_unlock(&cgroup_root_mutex);
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
return 0; return 0;
} }
...@@ -4588,7 +4550,6 @@ int __init cgroup_init(void) ...@@ -4588,7 +4550,6 @@ int __init cgroup_init(void)
/* allocate id for the dummy hierarchy */ /* allocate id for the dummy hierarchy */
mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_mutex);
mutex_lock(&cgroup_root_mutex);
/* Add init_css_set to the hash table */ /* Add init_css_set to the hash table */
key = css_set_hash(init_css_set.subsys); key = css_set_hash(init_css_set.subsys);
...@@ -4600,7 +4561,6 @@ int __init cgroup_init(void) ...@@ -4600,7 +4561,6 @@ int __init cgroup_init(void)
0, 1, GFP_KERNEL); 0, 1, GFP_KERNEL);
BUG_ON(err < 0); BUG_ON(err < 0);
mutex_unlock(&cgroup_root_mutex);
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj); cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment