aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-06-25 21:04:54 -0400
committerTejun Heo <tj@kernel.org>2013-06-26 13:39:46 -0400
commit1672d040709b789671c0502e7aac9d632c2f9175 (patch)
treeeceebdf6be0c9769e2c10270b4389c402d4a0df9 /kernel/cgroup.c
parentfc76df706123602214da494ba98bccea83e2cfff (diff)
cgroup: fix cgroupfs_root early destruction path
cgroupfs_root used to have ->actual_subsys_mask in addition to ->subsys_mask. a8a648c4ac ("cgroup: remove cgroup->actual_subsys_mask") removed it noting that the subsys_mask is essentially temporary and doesn't belong in cgroupfs_root; however, the patch made it impossible to tell whether a cgroupfs_root actually has the subsystems bound or just have the bits set leading to the following BUG when trying to mount with subsystems which are already mounted elsewhere. kernel BUG at kernel/cgroup.c:1038! invalid opcode: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC ... CPU: 1 PID: 7973 Comm: mount Tainted: G W 3.10.0-rc7-next-20130625-sasha-00011-g1c1dc0e #1105 task: ffff880fc0ae8000 ti: ffff880fc0b9a000 task.ti: ffff880fc0b9a000 RIP: 0010:[<ffffffff81249b29>] [<ffffffff81249b29>] rebind_subsystems+0x409/0x5f0 ... Call Trace: [<ffffffff8124bd4f>] cgroup_kill_sb+0xff/0x210 [<ffffffff813d21af>] deactivate_locked_super+0x4f/0x90 [<ffffffff8124f3b3>] cgroup_mount+0x673/0x6e0 [<ffffffff81257169>] cpuset_mount+0xd9/0x110 [<ffffffff813d2580>] mount_fs+0xb0/0x2d0 [<ffffffff81404afd>] vfs_kern_mount+0xbd/0x180 [<ffffffff814070b5>] do_new_mount+0x145/0x2c0 [<ffffffff814085d6>] do_mount+0x356/0x3c0 [<ffffffff8140873d>] SyS_mount+0xfd/0x140 [<ffffffff854eb600>] tracesys+0xdd/0xe2 We still want rebind_subsystems() to take added/removed masks, so let's fix it by marking whether a cgroupfs_root has finished binding or not. Also, document what's going on around ->subsys_mask initialization so that similar mistakes aren't repeated. Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Sasha Levin <sasha.levin@oracle.com> Acked-by: Li Zefan <lizefan@huawei.com>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index f9c99abc38ab..e801ecfa36ef 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1086,6 +1086,12 @@ static int rebind_subsystems(struct cgroupfs_root *root,
1086 } 1086 }
1087 } 1087 }
1088 1088
1089 /*
1090 * Mark @root has finished binding subsystems. @root->subsys_mask
1091 * now matches the bound subsystems.
1092 */
1093 root->flags |= CGRP_ROOT_SUBSYS_BOUND;
1094
1089 return 0; 1095 return 0;
1090} 1096}
1091 1097
@@ -1485,6 +1491,14 @@ static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts)
1485 1491
1486 init_cgroup_root(root); 1492 init_cgroup_root(root);
1487 1493
1494 /*
1495 * We need to set @root->subsys_mask now so that @root can be
1496 * matched by cgroup_test_super() before it finishes
1497 * initialization; otherwise, competing mounts with the same
1498 * options may try to bind the same subsystems instead of waiting
1499 * for the first one leading to unexpected mount errors.
1500 * SUBSYS_BOUND will be set once actual binding is complete.
1501 */
1488 root->subsys_mask = opts->subsys_mask; 1502 root->subsys_mask = opts->subsys_mask;
1489 root->flags = opts->flags; 1503 root->flags = opts->flags;
1490 ida_init(&root->cgroup_ida); 1504 ida_init(&root->cgroup_ida);
@@ -1734,9 +1748,11 @@ static void cgroup_kill_sb(struct super_block *sb) {
1734 mutex_lock(&cgroup_root_mutex); 1748 mutex_lock(&cgroup_root_mutex);
1735 1749
1736 /* Rebind all subsystems back to the default hierarchy */ 1750 /* Rebind all subsystems back to the default hierarchy */
1737 ret = rebind_subsystems(root, 0, root->subsys_mask); 1751 if (root->flags & CGRP_ROOT_SUBSYS_BOUND) {
1738 /* Shouldn't be able to fail ... */ 1752 ret = rebind_subsystems(root, 0, root->subsys_mask);
1739 BUG_ON(ret); 1753 /* Shouldn't be able to fail ... */
1754 BUG_ON(ret);
1755 }
1740 1756
1741 /* 1757 /*
1742 * Release all the links from cset_links to this hierarchy's 1758 * Release all the links from cset_links to this hierarchy's