summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-10-03 13:28:06 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-10-24 23:43:29 -0400
commit1adfcb03e31ba0d6be5fddf773da4357d0792cbb (patch)
treec5c89b58403938c263e81c115fc864ad9aabc782
parent1dcddd4abd2c6df7f28928ad5cafa4a1cd20030b (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.h1
-rw-r--r--kernel/pid_namespace.c8
2 files changed, 8 insertions, 1 deletions
diff --git a/include/linux/pid_namespace.h b/include/linux/pid_namespace.h
index e2772666f004..7246ef3d4455 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 42086551a24a..06c62de9c711 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,