aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2014-02-03 22:13:49 -0500
committerEric W. Biederman <ebiederm@xmission.com>2014-07-29 21:08:50 -0400
commit728dba3a39c66b3d8ac889ddbe38b5b1c264aec3 (patch)
tree26f69d0fe363f00b628d698b9df2634a33e42482 /net
parent9a3c4145af32125c5ee39c0272662b47307a8323 (diff)
namespaces: Use task_lock and not rcu to protect nsproxy
The synchronous syncrhonize_rcu in switch_task_namespaces makes setns a sufficiently expensive system call that people have complained. Upon inspect nsproxy no longer needs rcu protection for remote reads. remote reads are rare. So optimize for same process reads and write by switching using rask_lock instead. This yields a simpler to understand lock, and a faster setns system call. In particular this fixes a performance regression observed by Rafael David Tinoco <rafael.tinoco@canonical.com>. This is effectively a revert of Pavel Emelyanov's commit cf7b708c8d1d7a27736771bcf4c457b332b0f818 Make access to task's nsproxy lighter from 2007. The race this originialy fixed no longer exists as do_notify_parent uses task_active_pid_ns(parent) instead of parent->nsproxy. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'net')
-rw-r--r--net/core/net_namespace.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 85b62691f4f2..7c6b51a58968 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -373,9 +373,11 @@ struct net *get_net_ns_by_pid(pid_t pid)
373 tsk = find_task_by_vpid(pid); 373 tsk = find_task_by_vpid(pid);
374 if (tsk) { 374 if (tsk) {
375 struct nsproxy *nsproxy; 375 struct nsproxy *nsproxy;
376 nsproxy = task_nsproxy(tsk); 376 task_lock(tsk);
377 nsproxy = tsk->nsproxy;
377 if (nsproxy) 378 if (nsproxy)
378 net = get_net(nsproxy->net_ns); 379 net = get_net(nsproxy->net_ns);
380 task_unlock(tsk);
379 } 381 }
380 rcu_read_unlock(); 382 rcu_read_unlock();
381 return net; 383 return net;
@@ -632,11 +634,11 @@ static void *netns_get(struct task_struct *task)
632 struct net *net = NULL; 634 struct net *net = NULL;
633 struct nsproxy *nsproxy; 635 struct nsproxy *nsproxy;
634 636
635 rcu_read_lock(); 637 task_lock(task);
636 nsproxy = task_nsproxy(task); 638 nsproxy = task->nsproxy;
637 if (nsproxy) 639 if (nsproxy)
638 net = get_net(nsproxy->net_ns); 640 net = get_net(nsproxy->net_ns);
639 rcu_read_unlock(); 641 task_unlock(task);
640 642
641 return net; 643 return net;
642} 644}