diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2019-01-16 23:42:38 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2019-02-28 03:29:30 -0500 |
commit | f5dfb5315d340abd71bec523be9b114d5ac410de (patch) | |
tree | b2bbeb90606b63e904bc309bb7f18c29cfd7b1c9 /kernel/cgroup/cgroup.c | |
parent | 7feeef58690a5ea8c5033d43e696ef41b28d82eb (diff) |
cgroup: take options parsing into ->parse_monolithic()
Store the results in cgroup_fs_context. There's a nasty twist caused
by the enabling/disabling subsystems - we can't do the checks sensitive
to that until cgroup_mutex gets grabbed. Frankly, these checks are
complete bullshit (e.g. all,none combination is accepted if all subsystems
are disabled; so's cpusets,none and all,cpusets when cpusets is disabled,
etc.), but touching that would be a userland-visible behaviour change ;-/
So we do parsing in ->parse_monolithic() and have the consistency checks
done in check_cgroupfs_options(), with the latter called (on already parsed
options) from cgroup1_get_tree() and cgroup1_reconfigure().
Freeing the strdup'ed strings is done from fs_context destructor, which
somewhat simplifies the life for cgroup1_{get_tree,reconfigure}().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/cgroup/cgroup.c')
-rw-r--r-- | kernel/cgroup/cgroup.c | 54 |
1 files changed, 26 insertions, 28 deletions
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 0652f74064a2..33da9eef3ef4 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c | |||
@@ -1814,14 +1814,8 @@ static int cgroup_show_options(struct seq_file *seq, struct kernfs_root *kf_root | |||
1814 | static int cgroup_reconfigure(struct fs_context *fc) | 1814 | static int cgroup_reconfigure(struct fs_context *fc) |
1815 | { | 1815 | { |
1816 | struct cgroup_fs_context *ctx = cgroup_fc2context(fc); | 1816 | struct cgroup_fs_context *ctx = cgroup_fc2context(fc); |
1817 | unsigned int root_flags; | ||
1818 | int ret; | ||
1819 | |||
1820 | ret = parse_cgroup_root_flags(ctx->data, &root_flags); | ||
1821 | if (ret) | ||
1822 | return ret; | ||
1823 | 1817 | ||
1824 | apply_cgroup_root_flags(root_flags); | 1818 | apply_cgroup_root_flags(ctx->flags); |
1825 | return 0; | 1819 | return 0; |
1826 | } | 1820 | } |
1827 | 1821 | ||
@@ -1909,7 +1903,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) | |||
1909 | INIT_WORK(&cgrp->release_agent_work, cgroup1_release_agent); | 1903 | INIT_WORK(&cgrp->release_agent_work, cgroup1_release_agent); |
1910 | } | 1904 | } |
1911 | 1905 | ||
1912 | void init_cgroup_root(struct cgroup_root *root, struct cgroup_sb_opts *opts) | 1906 | void init_cgroup_root(struct cgroup_root *root, struct cgroup_fs_context *ctx) |
1913 | { | 1907 | { |
1914 | struct cgroup *cgrp = &root->cgrp; | 1908 | struct cgroup *cgrp = &root->cgrp; |
1915 | 1909 | ||
@@ -1919,12 +1913,12 @@ void init_cgroup_root(struct cgroup_root *root, struct cgroup_sb_opts *opts) | |||
1919 | init_cgroup_housekeeping(cgrp); | 1913 | init_cgroup_housekeeping(cgrp); |
1920 | idr_init(&root->cgroup_idr); | 1914 | idr_init(&root->cgroup_idr); |
1921 | 1915 | ||
1922 | root->flags = opts->flags; | 1916 | root->flags = ctx->flags; |
1923 | if (opts->release_agent) | 1917 | if (ctx->release_agent) |
1924 | strscpy(root->release_agent_path, opts->release_agent, PATH_MAX); | 1918 | strscpy(root->release_agent_path, ctx->release_agent, PATH_MAX); |
1925 | if (opts->name) | 1919 | if (ctx->name) |
1926 | strscpy(root->name, opts->name, MAX_CGROUP_ROOT_NAMELEN); | 1920 | strscpy(root->name, ctx->name, MAX_CGROUP_ROOT_NAMELEN); |
1927 | if (opts->cpuset_clone_children) | 1921 | if (ctx->cpuset_clone_children) |
1928 | set_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->cgrp.flags); | 1922 | set_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->cgrp.flags); |
1929 | } | 1923 | } |
1930 | 1924 | ||
@@ -2075,6 +2069,8 @@ static void cgroup_fs_context_free(struct fs_context *fc) | |||
2075 | { | 2069 | { |
2076 | struct cgroup_fs_context *ctx = cgroup_fc2context(fc); | 2070 | struct cgroup_fs_context *ctx = cgroup_fc2context(fc); |
2077 | 2071 | ||
2072 | kfree(ctx->name); | ||
2073 | kfree(ctx->release_agent); | ||
2078 | kfree(ctx); | 2074 | kfree(ctx); |
2079 | } | 2075 | } |
2080 | 2076 | ||
@@ -2082,28 +2078,30 @@ static int cgroup_parse_monolithic(struct fs_context *fc, void *data) | |||
2082 | { | 2078 | { |
2083 | struct cgroup_fs_context *ctx = cgroup_fc2context(fc); | 2079 | struct cgroup_fs_context *ctx = cgroup_fc2context(fc); |
2084 | 2080 | ||
2085 | ctx->data = data; | 2081 | if (data) |
2086 | if (ctx->data) | 2082 | security_sb_eat_lsm_opts(data, &fc->security); |
2087 | security_sb_eat_lsm_opts(ctx->data, &fc->security); | 2083 | return parse_cgroup_root_flags(data, &ctx->flags); |
2088 | return 0; | 2084 | } |
2085 | |||
2086 | static int cgroup1_parse_monolithic(struct fs_context *fc, void *data) | ||
2087 | { | ||
2088 | struct cgroup_fs_context *ctx = cgroup_fc2context(fc); | ||
2089 | |||
2090 | if (data) | ||
2091 | security_sb_eat_lsm_opts(data, &fc->security); | ||
2092 | return parse_cgroup1_options(data, ctx); | ||
2089 | } | 2093 | } |
2090 | 2094 | ||
2091 | static int cgroup_get_tree(struct fs_context *fc) | 2095 | static int cgroup_get_tree(struct fs_context *fc) |
2092 | { | 2096 | { |
2093 | struct cgroup_namespace *ns = current->nsproxy->cgroup_ns; | 2097 | struct cgroup_namespace *ns = current->nsproxy->cgroup_ns; |
2094 | struct cgroup_fs_context *ctx = cgroup_fc2context(fc); | 2098 | struct cgroup_fs_context *ctx = cgroup_fc2context(fc); |
2095 | unsigned int root_flags; | ||
2096 | struct dentry *root; | 2099 | struct dentry *root; |
2097 | int ret; | ||
2098 | 2100 | ||
2099 | /* Check if the caller has permission to mount. */ | 2101 | /* Check if the caller has permission to mount. */ |
2100 | if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) | 2102 | if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) |
2101 | return -EPERM; | 2103 | return -EPERM; |
2102 | 2104 | ||
2103 | ret = parse_cgroup_root_flags(ctx->data, &root_flags); | ||
2104 | if (ret) | ||
2105 | return ret; | ||
2106 | |||
2107 | cgrp_dfl_visible = true; | 2105 | cgrp_dfl_visible = true; |
2108 | cgroup_get_live(&cgrp_dfl_root.cgrp); | 2106 | cgroup_get_live(&cgrp_dfl_root.cgrp); |
2109 | 2107 | ||
@@ -2112,7 +2110,7 @@ static int cgroup_get_tree(struct fs_context *fc) | |||
2112 | if (IS_ERR(root)) | 2110 | if (IS_ERR(root)) |
2113 | return PTR_ERR(root); | 2111 | return PTR_ERR(root); |
2114 | 2112 | ||
2115 | apply_cgroup_root_flags(root_flags); | 2113 | apply_cgroup_root_flags(ctx->flags); |
2116 | fc->root = root; | 2114 | fc->root = root; |
2117 | return 0; | 2115 | return 0; |
2118 | } | 2116 | } |
@@ -2126,7 +2124,7 @@ static const struct fs_context_operations cgroup_fs_context_ops = { | |||
2126 | 2124 | ||
2127 | static const struct fs_context_operations cgroup1_fs_context_ops = { | 2125 | static const struct fs_context_operations cgroup1_fs_context_ops = { |
2128 | .free = cgroup_fs_context_free, | 2126 | .free = cgroup_fs_context_free, |
2129 | .parse_monolithic = cgroup_parse_monolithic, | 2127 | .parse_monolithic = cgroup1_parse_monolithic, |
2130 | .get_tree = cgroup1_get_tree, | 2128 | .get_tree = cgroup1_get_tree, |
2131 | .reconfigure = cgroup1_reconfigure, | 2129 | .reconfigure = cgroup1_reconfigure, |
2132 | }; | 2130 | }; |
@@ -5376,11 +5374,11 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss, bool early) | |||
5376 | */ | 5374 | */ |
5377 | int __init cgroup_init_early(void) | 5375 | int __init cgroup_init_early(void) |
5378 | { | 5376 | { |
5379 | static struct cgroup_sb_opts __initdata opts; | 5377 | static struct cgroup_fs_context __initdata ctx; |
5380 | struct cgroup_subsys *ss; | 5378 | struct cgroup_subsys *ss; |
5381 | int i; | 5379 | int i; |
5382 | 5380 | ||
5383 | init_cgroup_root(&cgrp_dfl_root, &opts); | 5381 | init_cgroup_root(&cgrp_dfl_root, &ctx); |
5384 | cgrp_dfl_root.cgrp.self.flags |= CSS_NO_REF; | 5382 | cgrp_dfl_root.cgrp.self.flags |= CSS_NO_REF; |
5385 | 5383 | ||
5386 | RCU_INIT_POINTER(init_task.cgroups, &init_css_set); | 5384 | RCU_INIT_POINTER(init_task.cgroups, &init_css_set); |