Merge tag 'fixes-nc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[firefly-linux-kernel-4.4.55.git] / kernel / cgroup.c
index ae7617095dec55956350a384b420d3622ef18bf1..2a9926275f806f41e7c15b6eed584acaf8796bc0 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/cred.h>
 #include <linux/ctype.h>
 #include <linux/errno.h>
-#include <linux/fs.h>
 #include <linux/init_task.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
  * B happens only through cgroup_show_options() and using cgroup_root_mutex
  * breaks it.
  */
+#ifdef CONFIG_PROVE_RCU
+DEFINE_MUTEX(cgroup_mutex);
+EXPORT_SYMBOL_GPL(cgroup_mutex);       /* only for task_subsys_state_check() */
+#else
 static DEFINE_MUTEX(cgroup_mutex);
+#endif
+
 static DEFINE_MUTEX(cgroup_root_mutex);
 
 /*
@@ -98,56 +103,6 @@ static struct cgroup_subsys *subsys[CGROUP_SUBSYS_COUNT] = {
 #include <linux/cgroup_subsys.h>
 };
 
-#define MAX_CGROUP_ROOT_NAMELEN 64
-
-/*
- * A cgroupfs_root represents the root of a cgroup hierarchy,
- * and may be associated with a superblock to form an active
- * hierarchy
- */
-struct cgroupfs_root {
-       struct super_block *sb;
-
-       /*
-        * The bitmask of subsystems intended to be attached to this
-        * hierarchy
-        */
-       unsigned long subsys_mask;
-
-       /* Unique id for this hierarchy. */
-       int hierarchy_id;
-
-       /* The bitmask of subsystems currently attached to this hierarchy */
-       unsigned long actual_subsys_mask;
-
-       /* A list running through the attached subsystems */
-       struct list_head subsys_list;
-
-       /* The root cgroup for this hierarchy */
-       struct cgroup top_cgroup;
-
-       /* Tracks how many cgroups are currently defined in hierarchy.*/
-       int number_of_cgroups;
-
-       /* A list running through the active hierarchies */
-       struct list_head root_list;
-
-       /* All cgroups on this root, cgroup_mutex protected */
-       struct list_head allcg_list;
-
-       /* Hierarchy-specific flags */
-       unsigned long flags;
-
-       /* IDs for cgroups in this hierarchy */
-       struct ida cgroup_ida;
-
-       /* The path to use for release notifications. */
-       char release_agent_path[PATH_MAX];
-
-       /* The name for this hierarchy - may be empty */
-       char name[MAX_CGROUP_ROOT_NAMELEN];
-};
-
 /*
  * The "rootnode" hierarchy is the "dummy hierarchy", reserved for the
  * subsystems that are otherwise unattached - it never has more than a
@@ -162,6 +117,9 @@ struct cfent {
        struct list_head                node;
        struct dentry                   *dentry;
        struct cftype                   *type;
+
+       /* file xattrs */
+       struct simple_xattrs            xattrs;
 };
 
 /*
@@ -251,20 +209,6 @@ static int cgroup_destroy_locked(struct cgroup *cgrp);
 static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
                              struct cftype cfts[], bool is_add);
 
-#ifdef CONFIG_PROVE_LOCKING
-int cgroup_lock_is_held(void)
-{
-       return lockdep_is_held(&cgroup_mutex);
-}
-#else /* #ifdef CONFIG_PROVE_LOCKING */
-int cgroup_lock_is_held(void)
-{
-       return mutex_is_locked(&cgroup_mutex);
-}
-#endif /* #else #ifdef CONFIG_PROVE_LOCKING */
-
-EXPORT_SYMBOL_GPL(cgroup_lock_is_held);
-
 static int css_unbias_refcnt(int refcnt)
 {
        return refcnt >= 0 ? refcnt : refcnt - CSS_DEACT_BIAS;
@@ -284,11 +228,25 @@ inline int cgroup_is_removed(const struct cgroup *cgrp)
        return test_bit(CGRP_REMOVED, &cgrp->flags);
 }
 
-/* bits in struct cgroupfs_root flags field */
-enum {
-       ROOT_NOPREFIX,  /* mounted subsystems have no named prefix */
-       ROOT_XATTR,     /* supports extended attributes */
-};
+/**
+ * cgroup_is_descendant - test ancestry
+ * @cgrp: the cgroup to be tested
+ * @ancestor: possible ancestor of @cgrp
+ *
+ * Test whether @cgrp is a descendant of @ancestor.  It also returns %true
+ * if @cgrp == @ancestor.  This function is safe to call as long as @cgrp
+ * and @ancestor are accessible.
+ */
+bool cgroup_is_descendant(struct cgroup *cgrp, struct cgroup *ancestor)
+{
+       while (cgrp) {
+               if (cgrp == ancestor)
+                       return true;
+               cgrp = cgrp->parent;
+       }
+       return false;
+}
+EXPORT_SYMBOL_GPL(cgroup_is_descendant);
 
 static int cgroup_is_releasable(const struct cgroup *cgrp)
 {
@@ -333,10 +291,10 @@ static inline struct cftype *__d_cft(struct dentry *dentry)
  * cgroup_lock_live_group - take cgroup_mutex and check that cgrp is alive.
  * @cgrp: the cgroup to be checked for liveness
  *
- * On success, returns true; the lock should be later released with
- * cgroup_unlock(). On failure returns false with no lock held.
+ * On success, returns true; the mutex should be later unlocked.  On
+ * failure returns false with no lock held.
  */
-bool cgroup_lock_live_group(struct cgroup *cgrp)
+static bool cgroup_lock_live_group(struct cgroup *cgrp)
 {
        mutex_lock(&cgroup_mutex);
        if (cgroup_is_removed(cgrp)) {
@@ -345,7 +303,6 @@ bool cgroup_lock_live_group(struct cgroup *cgrp)
        }
        return true;
 }
-EXPORT_SYMBOL_GPL(cgroup_lock_live_group);
 
 /* the list of cgroups eligible for automatic release. Protected by
  * release_list_lock */
@@ -820,27 +777,6 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task,
  * update of a tasks cgroup pointer by cgroup_attach_task()
  */
 
-/**
- * cgroup_lock - lock out any changes to cgroup structures
- *
- */
-void cgroup_lock(void)
-{
-       mutex_lock(&cgroup_mutex);
-}
-EXPORT_SYMBOL_GPL(cgroup_lock);
-
-/**
- * cgroup_unlock - release lock on cgroup changes
- *
- * Undo the lock taken in a previous cgroup_lock() call.
- */
-void cgroup_unlock(void)
-{
-       mutex_unlock(&cgroup_mutex);
-}
-EXPORT_SYMBOL_GPL(cgroup_unlock);
-
 /*
  * A couple of forward declarations required, due to cyclic reference loop:
  * cgroup_mkdir -> cgroup_create -> cgroup_populate_dir ->
@@ -905,9 +841,19 @@ static void cgroup_free_fn(struct work_struct *work)
        cgrp->root->number_of_cgroups--;
        mutex_unlock(&cgroup_mutex);
 
+       /*
+        * We get a ref to the parent's dentry, and put the ref when
+        * this cgroup is being freed, so it's guaranteed that the
+        * parent won't be destroyed before its children.
+        */
+       dput(cgrp->parent->dentry);
+
+       ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id);
+
        /*
         * Drop the active superblock reference that we took when we
-        * created the cgroup
+        * created the cgroup. This will free cgrp->root, if we are
+        * holding the last reference to @sb.
         */
        deactivate_super(cgrp->root->sb);
 
@@ -919,7 +865,6 @@ static void cgroup_free_fn(struct work_struct *work)
 
        simple_xattrs_free(&cgrp->xattrs);
 
-       ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id);
        kfree(rcu_dereference_raw(cgrp->name));
        kfree(cgrp);
 }
@@ -942,13 +887,12 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
        } else {
                struct cfent *cfe = __d_cfe(dentry);
                struct cgroup *cgrp = dentry->d_parent->d_fsdata;
-               struct cftype *cft = cfe->type;
 
                WARN_ONCE(!list_empty(&cfe->node) &&
                          cgrp != &cgrp->root->top_cgroup,
                          "cfe still linked for %s\n", cfe->type->name);
+               simple_xattrs_free(&cfe->xattrs);
                kfree(cfe);
-               simple_xattrs_free(&cft->xattrs);
        }
        iput(inode);
 }
@@ -1140,9 +1084,11 @@ static int cgroup_show_options(struct seq_file *seq, struct dentry *dentry)
        mutex_lock(&cgroup_root_mutex);
        for_each_subsys(root, ss)
                seq_printf(seq, ",%s", ss->name);
-       if (test_bit(ROOT_NOPREFIX, &root->flags))
+       if (root->flags & CGRP_ROOT_SANE_BEHAVIOR)
+               seq_puts(seq, ",sane_behavior");
+       if (root->flags & CGRP_ROOT_NOPREFIX)
                seq_puts(seq, ",noprefix");
-       if (test_bit(ROOT_XATTR, &root->flags))
+       if (root->flags & CGRP_ROOT_XATTR)
                seq_puts(seq, ",xattr");
        if (strlen(root->release_agent_path))
                seq_printf(seq, ",release_agent=%s", root->release_agent_path);
@@ -1204,8 +1150,12 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
                        all_ss = true;
                        continue;
                }
+               if (!strcmp(token, "__DEVEL__sane_behavior")) {
+                       opts->flags |= CGRP_ROOT_SANE_BEHAVIOR;
+                       continue;
+               }
                if (!strcmp(token, "noprefix")) {
-                       set_bit(ROOT_NOPREFIX, &opts->flags);
+                       opts->flags |= CGRP_ROOT_NOPREFIX;
                        continue;
                }
                if (!strcmp(token, "clone_children")) {
@@ -1213,7 +1163,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
                        continue;
                }
                if (!strcmp(token, "xattr")) {
-                       set_bit(ROOT_XATTR, &opts->flags);
+                       opts->flags |= CGRP_ROOT_XATTR;
                        continue;
                }
                if (!strncmp(token, "release_agent=", 14)) {
@@ -1291,13 +1241,26 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
 
        /* Consistency checks */
 
+       if (opts->flags & CGRP_ROOT_SANE_BEHAVIOR) {
+               pr_warning("cgroup: sane_behavior: this is still under development and its behaviors will change, proceed at your own risk\n");
+
+               if (opts->flags & CGRP_ROOT_NOPREFIX) {
+                       pr_err("cgroup: sane_behavior: noprefix is not allowed\n");
+                       return -EINVAL;
+               }
+
+               if (opts->cpuset_clone_children) {
+                       pr_err("cgroup: sane_behavior: clone_children is not allowed\n");
+                       return -EINVAL;
+               }
+       }
+
        /*
         * Option noprefix was introduced just for backward compatibility
         * with the old cpuset, so we allow noprefix only if mounting just
         * the cpuset subsystem.
         */
-       if (test_bit(ROOT_NOPREFIX, &opts->flags) &&
-           (opts->subsys_mask & mask))
+       if ((opts->flags & CGRP_ROOT_NOPREFIX) && (opts->subsys_mask & mask))
                return -EINVAL;
 
 
@@ -1368,6 +1331,11 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data)
        struct cgroup_sb_opts opts;
        unsigned long added_mask, removed_mask;
 
+       if (root->flags & CGRP_ROOT_SANE_BEHAVIOR) {
+               pr_err("cgroup: sane_behavior: remount is not allowed\n");
+               return -EINVAL;
+       }
+
        mutex_lock(&cgrp->dentry->d_inode->i_mutex);
        mutex_lock(&cgroup_mutex);
        mutex_lock(&cgroup_root_mutex);
@@ -1454,7 +1422,6 @@ static void init_cgroup_root(struct cgroupfs_root *root)
        root->number_of_cgroups = 1;
        cgrp->root = root;
        cgrp->name = &root_cgroup_name;
-       cgrp->top_cgroup = cgrp;
        init_cgroup_housekeeping(cgrp);
        list_add_tail(&cgrp->allcg_node, &root->allcg_list);
 }
@@ -1718,6 +1685,14 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
                 * any) is not needed
                 */
                cgroup_drop_root(opts.new_root);
+
+               if (((root->flags | opts.flags) & CGRP_ROOT_SANE_BEHAVIOR) &&
+                   root->flags != opts.flags) {
+                       pr_err("cgroup: sane_behavior: new mount options should match the existing superblock\n");
+                       ret = -EINVAL;
+                       goto drop_new_super;
+               }
+
                /* no subsys rebinding, so refcounts don't change */
                drop_parsed_module_refcounts(opts.subsys_mask);
        }
@@ -1814,11 +1789,17 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
        int ret = -ENAMETOOLONG;
        char *start;
 
+       if (!cgrp->parent) {
+               if (strlcpy(buf, "/", buflen) >= buflen)
+                       return -ENAMETOOLONG;
+               return 0;
+       }
+
        start = buf + buflen - 1;
        *start = '\0';
 
        rcu_read_lock();
-       while (cgrp) {
+       do {
                const char *name = cgroup_name(cgrp);
                int len;
 
@@ -1827,15 +1808,12 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
                        goto out;
                memcpy(start, name, len);
 
-               if (!cgrp->parent)
-                       break;
-
                if (--start < buf)
                        goto out;
                *start = '/';
 
                cgrp = cgrp->parent;
-       }
+       } while (cgrp->parent);
        ret = 0;
        memmove(buf, start, buf + buflen - start);
 out:
@@ -1970,8 +1948,8 @@ static void cgroup_task_migrate(struct cgroup *oldcgrp,
  * Call holding cgroup_mutex and the group_rwsem of the leader. Will take
  * task_lock of @tsk or each thread in the threadgroup individually in turn.
  */
-int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
-                      bool threadgroup)
+static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
+                             bool threadgroup)
 {
        int retval, i, group_size;
        struct cgroup_subsys *ss, *failed_ss = NULL;
@@ -2159,11 +2137,11 @@ retry_find_task:
                tsk = tsk->group_leader;
 
        /*
-        * Workqueue threads may acquire PF_THREAD_BOUND and become
+        * Workqueue threads may acquire PF_NO_SETAFFINITY and become
         * trapped in a cpuset, or RT worker may be born in a cgroup
         * with no rt_runtime allocated.  Just say no.
         */
-       if (tsk == kthreadd_task || (tsk->flags & PF_THREAD_BOUND)) {
+       if (tsk == kthreadd_task || (tsk->flags & PF_NO_SETAFFINITY)) {
                ret = -EINVAL;
                rcu_read_unlock();
                goto out_unlock_cgroup;
@@ -2194,7 +2172,7 @@ retry_find_task:
 
        put_task_struct(tsk);
 out_unlock_cgroup:
-       cgroup_unlock();
+       mutex_unlock(&cgroup_mutex);
        return ret;
 }
 
@@ -2208,7 +2186,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
        struct cgroupfs_root *root;
        int retval = 0;
 
-       cgroup_lock();
+       mutex_lock(&cgroup_mutex);
        for_each_active_root(root) {
                struct cgroup *from_cg = task_cgroup_from_root(from, root);
 
@@ -2216,7 +2194,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
                if (retval)
                        break;
        }
-       cgroup_unlock();
+       mutex_unlock(&cgroup_mutex);
 
        return retval;
 }
@@ -2243,7 +2221,7 @@ static int cgroup_release_agent_write(struct cgroup *cgrp, struct cftype *cft,
        mutex_lock(&cgroup_root_mutex);
        strcpy(cgrp->root->release_agent_path, buffer);
        mutex_unlock(&cgroup_root_mutex);
-       cgroup_unlock();
+       mutex_unlock(&cgroup_mutex);
        return 0;
 }
 
@@ -2254,7 +2232,14 @@ static int cgroup_release_agent_show(struct cgroup *cgrp, struct cftype *cft,
                return -ENODEV;
        seq_puts(seq, cgrp->root->release_agent_path);
        seq_putc(seq, '\n');
-       cgroup_unlock();
+       mutex_unlock(&cgroup_mutex);
+       return 0;
+}
+
+static int cgroup_sane_behavior_show(struct cgroup *cgrp, struct cftype *cft,
+                                    struct seq_file *seq)
+{
+       seq_printf(seq, "%d\n", cgroup_sane_behavior(cgrp));
        return 0;
 }
 
@@ -2520,13 +2505,13 @@ static struct simple_xattrs *__d_xattrs(struct dentry *dentry)
        if (S_ISDIR(dentry->d_inode->i_mode))
                return &__d_cgrp(dentry)->xattrs;
        else
-               return &__d_cft(dentry)->xattrs;
+               return &__d_cfe(dentry)->xattrs;
 }
 
 static inline int xattr_enabled(struct dentry *dentry)
 {
        struct cgroupfs_root *root = dentry->d_sb->s_fs_info;
-       return test_bit(ROOT_XATTR, &root->flags);
+       return root->flags & CGRP_ROOT_XATTR;
 }
 
 static bool is_valid_xattr(const char *name)
@@ -2696,9 +2681,7 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
        umode_t mode;
        char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 };
 
-       simple_xattrs_init(&cft->xattrs);
-
-       if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) {
+       if (subsys && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) {
                strcpy(name, subsys->name);
                strcat(name, ".");
        }
@@ -2722,6 +2705,7 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys,
                cfe->type = (void *)cft;
                cfe->dentry = dentry;
                dentry->d_fsdata = cfe;
+               simple_xattrs_init(&cfe->xattrs);
                list_add_tail(&cfe->node, &parent->files);
                cfe = NULL;
        }
@@ -2739,6 +2723,8 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys,
 
        for (cft = cfts; cft->name[0] != '\0'; cft++) {
                /* does cft->flags tell us to skip this file on @cgrp? */
+               if ((cft->flags & CFTYPE_INSANE) && cgroup_sane_behavior(cgrp))
+                       continue;
                if ((cft->flags & CFTYPE_NOT_ON_ROOT) && !cgrp->parent)
                        continue;
                if ((cft->flags & CFTYPE_ONLY_ON_ROOT) && cgrp->parent)
@@ -3274,9 +3260,9 @@ static void cgroup_transfer_one_task(struct task_struct *task,
 {
        struct cgroup *new_cgroup = scan->data;
 
-       cgroup_lock();
+       mutex_lock(&cgroup_mutex);
        cgroup_attach_task(new_cgroup, task, false);
-       cgroup_unlock();
+       mutex_unlock(&cgroup_mutex);
 }
 
 /**
@@ -3896,6 +3882,8 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft,
        if (ret)
                goto fail;
 
+       efile->f_op->poll(efile, &event->pt);
+
        /*
         * Events should be removed after rmdir of cgroup directory, but before
         * destroying subsystem state objects. Let's take reference to cgroup
@@ -3976,9 +3964,15 @@ static struct cftype files[] = {
        },
        {
                .name = "cgroup.clone_children",
+               .flags = CFTYPE_INSANE,
                .read_u64 = cgroup_clone_children_read,
                .write_u64 = cgroup_clone_children_write,
        },
+       {
+               .name = "cgroup.sane_behavior",
+               .flags = CFTYPE_ONLY_ON_ROOT,
+               .read_seq_string = cgroup_sane_behavior_show,
+       },
        {
                .name = "release_agent",
                .flags = CFTYPE_ONLY_ON_ROOT,
@@ -4155,7 +4149,6 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 
        cgrp->parent = parent;
        cgrp->root = parent->root;
-       cgrp->top_cgroup = parent->top_cgroup;
 
        if (notify_on_release(parent))
                set_bit(CGRP_NOTIFY_ON_RELEASE, &cgrp->flags);
@@ -4198,6 +4191,9 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
        for_each_subsys(root, ss)
                dget(dentry);
 
+       /* hold a ref to the parent's dentry */
+       dget(parent->dentry);
+
        /* creation succeeded, notify subsystems */
        for_each_subsys(root, ss) {
                err = online_css(ss, cgrp);
@@ -4384,7 +4380,6 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
         * need to invoke fork callbacks here. */
        BUG_ON(!list_empty(&init_task.tasks));
 
-       ss->active = 1;
        BUG_ON(online_css(ss, dummytop));
 
        mutex_unlock(&cgroup_mutex);
@@ -4489,7 +4484,6 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss)
        }
        write_unlock(&css_set_lock);
 
-       ss->active = 1;
        ret = online_css(ss, dummytop);
        if (ret)
                goto err_unload;
@@ -4530,7 +4524,6 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
        mutex_lock(&cgroup_mutex);
 
        offline_css(ss, dummytop);
-       ss->active = 0;
 
        if (ss->use_id)
                idr_destroy(&ss->idr);
@@ -4685,7 +4678,7 @@ out:
  */
 
 /* TODO: Use a proper seq_file iterator */
-static int proc_cgroup_show(struct seq_file *m, void *v)
+int proc_cgroup_show(struct seq_file *m, void *v)
 {
        struct pid *pid;
        struct task_struct *tsk;
@@ -4737,19 +4730,6 @@ out:
        return retval;
 }
 
-static int cgroup_open(struct inode *inode, struct file *file)
-{
-       struct pid *pid = PROC_I(inode)->pid;
-       return single_open(file, proc_cgroup_show, pid);
-}
-
-const struct file_operations proc_cgroup_operations = {
-       .open           = cgroup_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
 /* Display information about each subsystem and each hierarchy */
 static int proc_cgroupstats_show(struct seq_file *m, void *v)
 {
@@ -5294,55 +5274,6 @@ struct cgroup_subsys_state *css_lookup(struct cgroup_subsys *ss, int id)
 }
 EXPORT_SYMBOL_GPL(css_lookup);
 
-/**
- * css_get_next - lookup next cgroup under specified hierarchy.
- * @ss: pointer to subsystem
- * @id: current position of iteration.
- * @root: pointer to css. search tree under this.
- * @foundid: position of found object.
- *
- * Search next css under the specified hierarchy of rootid. Calling under
- * rcu_read_lock() is necessary. Returns NULL if it reaches the end.
- */
-struct cgroup_subsys_state *
-css_get_next(struct cgroup_subsys *ss, int id,
-            struct cgroup_subsys_state *root, int *foundid)
-{
-       struct cgroup_subsys_state *ret = NULL;
-       struct css_id *tmp;
-       int tmpid;
-       int rootid = css_id(root);
-       int depth = css_depth(root);
-
-       if (!rootid)
-               return NULL;
-
-       BUG_ON(!ss->use_id);
-       WARN_ON_ONCE(!rcu_read_lock_held());
-
-       /* fill start point for scan */
-       tmpid = id;
-       while (1) {
-               /*
-                * scan next entry from bitmap(tree), tmpid is updated after
-                * idr_get_next().
-                */
-               tmp = idr_get_next(&ss->idr, &tmpid);
-               if (!tmp)
-                       break;
-               if (tmp->depth >= depth && tmp->stack[depth] == rootid) {
-                       ret = rcu_dereference(tmp->css);
-                       if (ret) {
-                               *foundid = tmpid;
-                               break;
-                       }
-               }
-               /* continue to scan from next id */
-               tmpid = tmpid + 1;
-       }
-       return ret;
-}
-
 /*
  * get corresponding css from file open on cgroupfs directory
  */