cgroup: drop module support
authorTejun Heo <tj@kernel.org>
Sat, 8 Feb 2014 15:36:58 +0000 (10:36 -0500)
committerTejun Heo <tj@kernel.org>
Sat, 8 Feb 2014 15:36:58 +0000 (10:36 -0500)
With module supported dropped from net_prio, no controller is using
cgroup module support.  None of actual resource controllers can be
built as a module and we aren't gonna add new controllers which don't
control resources.  This patch drops module support from cgroup.

* cgroup_[un]load_subsys() and cgroup_subsys->module removed.

* As there's no point in distinguishing IS_BUILTIN() and IS_MODULE(),
  cgroup_subsys.h now uses IS_ENABLED() directly.

* enum cgroup_subsys_id now exactly matches the list of enabled
  controllers as ordered in cgroup_subsys.h.

* cgroup_subsys[] is now a contiguously occupied array.  Size
  specification is no longer necessary and dropped.

* for_each_builtin_subsys() is removed and for_each_subsys() is
  updated to not require any locking.

* module ref handling is removed from rebind_subsystems().

* Module related comments dropped.

v2: Rebased on top of fe1217c4f3f7 ("net: net_cls: move cgroupfs
    classid handling into core").

v3: Added {} around the if (need_forkexit_callback) block in
    cgroup_post_fork() for readability as suggested by Li.

Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Li Zefan <lizefan@huawei.com>
block/blk-cgroup.c
include/linux/cgroup.h
include/linux/cgroup_subsys.h
kernel/cgroup.c
net/core/netclassid_cgroup.c
net/core/netprio_cgroup.c

index 4e491d9b529255476939b8608d91718c40140059..660d419918a7b9a71cea67545b1b9ebcda6090de 100644 (file)
@@ -914,7 +914,6 @@ struct cgroup_subsys blkio_subsys = {
        .can_attach = blkcg_can_attach,
        .subsys_id = blkio_subsys_id,
        .base_cftypes = blkcg_files,
-       .module = THIS_MODULE,
 };
 EXPORT_SYMBOL_GPL(blkio_subsys);
 
index 5c097596104b80535a0a00bdd45b4a2441fac889..d842a737d448d0eb395e723f92715e288f9c16df 100644 (file)
@@ -37,28 +37,13 @@ extern void cgroup_post_fork(struct task_struct *p);
 extern void cgroup_exit(struct task_struct *p, int run_callbacks);
 extern int cgroupstats_build(struct cgroupstats *stats,
                                struct dentry *dentry);
-extern int cgroup_load_subsys(struct cgroup_subsys *ss);
-extern void cgroup_unload_subsys(struct cgroup_subsys *ss);
 
 extern int proc_cgroup_show(struct seq_file *, void *);
 
-/*
- * Define the enumeration of all cgroup subsystems.
- *
- * We define ids for builtin subsystems and then modular ones.
- */
+/* define the enumeration of all cgroup subsystems */
 #define SUBSYS(_x) _x ## _subsys_id,
 enum cgroup_subsys_id {
-#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
 #include <linux/cgroup_subsys.h>
-#undef IS_SUBSYS_ENABLED
-       CGROUP_BUILTIN_SUBSYS_COUNT,
-
-       __CGROUP_SUBSYS_TEMP_PLACEHOLDER = CGROUP_BUILTIN_SUBSYS_COUNT - 1,
-
-#define IS_SUBSYS_ENABLED(option) IS_MODULE(option)
-#include <linux/cgroup_subsys.h>
-#undef IS_SUBSYS_ENABLED
        CGROUP_SUBSYS_COUNT,
 };
 #undef SUBSYS
@@ -370,10 +355,9 @@ struct css_set {
        struct list_head cgrp_links;
 
        /*
-        * Set of subsystem states, one for each subsystem. This array
-        * is immutable after creation apart from the init_css_set
-        * during subsystem registration (at boot time) and modular subsystem
-        * loading/unloading.
+        * Set of subsystem states, one for each subsystem. This array is
+        * immutable after creation apart from the init_css_set during
+        * subsystem registration (at boot time).
         */
        struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
 
@@ -620,15 +604,10 @@ struct cgroup_subsys {
        /* base cftypes, automatically [de]registered with subsys itself */
        struct cftype *base_cftypes;
        struct cftype_set base_cftset;
-
-       /* should be defined only by modular subsystems */
-       struct module *module;
 };
 
 #define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys;
-#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
 #include <linux/cgroup_subsys.h>
-#undef IS_SUBSYS_ENABLED
 #undef SUBSYS
 
 /**
index 7b99d717411d2b5ef3c14c0b2668a9c3bfe036e2..11c42f6a25a8c46bc6f4809a85f7eea981a9818a 100644 (file)
@@ -3,51 +3,51 @@
  *
  * DO NOT ADD ANY SUBSYSTEM WITHOUT EXPLICIT ACKS FROM CGROUP MAINTAINERS.
  */
-#if IS_SUBSYS_ENABLED(CONFIG_CPUSETS)
+#if IS_ENABLED(CONFIG_CPUSETS)
 SUBSYS(cpuset)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_DEBUG)
+#if IS_ENABLED(CONFIG_CGROUP_DEBUG)
 SUBSYS(debug)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_SCHED)
+#if IS_ENABLED(CONFIG_CGROUP_SCHED)
 SUBSYS(cpu_cgroup)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_CPUACCT)
+#if IS_ENABLED(CONFIG_CGROUP_CPUACCT)
 SUBSYS(cpuacct)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_MEMCG)
+#if IS_ENABLED(CONFIG_MEMCG)
 SUBSYS(mem_cgroup)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_DEVICE)
+#if IS_ENABLED(CONFIG_CGROUP_DEVICE)
 SUBSYS(devices)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_FREEZER)
+#if IS_ENABLED(CONFIG_CGROUP_FREEZER)
 SUBSYS(freezer)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_NET_CLASSID)
+#if IS_ENABLED(CONFIG_CGROUP_NET_CLASSID)
 SUBSYS(net_cls)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_BLK_CGROUP)
+#if IS_ENABLED(CONFIG_BLK_CGROUP)
 SUBSYS(blkio)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_PERF)
+#if IS_ENABLED(CONFIG_CGROUP_PERF)
 SUBSYS(perf)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_NET_PRIO)
+#if IS_ENABLED(CONFIG_CGROUP_NET_PRIO)
 SUBSYS(net_prio)
 #endif
 
-#if IS_SUBSYS_ENABLED(CONFIG_CGROUP_HUGETLB)
+#if IS_ENABLED(CONFIG_CGROUP_HUGETLB)
 SUBSYS(hugetlb)
 #endif
 /*
index e2f46ba37f7243c4278de77a8c8536ddc4c0aad5..ccb16b47e293d0331d1ee37094f8548dd4e4048e 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/string.h>
 #include <linux/sort.h>
 #include <linux/kmod.h>
-#include <linux/module.h>
 #include <linux/delayacct.h>
 #include <linux/cgroupstats.h>
 #include <linux/hashtable.h>
@@ -120,15 +119,9 @@ static struct workqueue_struct *cgroup_destroy_wq;
  */
 static struct workqueue_struct *cgroup_pidlist_destroy_wq;
 
-/*
- * Generate an array of cgroup subsystem pointers. At boot time, this is
- * populated with the built in subsystems, and modular subsystems are
- * registered after that. The mutable section of this array is protected by
- * cgroup_mutex.
- */
+/* generate an array of cgroup subsystem pointers */
 #define SUBSYS(_x) [_x ## _subsys_id] = &_x ## _subsys,
-#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
-static struct cgroup_subsys *cgroup_subsys[CGROUP_SUBSYS_COUNT] = {
+static struct cgroup_subsys *cgroup_subsys[] = {
 #include <linux/cgroup_subsys.h>
 };
 
@@ -258,30 +251,13 @@ static int notify_on_release(const struct cgroup *cgrp)
                else
 
 /**
- * for_each_subsys - iterate all loaded cgroup subsystems
+ * for_each_subsys - iterate all enabled cgroup subsystems
  * @ss: the iteration cursor
  * @ssid: the index of @ss, CGROUP_SUBSYS_COUNT after reaching the end
- *
- * Iterates through all loaded subsystems.  Should be called under
- * cgroup_mutex or cgroup_root_mutex.
  */
 #define for_each_subsys(ss, ssid)                                      \
-       for (({ cgroup_assert_mutex_or_root_locked(); (ssid) = 0; });   \
-            (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++)                    \
-               if (!((ss) = cgroup_subsys[(ssid)])) { }                \
-               else
-
-/**
- * for_each_builtin_subsys - iterate all built-in cgroup subsystems
- * @ss: the iteration cursor
- * @i: the index of @ss, CGROUP_BUILTIN_SUBSYS_COUNT after reaching the end
- *
- * Bulit-in subsystems are always present and iteration itself doesn't
- * require any synchronization.
- */
-#define for_each_builtin_subsys(ss, i)                                 \
-       for ((i) = 0; (i) < CGROUP_BUILTIN_SUBSYS_COUNT &&              \
-            (((ss) = cgroup_subsys[i]) || true); (i)++)
+       for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT &&                \
+            (((ss) = cgroup_subsys[ssid]) || true); (ssid)++)
 
 /* iterate across the active hierarchies */
 #define for_each_active_root(root)                                     \
@@ -975,50 +951,24 @@ static void cgroup_d_remove_dir(struct dentry *dentry)
        remove_dir(dentry);
 }
 
-/*
- * Call with cgroup_mutex held. Drops reference counts on modules, including
- * any duplicate ones that parse_cgroupfs_options took. If this function
- * returns an error, no reference counts are touched.
- */
 static int rebind_subsystems(struct cgroupfs_root *root,
                             unsigned long added_mask, unsigned removed_mask)
 {
        struct cgroup *cgrp = &root->top_cgroup;
        struct cgroup_subsys *ss;
-       unsigned long pinned = 0;
        int i, ret;
 
        BUG_ON(!mutex_is_locked(&cgroup_mutex));
        BUG_ON(!mutex_is_locked(&cgroup_root_mutex));
 
        /* Check that any added subsystems are currently free */
-       for_each_subsys(ss, i) {
-               if (!(added_mask & (1 << i)))
-                       continue;
-
-               /* is the subsystem mounted elsewhere? */
-               if (ss->root != &cgroup_dummy_root) {
-                       ret = -EBUSY;
-                       goto out_put;
-               }
-
-               /* pin the module */
-               if (!try_module_get(ss->module)) {
-                       ret = -ENOENT;
-                       goto out_put;
-               }
-               pinned |= 1 << i;
-       }
-
-       /* subsys could be missing if unloaded between parsing and here */
-       if (added_mask != pinned) {
-               ret = -ENOENT;
-               goto out_put;
-       }
+       for_each_subsys(ss, i)
+               if ((added_mask & (1 << i)) && ss->root != &cgroup_dummy_root)
+                       return -EBUSY;
 
        ret = cgroup_populate_dir(cgrp, added_mask);
        if (ret)
-               goto out_put;
+               return ret;
 
        /*
         * Nothing can fail from this point on.  Remove files for the
@@ -1057,9 +1007,6 @@ static int rebind_subsystems(struct cgroupfs_root *root,
                        RCU_INIT_POINTER(cgrp->subsys[i], NULL);
 
                        cgroup_subsys[i]->root = &cgroup_dummy_root;
-
-                       /* subsystem is now free - drop reference on module */
-                       module_put(ss->module);
                        root->subsys_mask &= ~bit;
                }
        }
@@ -1071,12 +1018,6 @@ static int rebind_subsystems(struct cgroupfs_root *root,
        root->flags |= CGRP_ROOT_SUBSYS_BOUND;
 
        return 0;
-
-out_put:
-       for_each_subsys(ss, i)
-               if (pinned & (1 << i))
-                       module_put(ss->module);
-       return ret;
 }
 
 static int cgroup_show_options(struct seq_file *seq, struct dentry *dentry)
@@ -4506,7 +4447,7 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry)
        return ret;
 }
 
-static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
+static void __init cgroup_init_cftsets(struct cgroup_subsys *ss)
 {
        INIT_LIST_HEAD(&ss->cftsets);
 
@@ -4559,185 +4500,8 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
        BUG_ON(online_css(css));
 
        mutex_unlock(&cgroup_mutex);
-
-       /* this function shouldn't be used with modular subsystems, since they
-        * need to register a subsys_id, among other things */
-       BUG_ON(ss->module);
 }
 
-/**
- * cgroup_load_subsys: load and register a modular subsystem at runtime
- * @ss: the subsystem to load
- *
- * This function should be called in a modular subsystem's initcall. If the
- * subsystem is built as a module, it will be assigned a new subsys_id and set
- * up for use. If the subsystem is built-in anyway, work is delegated to the
- * simpler cgroup_init_subsys.
- */
-int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
-{
-       struct cgroup_subsys_state *css;
-       int i, ret;
-       struct hlist_node *tmp;
-       struct css_set *cset;
-       unsigned long key;
-
-       /* check name and function validity */
-       if (ss->name == NULL || strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN ||
-           ss->css_alloc == NULL || ss->css_free == NULL)
-               return -EINVAL;
-
-       /*
-        * we don't support callbacks in modular subsystems. this check is
-        * before the ss->module check for consistency; a subsystem that could
-        * be a module should still have no callbacks even if the user isn't
-        * compiling it as one.
-        */
-       if (ss->fork || ss->exit)
-               return -EINVAL;
-
-       /*
-        * an optionally modular subsystem is built-in: we want to do nothing,
-        * since cgroup_init_subsys will have already taken care of it.
-        */
-       if (ss->module == NULL) {
-               /* a sanity check */
-               BUG_ON(cgroup_subsys[ss->subsys_id] != ss);
-               return 0;
-       }
-
-       /* init base cftset */
-       cgroup_init_cftsets(ss);
-
-       mutex_lock(&cgroup_mutex);
-       mutex_lock(&cgroup_root_mutex);
-       cgroup_subsys[ss->subsys_id] = ss;
-
-       /*
-        * no ss->css_alloc seems to need anything important in the ss
-        * struct, so this can happen first (i.e. before the dummy root
-        * attachment).
-        */
-       css = ss->css_alloc(cgroup_css(cgroup_dummy_top, ss));
-       if (IS_ERR(css)) {
-               /* failure case - need to deassign the cgroup_subsys[] slot. */
-               cgroup_subsys[ss->subsys_id] = NULL;
-               mutex_unlock(&cgroup_root_mutex);
-               mutex_unlock(&cgroup_mutex);
-               return PTR_ERR(css);
-       }
-
-       ss->root = &cgroup_dummy_root;
-
-       /* our new subsystem will be attached to the dummy hierarchy. */
-       init_css(css, ss, cgroup_dummy_top);
-
-       /*
-        * Now we need to entangle the css into the existing css_sets. unlike
-        * in cgroup_init_subsys, there are now multiple css_sets, so each one
-        * will need a new pointer to it; done by iterating the css_set_table.
-        * furthermore, modifying the existing css_sets will corrupt the hash
-        * table state, so each changed css_set will need its hash recomputed.
-        * this is all done under the css_set_lock.
-        */
-       write_lock(&css_set_lock);
-       hash_for_each_safe(css_set_table, i, tmp, cset, hlist) {
-               /* skip entries that we already rehashed */
-               if (cset->subsys[ss->subsys_id])
-                       continue;
-               /* remove existing entry */
-               hash_del(&cset->hlist);
-               /* set new value */
-               cset->subsys[ss->subsys_id] = css;
-               /* recompute hash and restore entry */
-               key = css_set_hash(cset->subsys);
-               hash_add(css_set_table, &cset->hlist, key);
-       }
-       write_unlock(&css_set_lock);
-
-       ret = online_css(css);
-       if (ret) {
-               ss->css_free(css);
-               goto err_unload;
-       }
-
-       /* success! */
-       mutex_unlock(&cgroup_root_mutex);
-       mutex_unlock(&cgroup_mutex);
-       return 0;
-
-err_unload:
-       mutex_unlock(&cgroup_root_mutex);
-       mutex_unlock(&cgroup_mutex);
-       /* @ss can't be mounted here as try_module_get() would fail */
-       cgroup_unload_subsys(ss);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(cgroup_load_subsys);
-
-/**
- * cgroup_unload_subsys: unload a modular subsystem
- * @ss: the subsystem to unload
- *
- * This function should be called in a modular subsystem's exitcall. When this
- * function is invoked, the refcount on the subsystem's module will be 0, so
- * the subsystem will not be attached to any hierarchy.
- */
-void cgroup_unload_subsys(struct cgroup_subsys *ss)
-{
-       struct cgrp_cset_link *link;
-       struct cgroup_subsys_state *css;
-
-       BUG_ON(ss->module == NULL);
-
-       /*
-        * we shouldn't be called if the subsystem is in use, and the use of
-        * try_module_get() in rebind_subsystems() should ensure that it
-        * doesn't start being used while we're killing it off.
-        */
-       BUG_ON(ss->root != &cgroup_dummy_root);
-
-       mutex_lock(&cgroup_mutex);
-       mutex_lock(&cgroup_root_mutex);
-
-       css = cgroup_css(cgroup_dummy_top, ss);
-       if (css)
-               offline_css(css);
-
-       /* deassign the subsys_id */
-       cgroup_subsys[ss->subsys_id] = NULL;
-
-       /*
-        * disentangle the css from all css_sets attached to the dummy
-        * top. as in loading, we need to pay our respects to the hashtable
-        * gods.
-        */
-       write_lock(&css_set_lock);
-       list_for_each_entry(link, &cgroup_dummy_top->cset_links, cset_link) {
-               struct css_set *cset = link->cset;
-               unsigned long key;
-
-               hash_del(&cset->hlist);
-               cset->subsys[ss->subsys_id] = NULL;
-               key = css_set_hash(cset->subsys);
-               hash_add(css_set_table, &cset->hlist, key);
-       }
-       write_unlock(&css_set_lock);
-
-       /*
-        * remove subsystem's css from the cgroup_dummy_top and free it -
-        * need to free before marking as null because ss->css_free needs
-        * the cgrp->subsys pointer to find their state.
-        */
-       if (css)
-               ss->css_free(css);
-       RCU_INIT_POINTER(cgroup_dummy_top->subsys[ss->subsys_id], NULL);
-
-       mutex_unlock(&cgroup_root_mutex);
-       mutex_unlock(&cgroup_mutex);
-}
-EXPORT_SYMBOL_GPL(cgroup_unload_subsys);
-
 /**
  * cgroup_init_early - cgroup initialization at system boot
  *
@@ -4763,8 +4527,7 @@ int __init cgroup_init_early(void)
        list_add(&init_cgrp_cset_link.cset_link, &cgroup_dummy_top->cset_links);
        list_add(&init_cgrp_cset_link.cgrp_link, &init_css_set.cgrp_links);
 
-       /* at bootup time, we don't worry about modular subsystems */
-       for_each_builtin_subsys(ss, i) {
+       for_each_subsys(ss, i) {
                BUG_ON(!ss->name);
                BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN);
                BUG_ON(!ss->css_alloc);
@@ -4797,7 +4560,7 @@ int __init cgroup_init(void)
        if (err)
                return err;
 
-       for_each_builtin_subsys(ss, i) {
+       for_each_subsys(ss, i) {
                if (!ss->early_init)
                        cgroup_init_subsys(ss);
        }
@@ -5032,15 +4795,7 @@ void cgroup_post_fork(struct task_struct *child)
         * and addition to css_set.
         */
        if (need_forkexit_callback) {
-               /*
-                * fork/exit callbacks are supported only for builtin
-                * subsystems, and the builtin section of the subsys
-                * array is immutable, so we don't need to lock the
-                * subsys array here. On the other hand, modular section
-                * of the array can be freed at module unload, so we
-                * can't touch that.
-                */
-               for_each_builtin_subsys(ss, i)
+               for_each_subsys(ss, i)
                        if (ss->fork)
                                ss->fork(child);
        }
@@ -5105,11 +4860,8 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
        RCU_INIT_POINTER(tsk->cgroups, &init_css_set);
 
        if (run_callbacks && need_forkexit_callback) {
-               /*
-                * fork/exit callbacks are supported only for builtin
-                * subsystems, see cgroup_post_fork() for details.
-                */
-               for_each_builtin_subsys(ss, i) {
+               /* see cgroup_post_fork() for details */
+               for_each_subsys(ss, i) {
                        if (ss->exit) {
                                struct cgroup_subsys_state *old_css = cset->subsys[i];
                                struct cgroup_subsys_state *css = task_css(tsk, i);
@@ -5228,11 +4980,7 @@ static int __init cgroup_disable(char *str)
                if (!*token)
                        continue;
 
-               /*
-                * cgroup_disable, being at boot time, can't know about
-                * module subsystems, so we don't worry about them.
-                */
-               for_each_builtin_subsys(ss, i) {
+               for_each_subsys(ss, i) {
                        if (!strcmp(token, ss->name)) {
                                ss->disabled = 1;
                                printk(KERN_INFO "Disabling %s control group"
index 9fc7f90d034c7c44495ff18d76f97e58746aa621..9e5ad5d74e60cd55e7ed0d29fc18d7b7642422dd 100644 (file)
@@ -110,5 +110,4 @@ struct cgroup_subsys net_cls_subsys = {
        .attach                 = cgrp_attach,
        .subsys_id              = net_cls_subsys_id,
        .base_cftypes           = ss_files,
-       .module                 = THIS_MODULE,
 };
index cc3a31e7dc08c1cdfd74130d30dd7d06298991dd..857e1603f9b7c495700f506e7f44a3e4ae14a31a 100644 (file)
@@ -252,7 +252,6 @@ struct cgroup_subsys net_prio_subsys = {
        .attach         = net_prio_attach,
        .subsys_id      = net_prio_subsys_id,
        .base_cftypes   = ss_files,
-       .module         = THIS_MODULE,
 };
 
 static int netprio_device_event(struct notifier_block *unused,