mm: replace vma prio_tree with an interval tree
[firefly-linux-kernel-4.4.55.git] / kernel / cgroup.c
index ced292d720b9f722cb1f61c8b482f84c873cde76..13774b3b39aac9b73e25ba34a366d5402b70df00 100644 (file)
@@ -88,11 +88,12 @@ static DEFINE_MUTEX(cgroup_root_mutex);
 
 /*
  * Generate an array of cgroup subsystem pointers. At boot time, this is
- * populated up to CGROUP_BUILTIN_SUBSYS_COUNT, and modular subsystems are
+ * populated with the built in subsystems, and modular subsystems are
  * registered after that. The mutable section of this array is protected by
  * cgroup_mutex.
  */
-#define SUBSYS(_x) &_x ## _subsys,
+#define SUBSYS(_x) [_x ## _subsys_id] = &_x ## _subsys,
+#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
 static struct cgroup_subsys *subsys[CGROUP_SUBSYS_COUNT] = {
 #include <linux/cgroup_subsys.h>
 };
@@ -1321,7 +1322,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
         * take duplicate reference counts on a subsystem that's already used,
         * but rebind_subsystems handles this case.
         */
-       for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
+       for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                unsigned long bit = 1UL << i;
 
                if (!(bit & opts->subsys_mask))
@@ -1337,7 +1338,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
                 * raced with a module_delete call, and to the user this is
                 * essentially a "subsystem doesn't exist" case.
                 */
-               for (i--; i >= CGROUP_BUILTIN_SUBSYS_COUNT; i--) {
+               for (i--; i >= 0; i--) {
                        /* drop refcounts only on the ones we took */
                        unsigned long bit = 1UL << i;
 
@@ -1354,7 +1355,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
 static void drop_parsed_module_refcounts(unsigned long subsys_mask)
 {
        int i;
-       for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
+       for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                unsigned long bit = 1UL << i;
 
                if (!(bit & subsys_mask))
@@ -4075,8 +4076,9 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
                set_bit(CGRP_CLONE_CHILDREN, &cgrp->flags);
 
        for_each_subsys(root, ss) {
-               struct cgroup_subsys_state *css = ss->create(cgrp);
+               struct cgroup_subsys_state *css;
 
+               css = ss->create(cgrp);
                if (IS_ERR(css)) {
                        err = PTR_ERR(css);
                        goto err_destroy;
@@ -4090,6 +4092,15 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
                /* At error, ->destroy() callback has to free assigned ID. */
                if (clone_children(parent) && ss->post_clone)
                        ss->post_clone(cgrp);
+
+               if (ss->broken_hierarchy && !ss->warned_broken_hierarchy &&
+                   parent->parent) {
+                       pr_warning("cgroup: %s (%d) created nested cgroup for controller \"%s\" which has incomplete hierarchy support. Nested cgroups may change behavior in the future.\n",
+                                  current->comm, current->pid, ss->name);
+                       if (!strcmp(ss->name, "memory"))
+                               pr_warning("cgroup: \"memory\" requires setting use_hierarchy to 1 on the root.\n");
+                       ss->warned_broken_hierarchy = true;
+               }
        }
 
        list_add(&cgrp->sibling, &cgrp->parent->children);
@@ -4442,8 +4453,7 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
         * since cgroup_init_subsys will have already taken care of it.
         */
        if (ss->module == NULL) {
-               /* a few sanity checks */
-               BUG_ON(ss->subsys_id >= CGROUP_BUILTIN_SUBSYS_COUNT);
+               /* a sanity check */
                BUG_ON(subsys[ss->subsys_id] != ss);
                return 0;
        }
@@ -4451,24 +4461,8 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
        /* init base cftset */
        cgroup_init_cftsets(ss);
 
-       /*
-        * need to register a subsys id before anything else - for example,
-        * init_cgroup_css needs it.
-        */
        mutex_lock(&cgroup_mutex);
-       /* find the first empty slot in the array */
-       for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) {
-               if (subsys[i] == NULL)
-                       break;
-       }
-       if (i == CGROUP_SUBSYS_COUNT) {
-               /* maximum number of subsystems already registered! */
-               mutex_unlock(&cgroup_mutex);
-               return -EBUSY;
-       }
-       /* assign ourselves the subsys_id */
-       ss->subsys_id = i;
-       subsys[i] = ss;
+       subsys[ss->subsys_id] = ss;
 
        /*
         * no ss->create seems to need anything important in the ss struct, so
@@ -4477,7 +4471,7 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
        css = ss->create(dummytop);
        if (IS_ERR(css)) {
                /* failure case - need to deassign the subsys[] slot. */
-               subsys[i] = NULL;
+               subsys[ss->subsys_id] = NULL;
                mutex_unlock(&cgroup_mutex);
                return PTR_ERR(css);
        }
@@ -4493,7 +4487,7 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
                if (ret) {
                        dummytop->subsys[ss->subsys_id] = NULL;
                        ss->destroy(dummytop);
-                       subsys[i] = NULL;
+                       subsys[ss->subsys_id] = NULL;
                        mutex_unlock(&cgroup_mutex);
                        return ret;
                }
@@ -4560,7 +4554,6 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
 
        mutex_lock(&cgroup_mutex);
        /* deassign the subsys_id */
-       BUG_ON(ss->subsys_id < CGROUP_BUILTIN_SUBSYS_COUNT);
        subsys[ss->subsys_id] = NULL;
 
        /* remove subsystem from rootnode's list of subsystems */
@@ -4623,10 +4616,13 @@ int __init cgroup_init_early(void)
        for (i = 0; i < CSS_SET_TABLE_SIZE; i++)
                INIT_HLIST_HEAD(&css_set_table[i]);
 
-       /* at bootup time, we don't worry about modular subsystems */
-       for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+       for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                struct cgroup_subsys *ss = subsys[i];
 
+               /* at bootup time, we don't worry about modular subsystems */
+               if (!ss || ss->module)
+                       continue;
+
                BUG_ON(!ss->name);
                BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN);
                BUG_ON(!ss->create);
@@ -4659,9 +4655,12 @@ int __init cgroup_init(void)
        if (err)
                return err;
 
-       /* at bootup time, we don't worry about modular subsystems */
-       for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+       for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                struct cgroup_subsys *ss = subsys[i];
+
+               /* at bootup time, we don't worry about modular subsystems */
+               if (!ss || ss->module)
+                       continue;
                if (!ss->early_init)
                        cgroup_init_subsys(ss);
                if (ss->use_id)
@@ -4856,13 +4855,16 @@ void cgroup_fork_callbacks(struct task_struct *child)
 {
        if (need_forkexit_callback) {
                int i;
-               /*
-                * forkexit callbacks are only supported for builtin
-                * subsystems, and the builtin section of the subsys array is
-                * immutable, so we don't need to lock the subsys array here.
-                */
-               for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+               for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                        struct cgroup_subsys *ss = subsys[i];
+
+                       /*
+                        * forkexit callbacks are only supported for
+                        * builtin subsystems.
+                        */
+                       if (!ss || ss->module)
+                               continue;
+
                        if (ss->fork)
                                ss->fork(child);
                }
@@ -4967,12 +4969,13 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
        tsk->cgroups = &init_css_set;
 
        if (run_callbacks && need_forkexit_callback) {
-               /*
-                * modular subsystems can't use callbacks, so no need to lock
-                * the subsys array
-                */
-               for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+               for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                        struct cgroup_subsys *ss = subsys[i];
+
+                       /* modular subsystems can't use callbacks */
+                       if (!ss || ss->module)
+                               continue;
+
                        if (ss->exit) {
                                struct cgroup *old_cgrp =
                                        rcu_dereference_raw(cg->subsys[i])->cgroup;
@@ -5158,13 +5161,17 @@ static int __init cgroup_disable(char *str)
        while ((token = strsep(&str, ",")) != NULL) {
                if (!*token)
                        continue;
-               /*
-                * cgroup_disable, being at boot time, can't know about module
-                * subsystems, so we don't worry about them.
-                */
-               for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+               for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                        struct cgroup_subsys *ss = subsys[i];
 
+                       /*
+                        * cgroup_disable, being at boot time, can't
+                        * know about module subsystems, so we don't
+                        * worry about them.
+                        */
+                       if (!ss || ss->module)
+                               continue;
+
                        if (!strcmp(token, ss->name)) {
                                ss->disabled = 1;
                                printk(KERN_INFO "Disabling %s control group"