[Devel] [PATCH 6/13] Pid allocation/freeing procedures

Pavel Emelianov xemul at openvz.org
Thu May 24 05:54:20 PDT 2007


This patch make alloc_pid() and free_pid() aware of the
namespaces. When a pid is created not in init namespace
it gets into two hashes and holds the pointer to the 
namespace itself.

Signed-off-by: Pavel Emelianov <xemul at openvz.org>

---

diff --git a/kernel/pid.c b/kernel/pid.c
index eb66bd2..1815af4 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -54,6 +54,12 @@ static inline int mk_pid(struct pid_name
 #define find_next_offset(map, off)					\
 		find_next_zero_bit((map)->page, BITS_PER_PAGE, off)
 
+#ifdef CONFIG_PID_NS
+static struct hlist_head *vpid_hash;
+#define vpid_hashfn(nr, ns) hash_long((unsigned long)nr + (unsigned long)ns, \
+					pidhash_shift)
+#endif
+
 /*
  * PID-map pages start out as NULL, they get allocated upon
  * first use and are never deallocated. This way a low pid_max
@@ -197,9 +203,19 @@ fastcall void free_pid(struct pid *pid)
 
 	spin_lock_irqsave(&pidmap_lock, flags);
 	hlist_del_rcu(&pid->pid_chain);
+#ifdef CONFIG_PID_NS
+	if (pid->ns != &init_pid_ns)
+		hlist_del_rcu(&pid->vpid_chain);
+#endif
 	spin_unlock_irqrestore(&pidmap_lock, flags);
 
 	free_pidmap(&init_pid_ns, pid->nr);
+#ifdef CONFIG_PID_NS
+	if (pid->ns != &init_pid_ns) {
+		free_pidmap(pid->ns, pid->vnr);
+		put_pid_ns(pid->ns);
+	}
+#endif
 	call_rcu(&pid->rcu, delayed_put_pid);
 }
 
@@ -207,28 +223,52 @@ struct pid *alloc_pid(void)
 {
 	struct pid *pid;
 	enum pid_type type;
-	int nr = -1;
+	int nr, vnr;
+	struct pid_namespace *ns;
 
 	pid = kmem_cache_alloc(pid_cachep, GFP_KERNEL);
 	if (!pid)
 		goto out;
 
-	nr = alloc_pidmap(current->nsproxy->pid_ns);
+	vnr = nr = alloc_pidmap(&init_pid_ns);
 	if (nr < 0)
 		goto out_free;
 
+	ns = current->nsproxy->pid_ns;
+#ifdef CONFIG_PID_NS
+	if (ns != &init_pid_ns) {
+		vnr = alloc_pidmap(ns);
+		if (vnr < 0)
+			goto out_free_map;
+
+		get_pid_ns(ns);
+	}
+#endif
 	atomic_set(&pid->count, 1);
 	pid->nr = nr;
+#ifdef CONFIG_PID_NS
+	pid->vnr = vnr;
+	pid->ns = ns;
+#endif
 	for (type = 0; type < PIDTYPE_MAX; ++type)
 		INIT_HLIST_HEAD(&pid->tasks[type]);
 
 	spin_lock_irq(&pidmap_lock);
 	hlist_add_head_rcu(&pid->pid_chain, &pid_hash[pid_hashfn(pid->nr)]);
+#ifdef CONFIG_PID_NS
+	if (ns != &init_pid_ns)
+		hlist_add_head_rcu(&pid->vpid_chain,
+				&vpid_hash[vpid_hashfn(vnr, ns)]);
+#endif
 	spin_unlock_irq(&pidmap_lock);
 
 out:
 	return pid;
 
+#ifdef CONFIG_PID_NS
+out_free_map:
+	free_pidmap(&init_pid_ns, nr);
+#endif
 out_free:
 	kmem_cache_free(pid_cachep, pid);
 	pid = NULL;
@@ -397,12 +607,17 @@ void __init pidhash_init(void)
 	printk("PID hash table entries: %d (order: %d, %Zd bytes)\n",
 		pidhash_size, pidhash_shift,
 		pidhash_size * sizeof(struct hlist_head));
-
+#ifdef CONFIG_PID_NS
+	pidhash_size *= 2;
+#endif
 	pid_hash = alloc_bootmem(pidhash_size *	sizeof(*(pid_hash)));
 	if (!pid_hash)
 		panic("Could not alloc pidhash!\n");
 	for (i = 0; i < pidhash_size; i++)
 		INIT_HLIST_HEAD(&pid_hash[i]);
+#ifdef CONFIG_PID_NS
+	vpid_hash = pid_hash + (pidhash_size / 2);
+#endif
 }
 
 void __init pidmap_init(void)




More information about the Devel mailing list