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 <[EMAIL PROTECTED]>

---

 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
[EMAIL PROTECTED]
https://lists.linux-foundation.org/mailman/listinfo/containers

_______________________________________________
Devel mailing list
[email protected]
https://openvz.org/mailman/listinfo/devel

Reply via email to