cgroups: relax ns_can_attach checks to allow attaching to grandchild cgroups
[safe/jmp/linux-2.6] / kernel / cgroup.c
index 492215d..27792bc 100644 (file)
@@ -1071,7 +1071,8 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
                mutex_unlock(&cgroup_mutex);
        }
 
-       return simple_set_mnt(mnt, sb);
+       simple_set_mnt(mnt, sb);
+       return 0;
 
  free_cg_links:
        free_cg_links(&tmp_cg_links);
@@ -1115,13 +1116,15 @@ static void cgroup_kill_sb(struct super_block *sb) {
        }
        write_unlock(&css_set_lock);
 
-       list_del(&root->root_list);
-       root_count--;
+       if (!list_empty(&root->root_list)) {
+               list_del(&root->root_list);
+               root_count--;
+       }
 
        mutex_unlock(&cgroup_mutex);
 
-       kfree(root);
        kill_litter_super(sb);
+       kfree(root);
 }
 
 static struct file_system_type cgroup_fs_type = {
@@ -1625,7 +1628,7 @@ static struct inode_operations cgroup_dir_inode_operations = {
 static int cgroup_create_file(struct dentry *dentry, int mode,
                                struct super_block *sb)
 {
-       static struct dentry_operations cgroup_dops = {
+       static const struct dentry_operations cgroup_dops = {
                .d_iput = cgroup_diput,
        };
 
@@ -2349,7 +2352,7 @@ static void cgroup_lock_hierarchy(struct cgroupfs_root *root)
        for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                struct cgroup_subsys *ss = subsys[i];
                if (ss->root == root)
-                       mutex_lock_nested(&ss->hierarchy_mutex, i);
+                       mutex_lock(&ss->hierarchy_mutex);
        }
 }
 
@@ -2635,6 +2638,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
        BUG_ON(!list_empty(&init_task.tasks));
 
        mutex_init(&ss->hierarchy_mutex);
+       lockdep_set_class(&ss->hierarchy_mutex, &ss->subsys_key);
        ss->active = 1;
 }
 
@@ -3080,18 +3084,19 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
 }
 
 /**
- * cgroup_is_descendant - see if @cgrp is a descendant of current task's cgrp
+ * cgroup_is_descendant - see if @cgrp is a descendant of @task's cgrp
  * @cgrp: the cgroup in question
+ * @task: the task in question
  *
- * See if @cgrp is a descendant of the current task's cgroup in
- * the appropriate hierarchy.
+ * See if @cgrp is a descendant of @task's cgroup in the appropriate
+ * hierarchy.
  *
  * If we are sending in dummytop, then presumably we are creating
  * the top cgroup in the subsystem.
  *
  * Called only by the ns (nsproxy) cgroup.
  */
-int cgroup_is_descendant(const struct cgroup *cgrp)
+int cgroup_is_descendant(const struct cgroup *cgrp, struct task_struct *task)
 {
        int ret;
        struct cgroup *target;
@@ -3101,7 +3106,7 @@ int cgroup_is_descendant(const struct cgroup *cgrp)
                return 1;
 
        get_first_subsys(cgrp, NULL, &subsys_id);
-       target = task_cgroup(current, subsys_id);
+       target = task_cgroup(task, subsys_id);
        while (cgrp != target && cgrp!= cgrp->top_cgroup)
                cgrp = cgrp->parent;
        ret = (cgrp == target);