Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[safe/jmp/linux-2.6] / kernel / cgroup.c
index fe00b3b..87bb025 100644 (file)
@@ -571,9 +571,8 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
 
        if (inode) {
                inode->i_mode = mode;
-               inode->i_uid = current->fsuid;
-               inode->i_gid = current->fsgid;
-               inode->i_blocks = 0;
+               inode->i_uid = current_fsuid();
+               inode->i_gid = current_fsgid();
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;
        }
@@ -702,7 +701,7 @@ static int rebind_subsystems(struct cgroupfs_root *root,
         * any child cgroups exist. This is theoretically supportable
         * but involves complex error handling, so it's being left until
         * later */
-       if (!list_empty(&cgrp->children))
+       if (root->number_of_cgroups > 1)
                return -EBUSY;
 
        /* Process each subsystem */
@@ -1024,7 +1023,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
                if (ret == -EBUSY) {
                        mutex_unlock(&cgroup_mutex);
                        mutex_unlock(&inode->i_mutex);
-                       goto drop_new_super;
+                       goto free_cg_links;
                }
 
                /* EBUSY should be the only error here */
@@ -1073,10 +1072,11 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
 
        return simple_set_mnt(mnt, sb);
 
+ free_cg_links:
+       free_cg_links(&tmp_cg_links);
  drop_new_super:
        up_write(&sb->s_umount);
        deactivate_super(sb);
-       free_cg_links(&tmp_cg_links);
        return ret;
 }
 
@@ -1279,6 +1279,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
 static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
 {
        struct task_struct *tsk;
+       const struct cred *cred = current_cred(), *tcred;
        int ret;
 
        if (pid) {
@@ -1288,14 +1289,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
                        rcu_read_unlock();
                        return -ESRCH;
                }
-               get_task_struct(tsk);
-               rcu_read_unlock();
 
-               if ((current->euid) && (current->euid != tsk->uid)
-                   && (current->euid != tsk->suid)) {
-                       put_task_struct(tsk);
+               tcred = __task_cred(tsk);
+               if (cred->euid &&
+                   cred->euid != tcred->uid &&
+                   cred->euid != tcred->suid) {
+                       rcu_read_unlock();
                        return -EACCES;
                }
+               get_task_struct(tsk);
+               rcu_read_unlock();
        } else {
                tsk = current;
                get_task_struct(tsk);
@@ -2934,9 +2937,6 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
  again:
        root = subsys->root;
        if (root == &rootnode) {
-               printk(KERN_INFO
-                      "Not cloning cgroup for unused subsystem %s\n",
-                      subsys->name);
                mutex_unlock(&cgroup_mutex);
                return 0;
        }
@@ -2944,7 +2944,11 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
        parent = task_cgroup(tsk, subsys->subsys_id);
 
        /* Pin the hierarchy */
-       atomic_inc(&parent->root->sb->s_active);
+       if (!atomic_inc_not_zero(&parent->root->sb->s_active)) {
+               /* We race with the final deactivate_super() */
+               mutex_unlock(&cgroup_mutex);
+               return 0;
+       }
 
        /* Keep the cgroup alive */
        get_css_set(cg);