diff options
author | Tejun Heo <tj@kernel.org> | 2014-02-11 11:52:47 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2014-02-11 11:52:47 -0500 |
commit | 4ac0601744eb86e982fbdadde35f1945f7ce5882 (patch) | |
tree | 887f0cbc2853802ad113b87f0d2c5b764e2619ce /kernel/cgroup.c | |
parent | ace2bee8135a3dc725958b8d08c55ee9df813d39 (diff) |
cgroup: release cgroup_mutex over file removals
Now that cftypes and all tree modification operations are protected by
cgroup_tree_mutex, we can drop cgroup_mutex while deleting files and
directories. Drop cgroup_mutex over removals.
This doesn't make any noticeable difference now but is to help kernfs
conversion. In kernfs, removals are sync points which drain in-flight
operations as those operations would grab cgroup_mutex, trying to
delete under cgroup_mutex would deadlock. This can be resolved by
just holding the outer cgroup_tree_mutex which nests outside both
kernfs active reference and cgroup_mutex.
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index cb20d12cb096..d28cf75f33c1 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -976,7 +976,9 @@ static int rebind_subsystems(struct cgroupfs_root *root, | |||
976 | * Nothing can fail from this point on. Remove files for the | 976 | * Nothing can fail from this point on. Remove files for the |
977 | * removed subsystems and rebind each subsystem. | 977 | * removed subsystems and rebind each subsystem. |
978 | */ | 978 | */ |
979 | mutex_unlock(&cgroup_mutex); | ||
979 | cgroup_clear_dir(cgrp, removed_mask); | 980 | cgroup_clear_dir(cgrp, removed_mask); |
981 | mutex_lock(&cgroup_mutex); | ||
980 | 982 | ||
981 | for_each_subsys(ss, i) { | 983 | for_each_subsys(ss, i) { |
982 | unsigned long bit = 1UL << i; | 984 | unsigned long bit = 1UL << i; |
@@ -2696,10 +2698,11 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add) | |||
2696 | u64 update_before; | 2698 | u64 update_before; |
2697 | int ret = 0; | 2699 | int ret = 0; |
2698 | 2700 | ||
2701 | mutex_unlock(&cgroup_mutex); | ||
2702 | |||
2699 | /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */ | 2703 | /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */ |
2700 | if (!cfts || ss->root == &cgroup_dummy_root || | 2704 | if (!cfts || ss->root == &cgroup_dummy_root || |
2701 | !atomic_inc_not_zero(&sb->s_active)) { | 2705 | !atomic_inc_not_zero(&sb->s_active)) { |
2702 | mutex_unlock(&cgroup_mutex); | ||
2703 | mutex_unlock(&cgroup_tree_mutex); | 2706 | mutex_unlock(&cgroup_tree_mutex); |
2704 | return 0; | 2707 | return 0; |
2705 | } | 2708 | } |
@@ -2723,18 +2726,15 @@ static int cgroup_cfts_commit(struct cftype *cfts, bool is_add) | |||
2723 | dput(prev); | 2726 | dput(prev); |
2724 | prev = cgrp->dentry; | 2727 | prev = cgrp->dentry; |
2725 | 2728 | ||
2726 | mutex_unlock(&cgroup_mutex); | ||
2727 | mutex_unlock(&cgroup_tree_mutex); | 2729 | mutex_unlock(&cgroup_tree_mutex); |
2728 | mutex_lock(&inode->i_mutex); | 2730 | mutex_lock(&inode->i_mutex); |
2729 | mutex_lock(&cgroup_tree_mutex); | 2731 | mutex_lock(&cgroup_tree_mutex); |
2730 | mutex_lock(&cgroup_mutex); | ||
2731 | if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp)) | 2732 | if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp)) |
2732 | ret = cgroup_addrm_files(cgrp, cfts, is_add); | 2733 | ret = cgroup_addrm_files(cgrp, cfts, is_add); |
2733 | mutex_unlock(&inode->i_mutex); | 2734 | mutex_unlock(&inode->i_mutex); |
2734 | if (ret) | 2735 | if (ret) |
2735 | break; | 2736 | break; |
2736 | } | 2737 | } |
2737 | mutex_unlock(&cgroup_mutex); | ||
2738 | mutex_unlock(&cgroup_tree_mutex); | 2738 | mutex_unlock(&cgroup_tree_mutex); |
2739 | dput(prev); | 2739 | dput(prev); |
2740 | deactivate_super(sb); | 2740 | deactivate_super(sb); |
@@ -4387,10 +4387,13 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
4387 | /* | 4387 | /* |
4388 | * Initiate massacre of all css's. cgroup_destroy_css_killed() | 4388 | * Initiate massacre of all css's. cgroup_destroy_css_killed() |
4389 | * will be invoked to perform the rest of destruction once the | 4389 | * will be invoked to perform the rest of destruction once the |
4390 | * percpu refs of all css's are confirmed to be killed. | 4390 | * percpu refs of all css's are confirmed to be killed. This |
4391 | * involves removing the subsystem's files, drop cgroup_mutex. | ||
4391 | */ | 4392 | */ |
4393 | mutex_unlock(&cgroup_mutex); | ||
4392 | for_each_css(css, ssid, cgrp) | 4394 | for_each_css(css, ssid, cgrp) |
4393 | kill_css(css); | 4395 | kill_css(css); |
4396 | mutex_lock(&cgroup_mutex); | ||
4394 | 4397 | ||
4395 | /* | 4398 | /* |
4396 | * Mark @cgrp dead. This prevents further task migration and child | 4399 | * Mark @cgrp dead. This prevents further task migration and child |
@@ -4421,9 +4424,11 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) | |||
4421 | * puts the base ref but we aren't quite done with @cgrp yet, so | 4424 | * puts the base ref but we aren't quite done with @cgrp yet, so |
4422 | * hold onto it. | 4425 | * hold onto it. |
4423 | */ | 4426 | */ |
4427 | mutex_unlock(&cgroup_mutex); | ||
4424 | cgroup_addrm_files(cgrp, cgroup_base_files, false); | 4428 | cgroup_addrm_files(cgrp, cgroup_base_files, false); |
4425 | dget(d); | 4429 | dget(d); |
4426 | cgroup_d_remove_dir(d); | 4430 | cgroup_d_remove_dir(d); |
4431 | mutex_lock(&cgroup_mutex); | ||
4427 | 4432 | ||
4428 | return 0; | 4433 | return 0; |
4429 | }; | 4434 | }; |