[PATCH] send_sigqueue: simplify and fix the race
[safe/jmp/linux-2.6] / kernel / pid.c
index edba31c..a9f2dfd 100644 (file)
@@ -136,7 +136,7 @@ struct pid * fastcall find_pid(enum pid_type type, int nr)
        struct hlist_node *elem;
        struct pid *pid;
 
-       hlist_for_each_entry(pid, elem,
+       hlist_for_each_entry_rcu(pid, elem,
                        &pid_hash[type][pid_hashfn(nr)], pid_chain) {
                if (pid->nr == nr)
                        return pid;
@@ -150,15 +150,15 @@ int fastcall attach_pid(task_t *task, enum pid_type type, int nr)
 
        task_pid = &task->pids[type];
        pid = find_pid(type, nr);
+       task_pid->nr = nr;
        if (pid == NULL) {
-               hlist_add_head(&task_pid->pid_chain,
-                               &pid_hash[type][pid_hashfn(nr)]);
                INIT_LIST_HEAD(&task_pid->pid_list);
+               hlist_add_head_rcu(&task_pid->pid_chain,
+                                  &pid_hash[type][pid_hashfn(nr)]);
        } else {
                INIT_HLIST_NODE(&task_pid->pid_chain);
-               list_add_tail(&task_pid->pid_list, &pid->pid_list);
+               list_add_tail_rcu(&task_pid->pid_list, &pid->pid_list);
        }
-       task_pid->nr = nr;
 
        return 0;
 }
@@ -170,20 +170,20 @@ static fastcall int __detach_pid(task_t *task, enum pid_type type)
 
        pid = &task->pids[type];
        if (!hlist_unhashed(&pid->pid_chain)) {
-               hlist_del(&pid->pid_chain);
 
-               if (list_empty(&pid->pid_list))
+               if (list_empty(&pid->pid_list)) {
                        nr = pid->nr;
-               else {
+                       hlist_del_rcu(&pid->pid_chain);
+               } else {
                        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)]);
+                       hlist_replace_rcu(&pid->pid_chain,
+                                         &pid_next->pid_chain);
                }
        }
 
-       list_del(&pid->pid_list);
+       list_del_rcu(&pid->pid_list);
        pid->nr = 0;
 
        return nr;
@@ -218,36 +218,6 @@ task_t *find_task_by_pid_type(int type, int nr)
 EXPORT_SYMBOL(find_task_by_pid_type);
 
 /*
- * This function switches the PIDs if a non-leader thread calls
- * sys_execve() - this must be done without releasing the PID.
- * (which a detach_pid() would eventually do.)
- */
-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(thread, PIDTYPE_PID);
-       __detach_pid(thread, PIDTYPE_TGID);
-
-       leader->pid = leader->tgid = thread->pid;
-       thread->pid = thread->tgid;
-
-       attach_pid(thread, PIDTYPE_PID, thread->pid);
-       attach_pid(thread, PIDTYPE_TGID, thread->tgid);
-       attach_pid(thread, PIDTYPE_PGID, thread->signal->pgrp);
-       attach_pid(thread, PIDTYPE_SID, thread->signal->session);
-       list_add_tail(&thread->tasks, &init_task.tasks);
-
-       attach_pid(leader, PIDTYPE_PID, leader->pid);
-       attach_pid(leader, PIDTYPE_TGID, leader->tgid);
-       attach_pid(leader, PIDTYPE_PGID, leader->signal->pgrp);
-       attach_pid(leader, PIDTYPE_SID, leader->signal->session);
-}
-
-/*
  * The pid hash table is scaled according to the amount of memory in the
  * machine.  From a minimum of 16 slots up to 4096 slots at one gigabyte or
  * more.
@@ -277,16 +247,8 @@ void __init pidhash_init(void)
 
 void __init pidmap_init(void)
 {
-       int i;
-
        pidmap_array->page = (void *)get_zeroed_page(GFP_KERNEL);
+       /* Reserve PID 0. We never call free_pidmap(0) */
        set_bit(0, pidmap_array->page);
        atomic_dec(&pidmap_array->nr_free);
-
-       /*
-        * Allocate PID 0, and hash it via all PID types:
-        */
-
-       for (i = 0; i < PIDTYPE_MAX; i++)
-               attach_pid(current, i, 0);
 }