cgroup: move namespace code to kernel/cgroup/namespace.c
authorTejun Heo <tj@kernel.org>
Tue, 27 Dec 2016 19:49:09 +0000 (14:49 -0500)
committerTejun Heo <tj@kernel.org>
Tue, 27 Dec 2016 19:49:09 +0000 (14:49 -0500)
get/put_css_set() get exposed in cgroup-internal.h in the process.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Acked-by: Zefan Li <lizefan@huawei.com>
kernel/cgroup/Makefile
kernel/cgroup/cgroup-internal.h
kernel/cgroup/cgroup.c
kernel/cgroup/namespace.c [new file with mode: 0644]

index 719588cb18cde91abf5ee006539b45132ccca13f..6d42a3211164d1f1866895effd7da4c4f8975447 100644 (file)
@@ -1,4 +1,4 @@
-obj-y := cgroup.o cgroup-v1.o
+obj-y := cgroup.o namespace.o cgroup-v1.o
 
 obj-$(CONFIG_CGROUP_FREEZER) += freezer.o
 obj-$(CONFIG_CGROUP_PIDS) += pids.o
index a890c92cb688ad0dd9dec8693115ce762ce0eb0c..589b0e7013ec829056353f92b481be9830955b58 100644 (file)
@@ -65,6 +65,33 @@ static inline bool notify_on_release(const struct cgroup *cgrp)
        return test_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
 }
 
+void put_css_set_locked(struct css_set *cset);
+
+static inline void put_css_set(struct css_set *cset)
+{
+       unsigned long flags;
+
+       /*
+        * Ensure that the refcount doesn't hit zero while any readers
+        * can see it. Similar to atomic_dec_and_lock(), but for an
+        * rwlock
+        */
+       if (atomic_add_unless(&cset->refcount, -1, 1))
+               return;
+
+       spin_lock_irqsave(&css_set_lock, flags);
+       put_css_set_locked(cset);
+       spin_unlock_irqrestore(&css_set_lock, flags);
+}
+
+/*
+ * refcounted get/put for css_set objects
+ */
+static inline void get_css_set(struct css_set *cset)
+{
+       atomic_inc(&cset->refcount);
+}
+
 bool cgroup_ssid_enabled(int ssid);
 bool cgroup_on_dfl(const struct cgroup *cgrp);
 
@@ -107,6 +134,11 @@ int cgroup_rmdir(struct kernfs_node *kn);
 int cgroup_show_path(struct seq_file *sf, struct kernfs_node *kf_node,
                     struct kernfs_root *kf_root);
 
+/*
+ * namespace.c
+ */
+extern const struct proc_ns_operations cgroupns_operations;
+
 /*
  * cgroup-v1.c
  */
index a05a2dacf5dcf76093c6bc30f0225dedaf5b78fc..b6b9068ef468fab39a19e7b32592fb1b4bf5cab0 100644 (file)
@@ -718,7 +718,7 @@ static unsigned long css_set_hash(struct cgroup_subsys_state *css[])
        return key;
 }
 
-static void put_css_set_locked(struct css_set *cset)
+void put_css_set_locked(struct css_set *cset)
 {
        struct cgrp_cset_link *link, *tmp_link;
        struct cgroup_subsys *ss;
@@ -748,31 +748,6 @@ static void put_css_set_locked(struct css_set *cset)
        kfree_rcu(cset, rcu_head);
 }
 
-static void put_css_set(struct css_set *cset)
-{
-       unsigned long flags;
-
-       /*
-        * Ensure that the refcount doesn't hit zero while any readers
-        * can see it. Similar to atomic_dec_and_lock(), but for an
-        * rwlock
-        */
-       if (atomic_add_unless(&cset->refcount, -1, 1))
-               return;
-
-       spin_lock_irqsave(&css_set_lock, flags);
-       put_css_set_locked(cset);
-       spin_unlock_irqrestore(&css_set_lock, flags);
-}
-
-/*
- * refcounted get/put for css_set objects
- */
-static inline void get_css_set(struct css_set *cset)
-{
-       atomic_inc(&cset->refcount);
-}
-
 /**
  * compare_css_sets - helper function for find_existing_css_set().
  * @cset: candidate css_set being tested
@@ -5109,154 +5084,6 @@ void cgroup_sk_free(struct sock_cgroup_data *skcd)
 
 #endif /* CONFIG_SOCK_CGROUP_DATA */
 
-/* cgroup namespaces */
-
-static struct ucounts *inc_cgroup_namespaces(struct user_namespace *ns)
-{
-       return inc_ucount(ns, current_euid(), UCOUNT_CGROUP_NAMESPACES);
-}
-
-static void dec_cgroup_namespaces(struct ucounts *ucounts)
-{
-       dec_ucount(ucounts, UCOUNT_CGROUP_NAMESPACES);
-}
-
-static struct cgroup_namespace *alloc_cgroup_ns(void)
-{
-       struct cgroup_namespace *new_ns;
-       int ret;
-
-       new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL);
-       if (!new_ns)
-               return ERR_PTR(-ENOMEM);
-       ret = ns_alloc_inum(&new_ns->ns);
-       if (ret) {
-               kfree(new_ns);
-               return ERR_PTR(ret);
-       }
-       atomic_set(&new_ns->count, 1);
-       new_ns->ns.ops = &cgroupns_operations;
-       return new_ns;
-}
-
-void free_cgroup_ns(struct cgroup_namespace *ns)
-{
-       put_css_set(ns->root_cset);
-       dec_cgroup_namespaces(ns->ucounts);
-       put_user_ns(ns->user_ns);
-       ns_free_inum(&ns->ns);
-       kfree(ns);
-}
-EXPORT_SYMBOL(free_cgroup_ns);
-
-struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
-                                       struct user_namespace *user_ns,
-                                       struct cgroup_namespace *old_ns)
-{
-       struct cgroup_namespace *new_ns;
-       struct ucounts *ucounts;
-       struct css_set *cset;
-
-       BUG_ON(!old_ns);
-
-       if (!(flags & CLONE_NEWCGROUP)) {
-               get_cgroup_ns(old_ns);
-               return old_ns;
-       }
-
-       /* Allow only sysadmin to create cgroup namespace. */
-       if (!ns_capable(user_ns, CAP_SYS_ADMIN))
-               return ERR_PTR(-EPERM);
-
-       ucounts = inc_cgroup_namespaces(user_ns);
-       if (!ucounts)
-               return ERR_PTR(-ENOSPC);
-
-       /* It is not safe to take cgroup_mutex here */
-       spin_lock_irq(&css_set_lock);
-       cset = task_css_set(current);
-       get_css_set(cset);
-       spin_unlock_irq(&css_set_lock);
-
-       new_ns = alloc_cgroup_ns();
-       if (IS_ERR(new_ns)) {
-               put_css_set(cset);
-               dec_cgroup_namespaces(ucounts);
-               return new_ns;
-       }
-
-       new_ns->user_ns = get_user_ns(user_ns);
-       new_ns->ucounts = ucounts;
-       new_ns->root_cset = cset;
-
-       return new_ns;
-}
-
-static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns)
-{
-       return container_of(ns, struct cgroup_namespace, ns);
-}
-
-static int cgroupns_install(struct nsproxy *nsproxy, struct ns_common *ns)
-{
-       struct cgroup_namespace *cgroup_ns = to_cg_ns(ns);
-
-       if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN) ||
-           !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN))
-               return -EPERM;
-
-       /* Don't need to do anything if we are attaching to our own cgroupns. */
-       if (cgroup_ns == nsproxy->cgroup_ns)
-               return 0;
-
-       get_cgroup_ns(cgroup_ns);
-       put_cgroup_ns(nsproxy->cgroup_ns);
-       nsproxy->cgroup_ns = cgroup_ns;
-
-       return 0;
-}
-
-static struct ns_common *cgroupns_get(struct task_struct *task)
-{
-       struct cgroup_namespace *ns = NULL;
-       struct nsproxy *nsproxy;
-
-       task_lock(task);
-       nsproxy = task->nsproxy;
-       if (nsproxy) {
-               ns = nsproxy->cgroup_ns;
-               get_cgroup_ns(ns);
-       }
-       task_unlock(task);
-
-       return ns ? &ns->ns : NULL;
-}
-
-static void cgroupns_put(struct ns_common *ns)
-{
-       put_cgroup_ns(to_cg_ns(ns));
-}
-
-static struct user_namespace *cgroupns_owner(struct ns_common *ns)
-{
-       return to_cg_ns(ns)->user_ns;
-}
-
-const struct proc_ns_operations cgroupns_operations = {
-       .name           = "cgroup",
-       .type           = CLONE_NEWCGROUP,
-       .get            = cgroupns_get,
-       .put            = cgroupns_put,
-       .install        = cgroupns_install,
-       .owner          = cgroupns_owner,
-};
-
-static __init int cgroup_namespaces_init(void)
-{
-       return 0;
-}
-subsys_initcall(cgroup_namespaces_init);
-
 #ifdef CONFIG_CGROUP_BPF
 void cgroup_bpf_update(struct cgroup *cgrp,
                       struct bpf_prog *prog,
diff --git a/kernel/cgroup/namespace.c b/kernel/cgroup/namespace.c
new file mode 100644 (file)
index 0000000..cff7ea6
--- /dev/null
@@ -0,0 +1,155 @@
+#include "cgroup-internal.h"
+
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/nsproxy.h>
+#include <linux/proc_ns.h>
+
+
+/* cgroup namespaces */
+
+static struct ucounts *inc_cgroup_namespaces(struct user_namespace *ns)
+{
+       return inc_ucount(ns, current_euid(), UCOUNT_CGROUP_NAMESPACES);
+}
+
+static void dec_cgroup_namespaces(struct ucounts *ucounts)
+{
+       dec_ucount(ucounts, UCOUNT_CGROUP_NAMESPACES);
+}
+
+static struct cgroup_namespace *alloc_cgroup_ns(void)
+{
+       struct cgroup_namespace *new_ns;
+       int ret;
+
+       new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL);
+       if (!new_ns)
+               return ERR_PTR(-ENOMEM);
+       ret = ns_alloc_inum(&new_ns->ns);
+       if (ret) {
+               kfree(new_ns);
+               return ERR_PTR(ret);
+       }
+       atomic_set(&new_ns->count, 1);
+       new_ns->ns.ops = &cgroupns_operations;
+       return new_ns;
+}
+
+void free_cgroup_ns(struct cgroup_namespace *ns)
+{
+       put_css_set(ns->root_cset);
+       dec_cgroup_namespaces(ns->ucounts);
+       put_user_ns(ns->user_ns);
+       ns_free_inum(&ns->ns);
+       kfree(ns);
+}
+EXPORT_SYMBOL(free_cgroup_ns);
+
+struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
+                                       struct user_namespace *user_ns,
+                                       struct cgroup_namespace *old_ns)
+{
+       struct cgroup_namespace *new_ns;
+       struct ucounts *ucounts;
+       struct css_set *cset;
+
+       BUG_ON(!old_ns);
+
+       if (!(flags & CLONE_NEWCGROUP)) {
+               get_cgroup_ns(old_ns);
+               return old_ns;
+       }
+
+       /* Allow only sysadmin to create cgroup namespace. */
+       if (!ns_capable(user_ns, CAP_SYS_ADMIN))
+               return ERR_PTR(-EPERM);
+
+       ucounts = inc_cgroup_namespaces(user_ns);
+       if (!ucounts)
+               return ERR_PTR(-ENOSPC);
+
+       /* It is not safe to take cgroup_mutex here */
+       spin_lock_irq(&css_set_lock);
+       cset = task_css_set(current);
+       get_css_set(cset);
+       spin_unlock_irq(&css_set_lock);
+
+       new_ns = alloc_cgroup_ns();
+       if (IS_ERR(new_ns)) {
+               put_css_set(cset);
+               dec_cgroup_namespaces(ucounts);
+               return new_ns;
+       }
+
+       new_ns->user_ns = get_user_ns(user_ns);
+       new_ns->ucounts = ucounts;
+       new_ns->root_cset = cset;
+
+       return new_ns;
+}
+
+static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns)
+{
+       return container_of(ns, struct cgroup_namespace, ns);
+}
+
+static int cgroupns_install(struct nsproxy *nsproxy, struct ns_common *ns)
+{
+       struct cgroup_namespace *cgroup_ns = to_cg_ns(ns);
+
+       if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN) ||
+           !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN))
+               return -EPERM;
+
+       /* Don't need to do anything if we are attaching to our own cgroupns. */
+       if (cgroup_ns == nsproxy->cgroup_ns)
+               return 0;
+
+       get_cgroup_ns(cgroup_ns);
+       put_cgroup_ns(nsproxy->cgroup_ns);
+       nsproxy->cgroup_ns = cgroup_ns;
+
+       return 0;
+}
+
+static struct ns_common *cgroupns_get(struct task_struct *task)
+{
+       struct cgroup_namespace *ns = NULL;
+       struct nsproxy *nsproxy;
+
+       task_lock(task);
+       nsproxy = task->nsproxy;
+       if (nsproxy) {
+               ns = nsproxy->cgroup_ns;
+               get_cgroup_ns(ns);
+       }
+       task_unlock(task);
+
+       return ns ? &ns->ns : NULL;
+}
+
+static void cgroupns_put(struct ns_common *ns)
+{
+       put_cgroup_ns(to_cg_ns(ns));
+}
+
+static struct user_namespace *cgroupns_owner(struct ns_common *ns)
+{
+       return to_cg_ns(ns)->user_ns;
+}
+
+const struct proc_ns_operations cgroupns_operations = {
+       .name           = "cgroup",
+       .type           = CLONE_NEWCGROUP,
+       .get            = cgroupns_get,
+       .put            = cgroupns_put,
+       .install        = cgroupns_install,
+       .owner          = cgroupns_owner,
+};
+
+static __init int cgroup_namespaces_init(void)
+{
+       return 0;
+}
+subsys_initcall(cgroup_namespaces_init);