struct list_head children;      /* my children */
 
        struct cgroup *parent;  /* my parent */
-       struct dentry *dentry;          /* cgroup fs entry */
+       struct dentry *dentry;          /* cgroup fs entry, RCU protected */
 
        /* Private pointers for each registered subsystem */
        struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
        int pids_use_count;
        /* Length of the current tasks_pids array */
        int pids_length;
+
+       /* For RCU-protected deletion */
+       struct rcu_head rcu_head;
 };
 
 /* A css_set is a structure holding pointers to a set of
 
 
        rcu_read_lock();
        for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
-               struct cgroup *cgrp = cg->subsys[i]->cgroup;
+               struct cgroup *cgrp = rcu_dereference(cg->subsys[i]->cgroup);
                if (atomic_dec_and_test(&cgrp->count) &&
                    notify_on_release(cgrp)) {
                        if (taskexit)
        return;
 }
 
+static void free_cgroup_rcu(struct rcu_head *obj)
+{
+       struct cgroup *cgrp = container_of(obj, struct cgroup, rcu_head);
+
+       kfree(cgrp);
+}
+
 static void cgroup_diput(struct dentry *dentry, struct inode *inode)
 {
        /* is dentry a directory ? if so, kfree() associated cgroup */
                cgrp->root->number_of_cgroups--;
                mutex_unlock(&cgroup_mutex);
 
-               /* Drop the active superblock reference that we took when we
-                * created the cgroup */
+               /*
+                * Drop the active superblock reference that we took when we
+                * created the cgroup
+                */
                deactivate_super(cgrp->root->sb);
 
-               kfree(cgrp);
+               call_rcu(&cgrp->rcu_head, free_cgroup_rcu);
        }
        iput(inode);
 }
  * @buf: the buffer to write the path into
  * @buflen: the length of the buffer
  *
- * Called with cgroup_mutex held. Writes path of cgroup into buf.
- * Returns 0 on success, -errno on error.
+ * Called with cgroup_mutex held or else with an RCU-protected cgroup
+ * reference.  Writes path of cgroup into buf.  Returns 0 on success,
+ * -errno on error.
  */
 int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
 {
        char *start;
+       struct dentry *dentry = rcu_dereference(cgrp->dentry);
 
-       if (cgrp == dummytop) {
+       if (!dentry || cgrp == dummytop) {
                /*
                 * Inactive subsystems have no dentry for their root
                 * cgroup
 
        *--start = '\0';
        for (;;) {
-               int len = cgrp->dentry->d_name.len;
+               int len = dentry->d_name.len;
                if ((start -= len) < buf)
                        return -ENAMETOOLONG;
                memcpy(start, cgrp->dentry->d_name.name, len);
                cgrp = cgrp->parent;
                if (!cgrp)
                        break;
+               dentry = rcu_dereference(cgrp->dentry);
                if (!cgrp->parent)
                        continue;
                if (--start < buf)
        if (!error) {
                dentry->d_fsdata = cgrp;
                inc_nlink(parent->d_inode);
-               cgrp->dentry = dentry;
+               rcu_assign_pointer(cgrp->dentry, dentry);
                dget(dentry);
        }
        dput(dentry);