.subsys_id = blkio_subsys_id,
        .base_cftypes = blkcg_files,
        .module = THIS_MODULE,
+
+       /*
+        * blkio subsystem is utterly broken in terms of hierarchy support.
+        * It treats all cgroups equally regardless of where they're
+        * located in the hierarchy - all cgroups are treated as if they're
+        * right below the root.  Fix it and remove the following.
+        */
+       .broken_hierarchy = true,
 };
 EXPORT_SYMBOL_GPL(blkio_subsys);
 
 
         */
        bool __DEPRECATED_clear_css_refs;
 
+       /*
+        * If %false, this subsystem is properly hierarchical -
+        * configuration, resource accounting and restriction on a parent
+        * cgroup cover those of its children.  If %true, hierarchy support
+        * is broken in some ways - some subsystems ignore hierarchy
+        * completely while others are only implemented half-way.
+        *
+        * It's now disallowed to create nested cgroups if the subsystem is
+        * broken and cgroup core will emit a warning message on such
+        * cases.  Eventually, all subsystems will be made properly
+        * hierarchical and this will go away.
+        */
+       bool broken_hierarchy;
+       bool warned_broken_hierarchy;
+
 #define MAX_CGROUP_TYPE_NAMELEN 32
        const char *name;
 
 
                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;
                /* 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);
 
        .can_attach     = freezer_can_attach,
        .fork           = freezer_fork,
        .base_cftypes   = files,
+
+       /*
+        * freezer subsys doesn't handle hierarchy at all.  Frozen state
+        * should be inherited through the hierarchy - if a parent is
+        * frozen, all its children should be frozen.  Fix it and remove
+        * the following.
+        */
+       .broken_hierarchy = true,
 };
 
        .destroy        = perf_cgroup_destroy,
        .exit           = perf_cgroup_exit,
        .attach         = perf_cgroup_attach,
+
+       /*
+        * perf_event cgroup doesn't handle nesting correctly.
+        * ctx->nr_cgroups adjustments should be propagated through the
+        * cgroup hierarchy.  Fix it and remove the following.
+        */
+       .broken_hierarchy = true,
 };
 #endif /* CONFIG_CGROUP_PERF */
 
        } else {
                res_counter_init(&memcg->res, NULL);
                res_counter_init(&memcg->memsw, NULL);
+               /*
+                * Deeper hierachy with use_hierarchy == false doesn't make
+                * much sense so let cgroup subsystem know about this
+                * unfortunate state in our controller.
+                */
+               if (parent && parent != root_mem_cgroup)
+                       mem_cgroup_subsys.broken_hierarchy = true;
        }
        memcg->last_scanned_node = MAX_NUMNODES;
        INIT_LIST_HEAD(&memcg->oom_notify);
 
        .subsys_id      = net_prio_subsys_id,
 #endif
        .base_cftypes   = ss_files,
-       .module         = THIS_MODULE
+       .module         = THIS_MODULE,
+
+       /*
+        * net_prio has artificial limit on the number of cgroups and
+        * disallows nesting making it impossible to co-mount it with other
+        * hierarchical subsystems.  Remove the artificially low PRIOIDX_SZ
+        * limit and properly nest configuration such that children follow
+        * their parents' configurations by default and are allowed to
+        * override and remove the following.
+        */
+       .broken_hierarchy = true,
 };
 
 static int netprio_device_event(struct notifier_block *unused,
 
 #endif
        .base_cftypes   = ss_files,
        .module         = THIS_MODULE,
+
+       /*
+        * While net_cls cgroup has the rudimentary hierarchy support of
+        * inheriting the parent's classid on cgroup creation, it doesn't
+        * properly propagates config changes in ancestors to their
+        * descendents.  A child should follow the parent's configuration
+        * but be allowed to override it.  Fix it and remove the following.
+        */
+       .broken_hierarchy = true,
 };
 
 struct cls_cgroup_head {
 
        .destroy = devcgroup_destroy,
        .subsys_id = devices_subsys_id,
        .base_cftypes = dev_cgroup_files,
+
+       /*
+        * While devices cgroup has the rudimentary hierarchy support which
+        * checks the parent's restriction, it doesn't properly propagates
+        * config changes in ancestors to their descendents.  A child
+        * should only be allowed to add more restrictions to the parent's
+        * configuration.  Fix it and remove the following.
+        */
+       .broken_hierarchy = true,
 };
 
 int __devcgroup_inode_permission(struct inode *inode, int mask)