aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2007-10-19 02:39:54 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:37 -0400
commitcf7b708c8d1d7a27736771bcf4c457b332b0f818 (patch)
tree10f80257b052313b283f18ddfe35145882e0b47f /net/core/rtnetlink.c
parenta6f5e06378970a2687332c2d54046245fcff1e7e (diff)
Make access to task's nsproxy lighter
When someone wants to deal with some other taks's namespaces it has to lock the task and then to get the desired namespace if the one exists. This is slow on read-only paths and may be impossible in some cases. E.g. Oleg recently noticed a race between unshare() and the (sent for review in cgroups) pid namespaces - when the task notifies the parent it has to know the parent's namespace, but taking the task_lock() is impossible there - the code is under write locked tasklist lock. On the other hand switching the namespace on task (daemonize) and releasing the namespace (after the last task exit) is rather rare operation and we can sacrifice its speed to solve the issues above. The access to other task namespaces is proposed to be performed like this: rcu_read_lock(); nsproxy = task_nsproxy(tsk); if (nsproxy != NULL) { / * * work with the namespaces here * e.g. get the reference on one of them * / } / * * NULL task_nsproxy() means that this task is * almost dead (zombie) * / rcu_read_unlock(); This patch has passed the review by Eric and Oleg :) and, of course, tested. [clg@fr.ibm.com: fix unshare()] [ebiederm@xmission.com: Update get_net_ns_by_pid] Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Serge Hallyn <serue@us.ibm.com> Signed-off-by: Cedric Le Goater <clg@fr.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1072d16696c3..4a2640d38261 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -744,10 +744,10 @@ static struct net *get_net_ns_by_pid(pid_t pid)
744 rcu_read_lock(); 744 rcu_read_lock();
745 tsk = find_task_by_pid(pid); 745 tsk = find_task_by_pid(pid);
746 if (tsk) { 746 if (tsk) {
747 task_lock(tsk); 747 struct nsproxy *nsproxy;
748 if (tsk->nsproxy) 748 nsproxy = task_nsproxy(tsk);
749 net = get_net(tsk->nsproxy->net_ns); 749 if (nsproxy)
750 task_unlock(tsk); 750 net = get_net(nsproxy->net_ns);
751 } 751 }
752 rcu_read_unlock(); 752 rcu_read_unlock();
753 return net; 753 return net;