|
@@ -211,6 +211,7 @@ static unsigned long have_free_callback __read_mostly;
|
|
|
/* Ditto for the can_fork callback. */
|
|
|
static unsigned long have_canfork_callback __read_mostly;
|
|
|
|
|
|
+static struct file_system_type cgroup2_fs_type;
|
|
|
static struct cftype cgroup_dfl_base_files[];
|
|
|
static struct cftype cgroup_legacy_base_files[];
|
|
|
|
|
@@ -1641,10 +1642,6 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
|
|
|
all_ss = true;
|
|
|
continue;
|
|
|
}
|
|
|
- if (!strcmp(token, "__DEVEL__sane_behavior")) {
|
|
|
- opts->flags |= CGRP_ROOT_SANE_BEHAVIOR;
|
|
|
- continue;
|
|
|
- }
|
|
|
if (!strcmp(token, "noprefix")) {
|
|
|
opts->flags |= CGRP_ROOT_NOPREFIX;
|
|
|
continue;
|
|
@@ -1711,15 +1708,6 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
|
|
|
return -ENOENT;
|
|
|
}
|
|
|
|
|
|
- if (opts->flags & CGRP_ROOT_SANE_BEHAVIOR) {
|
|
|
- pr_warn("sane_behavior: this is still under development and its behaviors will change, proceed at your own risk\n");
|
|
|
- if (nr_opts != 1) {
|
|
|
- pr_err("sane_behavior: no other mount options allowed\n");
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
* If the 'all' option was specified select all the subsystems,
|
|
|
* otherwise if 'none', 'name=' and a subsystem name options were
|
|
@@ -1998,6 +1986,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
|
|
int flags, const char *unused_dev_name,
|
|
|
void *data)
|
|
|
{
|
|
|
+ bool is_v2 = fs_type == &cgroup2_fs_type;
|
|
|
struct super_block *pinned_sb = NULL;
|
|
|
struct cgroup_subsys *ss;
|
|
|
struct cgroup_root *root;
|
|
@@ -2014,6 +2003,17 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
|
|
if (!use_task_css_set_links)
|
|
|
cgroup_enable_task_cg_lists();
|
|
|
|
|
|
+ if (is_v2) {
|
|
|
+ if (data) {
|
|
|
+ pr_err("cgroup2: unknown option \"%s\"\n", (char *)data);
|
|
|
+ return ERR_PTR(-EINVAL);
|
|
|
+ }
|
|
|
+ cgrp_dfl_root_visible = true;
|
|
|
+ root = &cgrp_dfl_root;
|
|
|
+ cgroup_get(&root->cgrp);
|
|
|
+ goto out_mount;
|
|
|
+ }
|
|
|
+
|
|
|
mutex_lock(&cgroup_mutex);
|
|
|
|
|
|
/* First find the desired set of subsystems */
|
|
@@ -2021,15 +2021,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
|
|
if (ret)
|
|
|
goto out_unlock;
|
|
|
|
|
|
- /* look for a matching existing root */
|
|
|
- if (opts.flags & CGRP_ROOT_SANE_BEHAVIOR) {
|
|
|
- cgrp_dfl_root_visible = true;
|
|
|
- root = &cgrp_dfl_root;
|
|
|
- cgroup_get(&root->cgrp);
|
|
|
- ret = 0;
|
|
|
- goto out_unlock;
|
|
|
- }
|
|
|
-
|
|
|
/*
|
|
|
* Destruction of cgroup root is asynchronous, so subsystems may
|
|
|
* still be dying after the previous unmount. Let's drain the
|
|
@@ -2140,9 +2131,10 @@ out_free:
|
|
|
|
|
|
if (ret)
|
|
|
return ERR_PTR(ret);
|
|
|
-
|
|
|
+out_mount:
|
|
|
dentry = kernfs_mount(fs_type, flags, root->kf_root,
|
|
|
- CGROUP_SUPER_MAGIC, &new_sb);
|
|
|
+ is_v2 ? CGROUP2_SUPER_MAGIC : CGROUP_SUPER_MAGIC,
|
|
|
+ &new_sb);
|
|
|
if (IS_ERR(dentry) || !new_sb)
|
|
|
cgroup_put(&root->cgrp);
|
|
|
|
|
@@ -2185,6 +2177,12 @@ static struct file_system_type cgroup_fs_type = {
|
|
|
.kill_sb = cgroup_kill_sb,
|
|
|
};
|
|
|
|
|
|
+static struct file_system_type cgroup2_fs_type = {
|
|
|
+ .name = "cgroup2",
|
|
|
+ .mount = cgroup_mount,
|
|
|
+ .kill_sb = cgroup_kill_sb,
|
|
|
+};
|
|
|
+
|
|
|
/**
|
|
|
* task_cgroup_path - cgroup path of a task in the first cgroup hierarchy
|
|
|
* @task: target task
|
|
@@ -5315,6 +5313,7 @@ int __init cgroup_init(void)
|
|
|
|
|
|
WARN_ON(sysfs_create_mount_point(fs_kobj, "cgroup"));
|
|
|
WARN_ON(register_filesystem(&cgroup_fs_type));
|
|
|
+ WARN_ON(register_filesystem(&cgroup2_fs_type));
|
|
|
WARN_ON(!proc_create("cgroups", 0, NULL, &proc_cgroupstats_operations));
|
|
|
|
|
|
return 0;
|