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 */
};
/*
}
}
+ /*
+ * Mark @root has finished binding subsystems. @root->subsys_mask
+ * now matches the bound subsystems.
+ */
+ root->flags |= CGRP_ROOT_SUBSYS_BOUND;
+
return 0;
}
init_cgroup_root(root);
+ /*
+ * We need to set @root->subsys_mask now so that @root can be
+ * matched by cgroup_test_super() before it finishes
+ * initialization; otherwise, competing mounts with the same
+ * options may try to bind the same subsystems instead of waiting
+ * for the first one leading to unexpected mount errors.
+ * SUBSYS_BOUND will be set once actual binding is complete.
+ */
root->subsys_mask = opts->subsys_mask;
root->flags = opts->flags;
ida_init(&root->cgroup_ida);
mutex_lock(&cgroup_root_mutex);
/* Rebind all subsystems back to the default hierarchy */
- ret = rebind_subsystems(root, 0, root->subsys_mask);
- /* Shouldn't be able to fail ... */
- BUG_ON(ret);
+ if (root->flags & CGRP_ROOT_SUBSYS_BOUND) {
+ ret = rebind_subsystems(root, 0, root->subsys_mask);
+ /* Shouldn't be able to fail ... */
+ BUG_ON(ret);
+ }
/*
* Release all the links from cset_links to this hierarchy's