diff options
author | Tejun Heo <tj@kernel.org> | 2013-06-27 22:37:26 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-06-27 22:37:26 -0400 |
commit | 0ce6cba35777cf96a54ce0d5856dc962566b8717 (patch) | |
tree | c03ee20f1c6deff5494a4ca86802ea053c6d5667 | |
parent | e2bd416f6246d11be29999c177d2534943a5c2df (diff) |
cgroup: CGRP_ROOT_SUBSYS_BOUND should be ignored when comparing mount options
1672d04070 ("cgroup: fix cgroupfs_root early destruction path")
introduced CGRP_ROOT_SUBSYS_BOUND which is used to mark completion of
subsys binding on a new root; however, this broke remounts.
cgroup_remount() doesn't allow changing root options via remount and
CGRP_ROOT_SUBSYS_BOUND, which is set on all fully initialized roots,
makes the function reject all remounts.
Fix it by putting the options part in the lower 16 bits of root->flags
and masking the comparions. While at it, make cgroup_remount() emit
an error message explaining why it's rejecting a remount request, so
that it's less of a mystery.
Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r-- | include/linux/cgroup.h | 6 | ||||
-rw-r--r-- | kernel/cgroup.c | 5 |
2 files changed, 9 insertions, 2 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index ad3555bc21f4..8db53974f7b5 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -276,7 +276,11 @@ enum { | |||
276 | 276 | ||
277 | CGRP_ROOT_NOPREFIX = (1 << 1), /* mounted subsystems have no named prefix */ | 277 | CGRP_ROOT_NOPREFIX = (1 << 1), /* mounted subsystems have no named prefix */ |
278 | CGRP_ROOT_XATTR = (1 << 2), /* supports extended attributes */ | 278 | CGRP_ROOT_XATTR = (1 << 2), /* supports extended attributes */ |
279 | CGRP_ROOT_SUBSYS_BOUND = (1 << 3), /* subsystems finished binding */ | 279 | |
280 | /* mount options live below bit 16 */ | ||
281 | CGRP_ROOT_OPTION_MASK = (1 << 16) - 1, | ||
282 | |||
283 | CGRP_ROOT_SUBSYS_BOUND = (1 << 16), /* subsystems finished binding */ | ||
280 | }; | 284 | }; |
281 | 285 | ||
282 | /* | 286 | /* |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 1b7b567208cd..5a2fcf5bcc4a 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1362,8 +1362,11 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) | |||
1362 | removed_mask = root->subsys_mask & ~opts.subsys_mask; | 1362 | removed_mask = root->subsys_mask & ~opts.subsys_mask; |
1363 | 1363 | ||
1364 | /* Don't allow flags or name to change at remount */ | 1364 | /* Don't allow flags or name to change at remount */ |
1365 | if (opts.flags != root->flags || | 1365 | if (((opts.flags ^ root->flags) & CGRP_ROOT_OPTION_MASK) || |
1366 | (opts.name && strcmp(opts.name, root->name))) { | 1366 | (opts.name && strcmp(opts.name, root->name))) { |
1367 | pr_err("cgroup: option or name mismatch, new: 0x%lx \"%s\", old: 0x%lx \"%s\"\n", | ||
1368 | opts.flags & CGRP_ROOT_OPTION_MASK, opts.name ?: "", | ||
1369 | root->flags & CGRP_ROOT_OPTION_MASK, root->name); | ||
1367 | ret = -EINVAL; | 1370 | ret = -EINVAL; |
1368 | goto out_unlock; | 1371 | goto out_unlock; |
1369 | } | 1372 | } |