vserver 1.9.3
[linux-2.6.git] / kernel / pid.c
index 23706b2..83008f8 100644 (file)
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/hash.h>
-#include <linux/vs_cvirt.h>
 
 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
-static struct list_head *pid_hash[PIDTYPE_MAX];
+static struct hlist_head *pid_hash[PIDTYPE_MAX];
 static int pidhash_shift;
 
 int pid_max = PID_MAX_DEFAULT;
@@ -147,73 +146,66 @@ failure:
        return -1;
 }
 
-fastcall struct pid *find_pid(enum pid_type type, int nr)
+struct pid * fastcall find_pid(enum pid_type type, int nr)
 {
-       struct list_head *elem, *bucket = &pid_hash[type][pid_hashfn(nr)];
+       struct hlist_node *elem;
        struct pid *pid;
 
-       __list_for_each(elem, bucket) {
-               pid = list_entry(elem, struct pid, hash_chain);
+       hlist_for_each_entry(pid, elem,
+                       &pid_hash[type][pid_hashfn(nr)], pid_chain) {
                if (pid->nr == nr)
                        return pid;
        }
        return NULL;
 }
 
-void fastcall link_pid(task_t *task, struct pid_link *link, struct pid *pid)
-{
-       atomic_inc(&pid->count);
-       list_add_tail(&link->pid_chain, &pid->task_list);
-       link->pidptr = pid;
-}
-
 int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
 {
-       struct pid *pid = find_pid(type, nr);
-
-       if (pid)
-               atomic_inc(&pid->count);
-       else {
-               pid = &task->pids[type].pid;
-               pid->nr = nr;
-               atomic_set(&pid->count, 1);
-               INIT_LIST_HEAD(&pid->task_list);
-               pid->task = task;
-               get_task_struct(task);
-               list_add(&pid->hash_chain, &pid_hash[type][pid_hashfn(nr)]);
+       struct pid *pid, *task_pid;
+
+       task_pid = &task->pids[type];
+       pid = find_pid(type, nr);
+       if (pid == NULL) {
+               hlist_add_head(&task_pid->pid_chain,
+                               &pid_hash[type][pid_hashfn(nr)]);
+               INIT_LIST_HEAD(&task_pid->pid_list);
+       } else {
+               INIT_HLIST_NODE(&task_pid->pid_chain);
+               list_add_tail(&task_pid->pid_list, &pid->pid_list);
        }
-       list_add_tail(&task->pids[type].pid_chain, &pid->task_list);
-       task->pids[type].pidptr = pid;
+       task_pid->nr = nr;
 
        return 0;
 }
 
 static inline int __detach_pid(task_t *task, enum pid_type type)
 {
-       struct pid_link *link = task->pids + type;
-       struct pid *pid = link->pidptr;
+       struct pid *pid, *pid_next;
        int nr;
 
-       list_del(&link->pid_chain);
-       if (!atomic_dec_and_test(&pid->count))
-               return 0;
-
+       pid = &task->pids[type];
+       if (!hlist_unhashed(&pid->pid_chain)) {
+               hlist_del(&pid->pid_chain);
+               if (!list_empty(&pid->pid_list)) {
+                       pid_next = list_entry(pid->pid_list.next,
+                                               struct pid, pid_list);
+                       /* insert next pid from pid_list to hash */
+                       hlist_add_head(&pid_next->pid_chain,
+                               &pid_hash[type][pid_hashfn(pid_next->nr)]);
+               }
+       }
+       list_del(&pid->pid_list);
        nr = pid->nr;
-       list_del(&pid->hash_chain);
-       put_task_struct(pid->task);
+       pid->nr = 0;
 
        return nr;
 }
 
-static void _detach_pid(task_t *task, enum pid_type type)
-{
-       __detach_pid(task, type);
-}
-
 void fastcall detach_pid(task_t *task, enum pid_type type)
 {
-       int nr = __detach_pid(task, type);
+       int nr;
 
+       nr = __detach_pid(task, type);
        if (!nr)
                return;
 
@@ -223,17 +215,18 @@ void fastcall detach_pid(task_t *task, enum pid_type type)
        free_pidmap(nr);
 }
 
-task_t *find_task_by_pid(int nr)
+task_t *find_task_by_pid_type(int type, int nr)
 {
-       struct pid *pid = find_pid(PIDTYPE_PID,
-               vx_rmap_tgid(current->vx_info, nr));
+       struct pid *pid;
 
+       pid = find_pid(type, nr);
        if (!pid)
                return NULL;
-       return pid_task(pid->task_list.next, PIDTYPE_PID);
+
+       return pid_task(&pid->pid_list, type);
 }
 
-EXPORT_SYMBOL(find_task_by_pid);
+EXPORT_SYMBOL(find_task_by_pid_type);
 
 /*
  * This function switches the PIDs if a non-leader thread calls
@@ -242,13 +235,13 @@ EXPORT_SYMBOL(find_task_by_pid);
  */
 void switch_exec_pids(task_t *leader, task_t *thread)
 {
-       _detach_pid(leader, PIDTYPE_PID);
-       _detach_pid(leader, PIDTYPE_TGID);
-       _detach_pid(leader, PIDTYPE_PGID);
-       _detach_pid(leader, PIDTYPE_SID);
+       __detach_pid(leader, PIDTYPE_PID);
+       __detach_pid(leader, PIDTYPE_TGID);
+       __detach_pid(leader, PIDTYPE_PGID);
+       __detach_pid(leader, PIDTYPE_SID);
 
-       _detach_pid(thread, PIDTYPE_PID);
-       _detach_pid(thread, PIDTYPE_TGID);
+       __detach_pid(thread, PIDTYPE_PID);
+       __detach_pid(thread, PIDTYPE_TGID);
 
        leader->pid = leader->tgid = thread->pid;
        thread->pid = thread->tgid;
@@ -273,23 +266,23 @@ void switch_exec_pids(task_t *leader, task_t *thread)
 void __init pidhash_init(void)
 {
        int i, j, pidhash_size;
-       unsigned long megabytes = max_pfn >> (20 - PAGE_SHIFT);
+       unsigned long megabytes = nr_kernel_pages >> (20 - PAGE_SHIFT);
 
        pidhash_shift = max(4, fls(megabytes * 4));
        pidhash_shift = min(12, pidhash_shift);
        pidhash_size = 1 << pidhash_shift;
 
-       printk("PID hash table entries: %d (order %d: %Zd bytes)\n",
+       printk("PID hash table entries: %d (order: %d, %Zd bytes)\n",
                pidhash_size, pidhash_shift,
-               pidhash_size * sizeof(struct list_head));
+               PIDTYPE_MAX * pidhash_size * sizeof(struct hlist_head));
 
        for (i = 0; i < PIDTYPE_MAX; i++) {
                pid_hash[i] = alloc_bootmem(pidhash_size *
-                                       sizeof(struct list_head));
+                                       sizeof(*(pid_hash[i])));
                if (!pid_hash[i])
                        panic("Could not alloc pidhash!\n");
                for (j = 0; j < pidhash_size; j++)
-                       INIT_LIST_HEAD(&pid_hash[i][j]);
+                       INIT_HLIST_HEAD(&pid_hash[i][j]);
        }
 }