]> Pileus Git - ~andy/linux/commitdiff
cgroup: CGRP_ROOT_SUBSYS_BOUND should be ignored when comparing mount options
authorTejun Heo <tj@kernel.org>
Fri, 28 Jun 2013 02:37:26 +0000 (19:37 -0700)
committerTejun Heo <tj@kernel.org>
Fri, 28 Jun 2013 02:37:26 +0000 (19:37 -0700)
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>
include/linux/cgroup.h
kernel/cgroup.c

index ad3555bc21f4122f6897a8080416ca6dc10b425f..8db53974f7b530247c6aad4d1e3ca89c830f940b 100644 (file)
@@ -276,7 +276,11 @@ enum {
 
        CGRP_ROOT_NOPREFIX      = (1 << 1), /* mounted subsystems have no named prefix */
        CGRP_ROOT_XATTR         = (1 << 2), /* supports extended attributes */
-       CGRP_ROOT_SUBSYS_BOUND  = (1 << 3), /* subsystems finished binding */
+
+       /* mount options live below bit 16 */
+       CGRP_ROOT_OPTION_MASK   = (1 << 16) - 1,
+
+       CGRP_ROOT_SUBSYS_BOUND  = (1 << 16), /* subsystems finished binding */
 };
 
 /*
index 1b7b567208cd64266bec44f1b60f41463fa0d9c0..5a2fcf5bcc4ae9b7cffe93782e9104e6c2508f59 100644 (file)
@@ -1362,8 +1362,11 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
        removed_mask = root->subsys_mask & ~opts.subsys_mask;
 
        /* Don't allow flags or name to change at remount */
-       if (opts.flags != root->flags ||
+       if (((opts.flags ^ root->flags) & CGRP_ROOT_OPTION_MASK) ||
            (opts.name && strcmp(opts.name, root->name))) {
+               pr_err("cgroup: option or name mismatch, new: 0x%lx \"%s\", old: 0x%lx \"%s\"\n",
+                      opts.flags & CGRP_ROOT_OPTION_MASK, opts.name ?: "",
+                      root->flags & CGRP_ROOT_OPTION_MASK, root->name);
                ret = -EINVAL;
                goto out_unlock;
        }