From: Oleg Nesterov fork_idle() does unhash_process() just after copy_process(). Contrary, boot_cpu's idle thread explicitely registers itself for each pid_type with nr = 0. copy_process() already checks p->pid != 0 before process_counts++, I think we can just skip attach_pid() calls and job control inits for idle threads and kill unhash_process(). We don't need to cleanup ->proc_dentry in fork_idle() because with this patch idle threads are never hashed in kernel/pid.c:pid_hash[]. We don't need to hash pid == 0 in pidmap_init(). free_pidmap() is never called with pid == 0 arg, so it will never be reused. So it is still possible to use pid == 0 in any PIDTYPE_xxx namespace from kernel/pid.c's POV. However with this patch we don't hash pid == 0 for PIDTYPE_PID case. We still have have PIDTYPE_PGID/PIDTYPE_SID entries with pid == 0: /sbin/init and kernel threads which don't call daemonize(). Signed-off-by: Oleg Nesterov Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton --- arch/um/kernel/smp.c | 3 +-- include/linux/sched.h | 2 -- kernel/exit.c | 18 +----------------- kernel/fork.c | 33 +++++++++++++++++---------------- kernel/pid.c | 10 +--------- 5 files changed, 20 insertions(+), 46 deletions(-) diff -puN arch/um/kernel/smp.c~pidhash-dont-count-idle-threads arch/um/kernel/smp.c --- devel/arch/um/kernel/smp.c~pidhash-dont-count-idle-threads 2006-02-07 13:19:44.000000000 -0800 +++ devel-akpm/arch/um/kernel/smp.c 2006-02-07 13:19:44.000000000 -0800 @@ -139,11 +139,10 @@ void smp_prepare_cpus(unsigned int maxcp for(cpu = 1; cpu < ncpus; cpu++){ printk("Booting processor %d...\n", cpu); - + idle = idle_thread(cpu); init_idle(idle, cpu); - unhash_process(idle); waittime = 200000000; while (waittime-- && !cpu_isset(cpu, cpu_callin_map)) diff -puN include/linux/sched.h~pidhash-dont-count-idle-threads include/linux/sched.h --- devel/include/linux/sched.h~pidhash-dont-count-idle-threads 2006-02-07 13:19:44.000000000 -0800 +++ devel-akpm/include/linux/sched.h 2006-02-07 13:19:44.000000000 -0800 @@ -1209,8 +1209,6 @@ static inline int thread_group_empty(tas #define delay_group_leader(p) \ (thread_group_leader(p) && !thread_group_empty(p)) -extern void unhash_process(struct task_struct *p); - /* * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring * subscriptions and synchronises with wait4(). Also used in procfs. Also diff -puN kernel/exit.c~pidhash-dont-count-idle-threads kernel/exit.c --- devel/kernel/exit.c~pidhash-dont-count-idle-threads 2006-02-07 13:19:44.000000000 -0800 +++ devel-akpm/kernel/exit.c 2006-02-07 13:19:44.000000000 -0800 @@ -54,8 +54,7 @@ static void __unhash_process(struct task detach_pid(p, PIDTYPE_SID); list_del_init(&p->tasks); - if (p->pid) - __get_cpu_var(process_counts)--; + __get_cpu_var(process_counts)--; } remove_parent(p); @@ -116,21 +115,6 @@ repeat: goto repeat; } -/* we are using it only for SMP init */ - -void unhash_process(struct task_struct *p) -{ - struct dentry *proc_dentry; - - spin_lock(&p->proc_lock); - proc_dentry = proc_pid_unhash(p); - write_lock_irq(&tasklist_lock); - __unhash_process(p); - write_unlock_irq(&tasklist_lock); - spin_unlock(&p->proc_lock); - proc_pid_flush(proc_dentry); -} - /* * This checks not only the pgrp, but falls back on the pid if no * satisfactory pgrp is found. I dunno - gdb doesn't work correctly diff -puN kernel/fork.c~pidhash-dont-count-idle-threads kernel/fork.c --- devel/kernel/fork.c~pidhash-dont-count-idle-threads 2006-02-07 13:19:44.000000000 -0800 +++ devel-akpm/kernel/fork.c 2006-02-07 13:19:44.000000000 -0800 @@ -1172,25 +1172,26 @@ static task_t *copy_process(unsigned lon */ p->ioprio = current->ioprio; - add_parent(p); - if (unlikely(p->ptrace & PT_PTRACED)) - __ptrace_link(p, current->parent); - - attach_pid(p, PIDTYPE_PID, p->pid); - attach_pid(p, PIDTYPE_TGID, p->tgid); - if (thread_group_leader(p)) { - p->signal->tty = current->signal->tty; - p->signal->pgrp = process_group(current); - p->signal->session = current->signal->session; - attach_pid(p, PIDTYPE_PGID, process_group(p)); - attach_pid(p, PIDTYPE_SID, p->signal->session); + if (likely(p->pid)) { + add_parent(p); + if (unlikely(p->ptrace & PT_PTRACED)) + __ptrace_link(p, current->parent); + + attach_pid(p, PIDTYPE_PID, p->pid); + attach_pid(p, PIDTYPE_TGID, p->tgid); + if (thread_group_leader(p)) { + p->signal->tty = current->signal->tty; + p->signal->pgrp = process_group(current); + p->signal->session = current->signal->session; + attach_pid(p, PIDTYPE_PGID, process_group(p)); + attach_pid(p, PIDTYPE_SID, p->signal->session); - list_add_tail(&p->tasks, &init_task.tasks); - if (p->pid) + list_add_tail(&p->tasks, &init_task.tasks); __get_cpu_var(process_counts)++; + } + nr_threads++; } - nr_threads++; total_forks++; write_unlock_irq(&tasklist_lock); proc_fork_connector(p); @@ -1253,7 +1254,7 @@ task_t * __devinit fork_idle(int cpu) if (!task) return ERR_PTR(-ENOMEM); init_idle(task, cpu); - unhash_process(task); + return task; } diff -puN kernel/pid.c~pidhash-dont-count-idle-threads kernel/pid.c --- devel/kernel/pid.c~pidhash-dont-count-idle-threads 2006-02-07 13:19:44.000000000 -0800 +++ devel-akpm/kernel/pid.c 2006-02-07 13:19:44.000000000 -0800 @@ -247,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); } _