struct list_head css_sets;
 
        struct list_head allcg_node;    /* cgroupfs_root->allcg_list */
+       struct list_head cft_q_node;    /* used during cftype add/rm */
 
        /*
         * Linked list running through all cgroups that can
  *     - the 'cftype' of the file is file->f_dentry->d_fsdata
  */
 
-#define MAX_CFTYPE_NAME 64
+/* cftype->flags */
+#define CFTYPE_ONLY_ON_ROOT    (1U << 0)       /* only create on root cg */
+#define CFTYPE_NOT_ON_ROOT     (1U << 1)       /* don't create onp root cg */
+
+#define MAX_CFTYPE_NAME                64
+
 struct cftype {
        /*
         * By convention, the name should begin with the name of the
-        * subsystem, followed by a period
+        * subsystem, followed by a period.  Zero length string indicates
+        * end of cftype array.
         */
        char name[MAX_CFTYPE_NAME];
        int private;
         */
        size_t max_write_len;
 
+       /* CFTYPE_* flags */
+       unsigned int flags;
+
        int (*open)(struct inode *inode, struct file *file);
        ssize_t (*read)(struct cgroup *cgrp, struct cftype *cft,
                        struct file *file,
                        struct eventfd_ctx *eventfd);
 };
 
+/*
+ * cftype_sets describe cftypes belonging to a subsystem and are chained at
+ * cgroup_subsys->cftsets.  Each cftset points to an array of cftypes
+ * terminated by zero length name.
+ */
+struct cftype_set {
+       struct list_head                node;   /* chained at subsys->cftsets */
+       const struct cftype             *cfts;
+};
+
 struct cgroup_scanner {
        struct cgroup *cg;
        int (*test_task)(struct task_struct *p, struct cgroup_scanner *scan);
                        const struct cftype cft[],
                        int count);
 
+int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts);
+
 int cgroup_is_removed(const struct cgroup *cgrp);
 
 int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen);
        struct idr idr;
        spinlock_t id_lock;
 
+       /* list of cftype_sets */
+       struct list_head cftsets;
+
+       /* 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;
 };
 
        struct dentry *dentry;
        int error;
        umode_t mode;
-
        char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
+
+       /* does @cft->flags tell us to skip creation on @cgrp? */
+       if ((cft->flags & CFTYPE_NOT_ON_ROOT) && !cgrp->parent)
+               return 0;
+       if ((cft->flags & CFTYPE_ONLY_ON_ROOT) && cgrp->parent)
+               return 0;
+
        if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) {
                strcpy(name, subsys->name);
                strcat(name, ".");
 }
 EXPORT_SYMBOL_GPL(cgroup_add_files);
 
+static DEFINE_MUTEX(cgroup_cft_mutex);
+
+static void cgroup_cfts_prepare(void)
+       __acquires(&cgroup_cft_mutex) __acquires(&cgroup_mutex)
+{
+       /*
+        * Thanks to the entanglement with vfs inode locking, we can't walk
+        * the existing cgroups under cgroup_mutex and create files.
+        * Instead, we increment reference on all cgroups and build list of
+        * them using @cgrp->cft_q_node.  Grab cgroup_cft_mutex to ensure
+        * exclusive access to the field.
+        */
+       mutex_lock(&cgroup_cft_mutex);
+       mutex_lock(&cgroup_mutex);
+}
+
+static void cgroup_cfts_commit(struct cgroup_subsys *ss,
+                              const struct cftype *cfts)
+       __releases(&cgroup_mutex) __releases(&cgroup_cft_mutex)
+{
+       LIST_HEAD(pending);
+       struct cgroup *cgrp, *n;
+       int count = 0;
+
+       while (cfts[count].name[0] != '\0')
+               count++;
+
+       /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */
+       if (cfts && ss->root != &rootnode) {
+               list_for_each_entry(cgrp, &ss->root->allcg_list, allcg_node) {
+                       dget(cgrp->dentry);
+                       list_add_tail(&cgrp->cft_q_node, &pending);
+               }
+       }
+
+       mutex_unlock(&cgroup_mutex);
+
+       /*
+        * All new cgroups will see @cfts update on @ss->cftsets.  Add/rm
+        * files for all cgroups which were created before.
+        */
+       list_for_each_entry_safe(cgrp, n, &pending, cft_q_node) {
+               struct inode *inode = cgrp->dentry->d_inode;
+
+               mutex_lock(&inode->i_mutex);
+               mutex_lock(&cgroup_mutex);
+               if (!cgroup_is_removed(cgrp))
+                       cgroup_add_files(cgrp, ss, cfts, count);
+               mutex_unlock(&cgroup_mutex);
+               mutex_unlock(&inode->i_mutex);
+
+               list_del_init(&cgrp->cft_q_node);
+               dput(cgrp->dentry);
+       }
+
+       mutex_unlock(&cgroup_cft_mutex);
+}
+
+/**
+ * cgroup_add_cftypes - add an array of cftypes to a subsystem
+ * @ss: target cgroup subsystem
+ * @cfts: zero-length name terminated array of cftypes
+ *
+ * Register @cfts to @ss.  Files described by @cfts are created for all
+ * existing cgroups to which @ss is attached and all future cgroups will
+ * have them too.  This function can be called anytime whether @ss is
+ * attached or not.
+ *
+ * Returns 0 on successful registration, -errno on failure.  Note that this
+ * function currently returns 0 as long as @cfts registration is successful
+ * even if some file creation attempts on existing cgroups fail.
+ */
+int cgroup_add_cftypes(struct cgroup_subsys *ss, const struct cftype *cfts)
+{
+       struct cftype_set *set;
+
+       set = kzalloc(sizeof(*set), GFP_KERNEL);
+       if (!set)
+               return -ENOMEM;
+
+       cgroup_cfts_prepare();
+       set->cfts = cfts;
+       list_add_tail(&set->node, &ss->cftsets);
+       cgroup_cfts_commit(ss, cfts);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cgroup_add_cftypes);
+
 /**
  * cgroup_task_count - count the number of tasks in a cgroup.
  * @cgrp: the cgroup in question
                        return err;
        }
 
+       /* process cftsets of each subsystem */
        for_each_subsys(cgrp->root, ss) {
+               struct cftype_set *set;
+
                if (ss->populate && (err = ss->populate(ss, cgrp)) < 0)
                        return err;
+
+               list_for_each_entry(set, &ss->cftsets, node) {
+                       const struct cftype *cft;
+
+                       for (cft = set->cfts; cft->name[0] != '\0'; cft++) {
+                               err = cgroup_add_file(cgrp, ss, cft);
+                               if (err)
+                                       pr_warning("cgroup_populate_dir: failed to create %s, err=%d\n",
+                                                  cft->name, err);
+                       }
+               }
        }
+
        /* This cgroup is ready now */
        for_each_subsys(cgrp->root, ss) {
                struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id];
        return 0;
 }
 
+static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
+{
+       INIT_LIST_HEAD(&ss->cftsets);
+
+       /*
+        * base_cftset is embedded in subsys itself, no need to worry about
+        * deregistration.
+        */
+       if (ss->base_cftypes) {
+               ss->base_cftset.cfts = ss->base_cftypes;
+               list_add_tail(&ss->base_cftset.node, &ss->cftsets);
+       }
+}
+
 static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
 {
        struct cgroup_subsys_state *css;
 
        printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
 
+       /* init base cftset */
+       cgroup_init_cftsets(ss);
+
        /* Create the top cgroup state for this subsystem */
        list_add(&ss->sibling, &rootnode.subsys_list);
        ss->root = &rootnode;
                return 0;
        }
 
+       /* init base cftset */
+       cgroup_init_cftsets(ss);
+
        /*
         * need to register a subsys id before anything else - for example,
         * init_cgroup_css needs it.