aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/nsproxy.h
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 /include/linux/nsproxy.h
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 'include/linux/nsproxy.h')
-rw-r--r--include/linux/nsproxy.h16
1 files changed, 6 insertions, 10 deletions
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index b4ec59d159ac..35fa08fd7739 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -40,32 +40,28 @@ extern struct nsproxy init_nsproxy;
40 * the namespaces access rules are: 40 * the namespaces access rules are:
41 * 41 *
42 * 1. only current task is allowed to change tsk->nsproxy pointer or 42 * 1. only current task is allowed to change tsk->nsproxy pointer or
43 * any pointer on the nsproxy itself 43 * any pointer on the nsproxy itself. Current must hold the task_lock
44 * when changing tsk->nsproxy.
44 * 45 *
45 * 2. when accessing (i.e. reading) current task's namespaces - no 46 * 2. when accessing (i.e. reading) current task's namespaces - no
46 * precautions should be taken - just dereference the pointers 47 * precautions should be taken - just dereference the pointers
47 * 48 *
48 * 3. the access to other task namespaces is performed like this 49 * 3. the access to other task namespaces is performed like this
49 * rcu_read_lock(); 50 * task_lock(task);
50 * nsproxy = task_nsproxy(tsk); 51 * nsproxy = task->nsproxy;
51 * if (nsproxy != NULL) { 52 * if (nsproxy != NULL) {
52 * / * 53 * / *
53 * * work with the namespaces here 54 * * work with the namespaces here
54 * * e.g. get the reference on one of them 55 * * e.g. get the reference on one of them
55 * * / 56 * * /
56 * } / * 57 * } / *
57 * * NULL task_nsproxy() means that this task is 58 * * NULL task->nsproxy means that this task is
58 * * almost dead (zombie) 59 * * almost dead (zombie)
59 * * / 60 * * /
60 * rcu_read_unlock(); 61 * task_unlock(task);
61 * 62 *
62 */ 63 */
63 64
64static inline struct nsproxy *task_nsproxy(struct task_struct *tsk)
65{
66 return rcu_dereference(tsk->nsproxy);
67}
68
69int copy_namespaces(unsigned long flags, struct task_struct *tsk); 65int copy_namespaces(unsigned long flags, struct task_struct *tsk);
70void exit_task_namespaces(struct task_struct *tsk); 66void exit_task_namespaces(struct task_struct *tsk);
71void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new); 67void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);