ucc_geth: fix non-functional fixed phy support
[safe/jmp/linux-2.6] / kernel / nsproxy.c
index ac99837..f5d332c 100644 (file)
 #include <linux/utsname.h>
 #include <linux/pid_namespace.h>
 #include <net/net_namespace.h>
+#include <linux/ipc_namespace.h>
 
 static struct kmem_cache *nsproxy_cachep;
 
 struct nsproxy init_nsproxy = INIT_NSPROXY(init_nsproxy);
 
-static inline void get_nsproxy(struct nsproxy *ns)
-{
-       atomic_inc(&ns->count);
-}
-
-void get_task_namespaces(struct task_struct *tsk)
-{
-       struct nsproxy *ns = tsk->nsproxy;
-       if (ns) {
-               get_nsproxy(ns);
-       }
-}
-
 /*
  * creates a copy of "orig" with refcount 1.
  */
@@ -87,7 +75,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
                goto out_ipc;
        }
 
-       new_nsp->pid_ns = copy_pid_ns(flags, tsk->nsproxy->pid_ns);
+       new_nsp->pid_ns = copy_pid_ns(flags, task_active_pid_ns(tsk));
        if (IS_ERR(new_nsp->pid_ns)) {
                err = PTR_ERR(new_nsp->pid_ns);
                goto out_pid;
@@ -142,7 +130,8 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
 
        get_nsproxy(old_ns);
 
-       if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER | CLONE_NEWNET)))
+       if (!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
+                               CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNET)))
                return 0;
 
        if (!capable(CAP_SYS_ADMIN)) {
@@ -216,6 +205,33 @@ out:
        return err;
 }
 
+void switch_task_namespaces(struct task_struct *p, struct nsproxy *new)
+{
+       struct nsproxy *ns;
+
+       might_sleep();
+
+       ns = p->nsproxy;
+
+       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();
+               free_nsproxy(ns);
+       }
+}
+
+void exit_task_namespaces(struct task_struct *p)
+{
+       switch_task_namespaces(p, NULL);
+}
+
 static int __init nsproxy_cache_init(void)
 {
        nsproxy_cachep = KMEM_CACHE(nsproxy, SLAB_PANIC);