diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-03 13:28:06 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-24 23:43:29 -0400 |
commit | 1adfcb03e31ba0d6be5fddf773da4357d0792cbb (patch) | |
tree | c5c89b58403938c263e81c115fc864ad9aabc782 | |
parent | 1dcddd4abd2c6df7f28928ad5cafa4a1cd20030b (diff) |
pid_namespace: make freeing struct pid_namespace rcu-delayed
makes procfs ->premission() instances safety in RCU mode independent
from vfsmount_lock.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | include/linux/pid_namespace.h | 1 | ||||
-rw-r--r-- | kernel/pid_namespace.c | 8 |
2 files changed, 8 insertions, 1 deletions
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h index e2772666f00..7246ef3d445 100644 --- a/include/linux/pid_namespace.h +++ b/include/linux/pid_namespace.h @@ -23,6 +23,7 @@ struct bsd_acct_struct; struct pid_namespace { struct kref kref; struct pidmap pidmap[PIDMAP_ENTRIES]; + struct rcu_head rcu; int last_pid; unsigned int nr_hashed; struct task_struct *child_reaper; diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 42086551a24..06c62de9c71 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -132,6 +132,12 @@ out: return ERR_PTR(err); } +static void delayed_free_pidns(struct rcu_head *p) +{ + kmem_cache_free(pid_ns_cachep, + container_of(p, struct pid_namespace, rcu)); +} + static void destroy_pid_namespace(struct pid_namespace *ns) { int i; @@ -140,7 +146,7 @@ static void destroy_pid_namespace(struct pid_namespace *ns) for (i = 0; i < PIDMAP_ENTRIES; i++) kfree(ns->pidmap[i].page); put_user_ns(ns->user_ns); - kmem_cache_free(pid_ns_cachep, ns); + call_rcu(&ns->rcu, delayed_free_pidns); } struct pid_namespace *copy_pid_ns(unsigned long flags, |