aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/cgroup/cgroup.c140
1 files changed, 79 insertions, 61 deletions
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index d34c170f87ef..228dd9ae708b 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -1989,48 +1989,55 @@ out:
1989 return ret; 1989 return ret;
1990} 1990}
1991 1991
1992static struct dentry *cgroup_mount(struct file_system_type *fs_type, 1992static struct dentry *cgroup_do_mount(struct file_system_type *fs_type,
1993 int flags, const char *unused_dev_name, 1993 int flags, struct cgroup_root *root,
1994 void *data) 1994 unsigned long magic,
1995 struct cgroup_namespace *ns)
1995{ 1996{
1996 bool is_v2 = fs_type == &cgroup2_fs_type;
1997 struct super_block *pinned_sb = NULL;
1998 struct cgroup_namespace *ns = current->nsproxy->cgroup_ns;
1999 struct cgroup_subsys *ss;
2000 struct cgroup_root *root;
2001 struct cgroup_sb_opts opts;
2002 struct dentry *dentry; 1997 struct dentry *dentry;
2003 int ret;
2004 int i;
2005 bool new_sb; 1998 bool new_sb;
2006 1999
2007 get_cgroup_ns(ns); 2000 dentry = kernfs_mount(fs_type, flags, root->kf_root, magic, &new_sb);
2008
2009 /* Check if the caller has permission to mount. */
2010 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) {
2011 put_cgroup_ns(ns);
2012 return ERR_PTR(-EPERM);
2013 }
2014 2001
2015 /* 2002 /*
2016 * The first time anyone tries to mount a cgroup, enable the list 2003 * In non-init cgroup namespace, instead of root cgroup's dentry,
2017 * linking each css_set to its tasks and fix up all existing tasks. 2004 * we return the dentry corresponding to the cgroupns->root_cgrp.
2018 */ 2005 */
2019 if (!use_task_css_set_links) 2006 if (!IS_ERR(dentry) && ns != &init_cgroup_ns) {
2020 cgroup_enable_task_cg_lists(); 2007 struct dentry *nsdentry;
2008 struct cgroup *cgrp;
2021 2009
2022 if (is_v2) { 2010 mutex_lock(&cgroup_mutex);
2023 if (data) { 2011 spin_lock_irq(&css_set_lock);
2024 pr_err("cgroup2: unknown option \"%s\"\n", (char *)data); 2012
2025 put_cgroup_ns(ns); 2013 cgrp = cset_cgroup_from_root(ns->root_cset, root);
2026 return ERR_PTR(-EINVAL); 2014
2027 } 2015 spin_unlock_irq(&css_set_lock);
2028 cgrp_dfl_visible = true; 2016 mutex_unlock(&cgroup_mutex);
2029 root = &cgrp_dfl_root; 2017
2030 cgroup_get(&root->cgrp); 2018 nsdentry = kernfs_node_dentry(cgrp->kn, dentry->d_sb);
2031 goto out_mount; 2019 dput(dentry);
2020 dentry = nsdentry;
2032 } 2021 }
2033 2022
2023 if (IS_ERR(dentry) || !new_sb)
2024 cgroup_put(&root->cgrp);
2025
2026 return dentry;
2027}
2028
2029static struct dentry *cgroup1_mount(struct file_system_type *fs_type,
2030 int flags, void *data,
2031 unsigned long magic,
2032 struct cgroup_namespace *ns)
2033{
2034 struct super_block *pinned_sb = NULL;
2035 struct cgroup_sb_opts opts;
2036 struct cgroup_root *root;
2037 struct cgroup_subsys *ss;
2038 struct dentry *dentry;
2039 int i, ret;
2040
2034 cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp); 2041 cgroup_lock_and_drain_offline(&cgrp_dfl_root.cgrp);
2035 2042
2036 /* First find the desired set of subsystems */ 2043 /* First find the desired set of subsystems */
@@ -2152,47 +2159,58 @@ out_free:
2152 kfree(opts.release_agent); 2159 kfree(opts.release_agent);
2153 kfree(opts.name); 2160 kfree(opts.name);
2154 2161
2155 if (ret) { 2162 if (ret)
2156 put_cgroup_ns(ns);
2157 return ERR_PTR(ret); 2163 return ERR_PTR(ret);
2158 } 2164
2159out_mount: 2165 dentry = cgroup_do_mount(&cgroup_fs_type, flags, root,
2160 dentry = kernfs_mount(fs_type, flags, root->kf_root, 2166 CGROUP_SUPER_MAGIC, ns);
2161 is_v2 ? CGROUP2_SUPER_MAGIC : CGROUP_SUPER_MAGIC,
2162 &new_sb);
2163 2167
2164 /* 2168 /*
2165 * In non-init cgroup namespace, instead of root cgroup's 2169 * If @pinned_sb, we're reusing an existing root and holding an
2166 * dentry, we return the dentry corresponding to the 2170 * extra ref on its sb. Mount is complete. Put the extra ref.
2167 * cgroupns->root_cgrp.
2168 */ 2171 */
2169 if (!IS_ERR(dentry) && ns != &init_cgroup_ns) { 2172 if (pinned_sb)
2170 struct dentry *nsdentry; 2173 deactivate_super(pinned_sb);
2171 struct cgroup *cgrp;
2172 2174
2173 mutex_lock(&cgroup_mutex); 2175 return dentry;
2174 spin_lock_irq(&css_set_lock); 2176}
2175 2177
2176 cgrp = cset_cgroup_from_root(ns->root_cset, root); 2178static struct dentry *cgroup_mount(struct file_system_type *fs_type,
2179 int flags, const char *unused_dev_name,
2180 void *data)
2181{
2182 struct cgroup_namespace *ns = current->nsproxy->cgroup_ns;
2183 struct dentry *dentry;
2177 2184
2178 spin_unlock_irq(&css_set_lock); 2185 get_cgroup_ns(ns);
2179 mutex_unlock(&cgroup_mutex);
2180 2186
2181 nsdentry = kernfs_node_dentry(cgrp->kn, dentry->d_sb); 2187 /* Check if the caller has permission to mount. */
2182 dput(dentry); 2188 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) {
2183 dentry = nsdentry; 2189 put_cgroup_ns(ns);
2190 return ERR_PTR(-EPERM);
2184 } 2191 }
2185 2192
2186 if (IS_ERR(dentry) || !new_sb)
2187 cgroup_put(&root->cgrp);
2188
2189 /* 2193 /*
2190 * If @pinned_sb, we're reusing an existing root and holding an 2194 * The first time anyone tries to mount a cgroup, enable the list
2191 * extra ref on its sb. Mount is complete. Put the extra ref. 2195 * linking each css_set to its tasks and fix up all existing tasks.
2192 */ 2196 */
2193 if (pinned_sb) { 2197 if (!use_task_css_set_links)
2194 WARN_ON(new_sb); 2198 cgroup_enable_task_cg_lists();
2195 deactivate_super(pinned_sb); 2199
2200 if (fs_type == &cgroup2_fs_type) {
2201 if (data) {
2202 pr_err("cgroup2: unknown option \"%s\"\n", (char *)data);
2203 put_cgroup_ns(ns);
2204 return ERR_PTR(-EINVAL);
2205 }
2206 cgrp_dfl_visible = true;
2207 cgroup_get(&cgrp_dfl_root.cgrp);
2208
2209 dentry = cgroup_do_mount(&cgroup2_fs_type, flags, &cgrp_dfl_root,
2210 CGROUP2_SUPER_MAGIC, ns);
2211 } else {
2212 dentry = cgroup1_mount(&cgroup_fs_type, flags, data,
2213 CGROUP_SUPER_MAGIC, ns);
2196 } 2214 }
2197 2215
2198 put_cgroup_ns(ns); 2216 put_cgroup_ns(ns);