Merge tag 'md/3.17' of git://neil.brown.name/md
[deliverable/linux.git] / kernel / nsproxy.c
index 997cbb951a3bd07783e02e5354c3ac369ae4e356..ef42d0ab3115709adbe4b4a27c71f3638a481954 100644 (file)
@@ -126,22 +126,16 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
        struct nsproxy *old_ns = tsk->nsproxy;
        struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
        struct nsproxy *new_ns;
-       int err = 0;
 
-       if (!old_ns)
+       if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+                             CLONE_NEWPID | CLONE_NEWNET)))) {
+               get_nsproxy(old_ns);
                return 0;
-
-       get_nsproxy(old_ns);
-
-       if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
-                               CLONE_NEWPID | CLONE_NEWNET)))
-               return 0;
-
-       if (!ns_capable(user_ns, CAP_SYS_ADMIN)) {
-               err = -EPERM;
-               goto out;
        }
 
+       if (!ns_capable(user_ns, CAP_SYS_ADMIN))
+               return -EPERM;
+
        /*
         * CLONE_NEWIPC must detach from the undolist: after switching
         * to a new ipc namespace, the semaphore arrays from the old
@@ -149,22 +143,16 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
         * means share undolist with parent, so we must forbid using
         * it along with CLONE_NEWIPC.
         */
-       if ((flags & CLONE_NEWIPC) && (flags & CLONE_SYSVSEM)) {
-               err = -EINVAL;
-               goto out;
-       }
+       if ((flags & (CLONE_NEWIPC | CLONE_SYSVSEM)) ==
+               (CLONE_NEWIPC | CLONE_SYSVSEM)) 
+               return -EINVAL;
 
        new_ns = create_new_namespaces(flags, tsk, user_ns, tsk->fs);
-       if (IS_ERR(new_ns)) {
-               err = PTR_ERR(new_ns);
-               goto out;
-       }
+       if (IS_ERR(new_ns))
+               return  PTR_ERR(new_ns);
 
        tsk->nsproxy = new_ns;
-
-out:
-       put_nsproxy(old_ns);
-       return err;
+       return 0;
 }
 
 void free_nsproxy(struct nsproxy *ns)
@@ -216,20 +204,13 @@ void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
 
        might_sleep();
 
+       task_lock(p);
        ns = p->nsproxy;
+       p->nsproxy = new;
+       task_unlock(p);
 
-       rcu_assign_pointer(p->nsproxy, new);
-
-       if (ns && atomic_dec_and_test(&ns->count)) {
-               /*
-                * wait for others to get what they want from this nsproxy.
-                *
-                * cannot release this nsproxy via the call_rcu() since
-                * put_mnt_ns() will want to sleep
-                */
-               synchronize_rcu();
+       if (ns && atomic_dec_and_test(&ns->count))
                free_nsproxy(ns);
-       }
 }
 
 void exit_task_namespaces(struct task_struct *p)
This page took 0.036779 seconds and 5 git commands to generate.