proc_fill_super() simply needs someone to keep count of the number of processes; remove the tasklist iteration. fs/proc/inode.c | 7 +------ include/linux/sched.h | 3 +++ kernel/exit.c | 2 ++ kernel/fork.c | 14 ++++++++++++++ 4 files changed, 20 insertions(+), 6 deletions(-) diff -urpN wli-2.5.50-bk5-2/fs/proc/inode.c wli-2.5.50-bk5-3/fs/proc/inode.c --- wli-2.5.50-bk5-2/fs/proc/inode.c 2002-11-27 14:36:19.000000000 -0800 +++ wli-2.5.50-bk5-3/fs/proc/inode.c 2002-12-05 20:17:40.000000000 -0800 @@ -221,7 +221,6 @@ out_fail: int proc_fill_super(struct super_block *s, void *data, int silent) { struct inode * root_inode; - struct task_struct *p; s->s_blocksize = 1024; s->s_blocksize_bits = 10; @@ -234,11 +233,7 @@ int proc_fill_super(struct super_block * /* * Fixup the root inode's nlink value */ - read_lock(&tasklist_lock); - for_each_process(p) - if (p->pid) - root_inode->i_nlink++; - read_unlock(&tasklist_lock); + root_inode->i_nlink += nr_processes(); s->s_root = d_alloc_root(root_inode); if (!s->s_root) goto out_no_root; diff -urpN wli-2.5.50-bk5-2/include/linux/sched.h wli-2.5.50-bk5-3/include/linux/sched.h --- wli-2.5.50-bk5-2/include/linux/sched.h 2002-12-05 19:28:26.000000000 -0800 +++ wli-2.5.50-bk5-3/include/linux/sched.h 2002-12-05 20:03:22.000000000 -0800 @@ -27,6 +27,7 @@ #include #include #include +#include struct exec_domain; @@ -87,6 +88,8 @@ extern unsigned long avenrun[]; /* Load extern int nr_threads; extern int last_pid; +DECLARE_PER_CPU(unsigned long, process_counts); +extern int nr_processes(void); extern unsigned long nr_running(void); extern unsigned long nr_uninterruptible(void); extern unsigned long nr_iowait(void); diff -urpN wli-2.5.50-bk5-2/kernel/exit.c wli-2.5.50-bk5-3/kernel/exit.c --- wli-2.5.50-bk5-2/kernel/exit.c 2002-12-05 19:28:26.000000000 -0800 +++ wli-2.5.50-bk5-3/kernel/exit.c 2002-12-05 20:03:22.000000000 -0800 @@ -41,6 +41,8 @@ static struct dentry * __unhash_process( if (thread_group_leader(p)) { detach_pid(p, PIDTYPE_PGID); detach_pid(p, PIDTYPE_SID); + if (p->pid) + per_cpu(process_counts, smp_processor_id())--; } REMOVE_LINKS(p); diff -urpN wli-2.5.50-bk5-2/kernel/fork.c wli-2.5.50-bk5-3/kernel/fork.c --- wli-2.5.50-bk5-2/kernel/fork.c 2002-12-05 19:28:26.000000000 -0800 +++ wli-2.5.50-bk5-3/kernel/fork.c 2002-12-05 20:03:22.000000000 -0800 @@ -48,6 +48,8 @@ int nr_threads; int max_threads; unsigned long total_forks; /* Handle normal Linux uptimes. */ +DEFINE_PER_CPU(unsigned long, process_counts); + rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED; /* outer */ /* @@ -57,6 +59,16 @@ rwlock_t tasklist_lock __cacheline_align */ static task_t *task_cache[NR_CPUS] __cacheline_aligned; +int nr_processes(void) +{ + int cpu; + unsigned long total = 0; + + for (cpu = 0; cpu < NR_CPUS; ++cpu) + total += per_cpu(process_counts, cpu); + return (int)total; +} + void __put_task_struct(struct task_struct *tsk) { if (tsk != current) { @@ -927,6 +939,8 @@ static struct task_struct *copy_process( attach_pid(p, PIDTYPE_TGID, p->tgid); attach_pid(p, PIDTYPE_PGID, p->pgrp); attach_pid(p, PIDTYPE_SID, p->session); + if (p->pid) + per_cpu(process_counts, smp_processor_id())++; } else link_pid(p, p->pids + PIDTYPE_TGID, &p->group_leader->pids[PIDTYPE_TGID].pid);