[Devel] [PATCH 26/28] [MULTI 5/6] Multilevel model pid manipulations

Pavel Emelianov xemul at openvz.org
Fri Jun 15 09:28:27 PDT 2007


The alloc_pid(), free_pid() and put_pid() implementation for multilevel
model (see [PREP 10/14]). This model allocates the appropriate number 
and hashed them into two tables.

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

---

 pid.c |  158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 158 insertions(+)

--- ./kernel/pid.c.multicore	2007-06-15 15:38:59.000000000 +0400
+++ ./kernel/pid.c	2007-06-15 15:41:30.000000000 +0400
@@ -73,6 +73,22 @@ static struct hlist_head *pid_hash2;
 #define vpid_hash	pid_hash2
 #define vpid_hashfn	pid_ehashfn
 #endif
+
+#ifdef CONFIG_PID_NS_MULTILEVEL
+/*
+ * multilevel model stores pid numbers in two hashes
+ *  - one hashes them with numerical id and the namespace
+ *  - the other one - with struct pid and the namespace
+ */
+#define pid_phash	pid_hash
+#define pid_nhash	pid_hash2
+
+#define pid_phashfn	pid_ehashfn
+#define pid_nhashfn	pid_ehashfn
+
+struct kmem_cache *pid_nr_cachep;
+#endif
+
 #endif
 
 /*
@@ -377,6 +393,145 @@ static inline void del_pid_from_ns(struc
 	pid->ns = &init_pid_ns;
 }
 #endif
+
+#ifdef CONFIG_PID_NS_MULTILEVEL
+static inline int alloc_pid_nr(struct pid *pid, struct pid_namespace *ns)
+{
+	struct pid_number *pnr;
+	int nr;
+
+	pnr = kmem_cache_alloc(pid_nr_cachep, GFP_KERNEL);
+	if (pnr == NULL)
+		goto out_nr;
+
+	nr = alloc_pidmap(ns);
+	if (nr < 0)
+		goto out_map;
+
+	get_pid_ns(ns);
+	pnr->nr = nr;
+	pnr->ns = ns;
+	pnr->pid = pid;
+	pnr->next = pid->pid_nrs;
+	pid->pid_nrs = pnr;
+	return 0;
+
+out_map:
+	kmem_cache_free(pid_nr_cachep, pnr);
+out_nr:
+	return -ENOMEM;
+}
+
+static inline void free_pid_nr(struct pid_number *pnr)
+{
+	free_pidmap(pnr->ns, pnr->nr);
+	put_pid_ns(pnr->ns);
+	kmem_cache_free(pid_nr_cachep, pnr);
+}
+
+static inline void hash_pid_nr(struct pid_number *pnr)
+{
+	hlist_add_head_rcu(&pnr->nr_chain,
+			&pid_nhash[pid_nhashfn(pnr->nr, pnr->ns)]);
+	hlist_add_head_rcu(&pnr->pid_chain,
+			&pid_phash[pid_phashfn(pnr->pid, pnr->ns)]);
+}
+
+static inline void unhash_pid_nr(struct pid_number *pnr)
+{
+	hlist_del_rcu(&pnr->nr_chain);
+	hlist_del_rcu(&pnr->pid_chain);
+}
+
+static inline void free_pid_nrs(struct pid *pid)
+{
+	struct pid_number *pnr;
+
+	while (pid->pid_nrs != NULL) {
+		pnr = pid->pid_nrs;
+		pid->pid_nrs = pnr->next;
+		free_pid_nr(pnr);
+	}
+}
+
+static inline int alloc_pid_nrs(struct pid *pid)
+{
+	int err;
+	struct pid *parent_pid;
+	struct pid_number *pnr;
+
+	pid->pid_nrs = NULL;
+
+	parent_pid = task_pid(current);
+	for_each_pid_nr(pnr, parent_pid) {
+		err = alloc_pid_nr(pid, pnr->ns);
+		if (err < 0)
+			goto out;
+	}
+
+	spin_lock_irq(&pidmap_lock);
+	for_each_pid_nr(pnr, pid)
+		hash_pid_nr(pnr);
+	spin_unlock_irq(&pidmap_lock);
+	return 0;
+
+out:
+	free_pid_nrs(pid);
+	return err;
+}
+
+static inline void unhash_pid_nrs(struct pid *pid)
+{
+	unsigned long flags;
+	struct pid_number *pnr;
+
+	spin_lock_irqsave(&pidmap_lock, flags);
+	for_each_pid_nr(pnr, pid)
+		unhash_pid_nr(pnr);
+	spin_unlock_irqrestore(&pidmap_lock, flags);
+}
+
+struct pid_number *find_nr_by_pid(struct pid *pid, struct pid_namespace *ns)
+{
+	struct pid_number *pnr;
+	struct hlist_node *n;
+
+	hlist_for_each_entry_rcu(pnr, n, &pid_phash[pid_phashfn(pid, ns)],
+			pid_chain)
+		if (pnr->pid == pid && pnr->ns == ns)
+			return pnr;
+
+	return NULL;
+}
+
+EXPORT_SYMBOL_GPL(find_nr_by_pid);
+
+/*
+ * this function finds the struct pid_number by its numerical id
+ * the name is not so beautiful, but this is an internal function
+ */
+
+static struct pid_number *find_nr_by_nr(pid_t nr, struct pid_namespace *ns)
+{
+	struct pid_number *pnr;
+	struct hlist_node *n;
+
+	hlist_for_each_entry_rcu(pnr, n, &pid_nhash[pid_nhashfn(nr, ns)],
+			nr_chain)
+		if (pnr->nr == nr && pnr->ns == ns)
+			return pnr;
+
+	return NULL;
+}
+
+struct pid * fastcall find_pid_ns(int nr, struct pid_namespace *ns)
+{
+	struct pid_number *pnr;
+
+	pnr = find_nr_by_nr(nr, ns);
+	return pnr != NULL ? pnr->pid : NULL;
+}
+#endif
 #endif
 
 EXPORT_SYMBOL_GPL(find_pid_ns);
@@ -762,4 +917,7 @@ void __init pidmap_init(void)
 	atomic_dec(&init_pid_ns.pidmap[0].nr_free);
 
 	pid_cachep = KMEM_CACHE(pid, SLAB_PANIC);
+#ifdef CONFIG_PID_NS_MULTILEVEL
+	pid_nr_cachep = KMEM_CACHE(pid_number, SLAB_PANIC);
+#endif
 }
_______________________________________________
Containers mailing list
Containers at lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/containers




More information about the Devel mailing list