mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
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.
[[email protected]: fix unshare()]
[[email protected]: Update get_net_ns_by_pid]
Signed-off-by: Pavel Emelyanov <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Paul E. McKenney <[email protected]>
Cc: Serge Hallyn <[email protected]>
Signed-off-by: Cedric Le Goater <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
a6f5e06378
commit
cf7b708c8d
6 changed files with 91 additions and 45 deletions
|
|
@ -350,18 +350,21 @@ struct proc_mounts {
|
|||
static int mounts_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct task_struct *task = get_proc_task(inode);
|
||||
struct nsproxy *nsp;
|
||||
struct mnt_namespace *ns = NULL;
|
||||
struct proc_mounts *p;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (task) {
|
||||
task_lock(task);
|
||||
if (task->nsproxy) {
|
||||
ns = task->nsproxy->mnt_ns;
|
||||
rcu_read_lock();
|
||||
nsp = task_nsproxy(task);
|
||||
if (nsp) {
|
||||
ns = nsp->mnt_ns;
|
||||
if (ns)
|
||||
get_mnt_ns(ns);
|
||||
}
|
||||
task_unlock(task);
|
||||
rcu_read_unlock();
|
||||
|
||||
put_task_struct(task);
|
||||
}
|
||||
|
||||
|
|
@ -424,16 +427,20 @@ static int mountstats_open(struct inode *inode, struct file *file)
|
|||
|
||||
if (!ret) {
|
||||
struct seq_file *m = file->private_data;
|
||||
struct nsproxy *nsp;
|
||||
struct mnt_namespace *mnt_ns = NULL;
|
||||
struct task_struct *task = get_proc_task(inode);
|
||||
|
||||
if (task) {
|
||||
task_lock(task);
|
||||
if (task->nsproxy)
|
||||
mnt_ns = task->nsproxy->mnt_ns;
|
||||
if (mnt_ns)
|
||||
get_mnt_ns(mnt_ns);
|
||||
task_unlock(task);
|
||||
rcu_read_lock();
|
||||
nsp = task_nsproxy(task);
|
||||
if (nsp) {
|
||||
mnt_ns = nsp->mnt_ns;
|
||||
if (mnt_ns)
|
||||
get_mnt_ns(mnt_ns);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
put_task_struct(task);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue