Subject: [PATCH] More pspace code From: Eric W. Biederman Date: 1129744481 -0600 - Move child_reaper and nr_processes into struct pspace. - Use nr_processes instead of nr_threads for the dentry count in /proc --- fs/exec.c | 3 ++- fs/proc/root.c | 4 ++-- include/linux/pspace.h | 2 ++ include/linux/sched.h | 4 ---- init/main.c | 5 ++--- kernel/exit.c | 13 ++++++------- kernel/fork.c | 15 +-------------- kernel/pid.c | 36 ++++++++++++++++++------------------ 8 files changed, 33 insertions(+), 49 deletions(-) aa613de033e7bc4391f8d39baf6621c1afb52260 diff --git a/fs/exec.c b/fs/exec.c index a04a575..b872f2c 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -713,7 +714,7 @@ static inline int de_thread(struct task_ switch_exec_pids(leader, current); current->parent = current->real_parent = leader->real_parent; - leader->parent = leader->real_parent = child_reaper; + leader->parent = leader->real_parent = leader->pspace->child_reaper; current->group_leader = current; leader->group_leader = leader; diff --git a/fs/proc/root.c b/fs/proc/root.c index f725980..9d28720 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -139,12 +139,12 @@ static void *proc_root_follow_link(struc static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) { /* - * nr_threads is actually protected by the tasklist_lock; + * nr_processes is actually protected by the tasklist_lock; * however, it's conventional to do reads, especially for * reporting, without any locking whatsoever. */ if (dir->i_ino == PROC_ROOT_INO) /* check for safety... */ - dir->i_nlink = proc_root.nlink + current->pspace->nr_threads; + dir->i_nlink = proc_root.nlink + current->pspace->nr_processes; if (!proc_lookup(dir, dentry, nd)) { return NULL; diff --git a/include/linux/pspace.h b/include/linux/pspace.h index 4ad74c7..4506670 100644 --- a/include/linux/pspace.h +++ b/include/linux/pspace.h @@ -16,7 +16,9 @@ struct pspace { atomic_t count; struct pspace *parent; + struct task_struct *child_reaper; int nr_threads; + int nr_processes; int last_pid; int offset; int min; diff --git a/include/linux/sched.h b/include/linux/sched.h index aab32c1..43f5afd 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -94,9 +94,6 @@ extern unsigned long avenrun[]; /* Load extern unsigned long total_forks; 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); @@ -1106,7 +1103,6 @@ extern NORET_TYPE void do_group_exit(int extern void daemonize(const char *, ...); extern int allow_signal(int); extern int disallow_signal(int); -extern task_t *child_reaper; extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *); extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); diff --git a/init/main.c b/init/main.c index f142d40..b2342eb 100644 --- a/init/main.c +++ b/init/main.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -555,8 +556,6 @@ static int __init initcall_debug_setup(c } __setup("initcall_debug", initcall_debug_setup); -struct task_struct *child_reaper = &init_task; - extern initcall_t __initcall_start[], __initcall_end[]; static void __init do_initcalls(void) @@ -669,7 +668,7 @@ static int init(void * unused) * assumptions about where in the task array this * can be found. */ - child_reaper = current; + init_pspace.child_reaper = current; /* Sets up cpus_possible() */ smp_prepare_cpus(max_cpus); diff --git a/kernel/exit.c b/kernel/exit.c index 4a608ba..b620670 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -36,7 +36,6 @@ #include extern void sem_exit (void); -extern struct task_struct *child_reaper; int getrusage(struct task_struct *, int, struct rusage __user *); @@ -52,7 +51,7 @@ static void __unhash_process(struct task detach_pid(p, PIDTYPE_PGID); detach_pid(p, PIDTYPE_SID); if (p->pid) - __get_cpu_var(process_counts)--; + current->pspace->nr_processes--; } exit_pspace(p); @@ -238,8 +237,8 @@ static inline void reparent_to_init(void ptrace_unlink(current); /* Reparent to init */ REMOVE_LINKS(current); - current->parent = child_reaper; - current->real_parent = child_reaper; + current->parent = current->pspace->child_reaper; + current->real_parent = current->pspace->child_reaper; SET_LINKS(current); /* Set the exit signal to SIGCHLD so we signal init on exit */ @@ -615,7 +614,7 @@ static inline void forget_original_paren do { reaper = next_thread(reaper); if (reaper == father) { - reaper = child_reaper; + reaper = father->pspace->child_reaper; break; } } while (reaper->exit_state); @@ -639,7 +638,7 @@ static inline void forget_original_paren if (father == p->real_parent) { /* reparent with a reaper, real father it's us */ - choose_new_parent(p, reaper, child_reaper); + choose_new_parent(p, reaper, p->pspace->child_reaper); reparent_thread(p, father, 0); } else { /* reparent ptraced task to its real parent */ @@ -660,7 +659,7 @@ static inline void forget_original_paren } list_for_each_safe(_p, _n, &father->ptrace_children) { p = list_entry(_p,struct task_struct,ptrace_list); - choose_new_parent(p, reaper, child_reaper); + choose_new_parent(p, reaper, p->pspace->child_reaper); reparent_thread(p, father, 1); } } diff --git a/kernel/fork.c b/kernel/fork.c index fce637f..156359a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -59,23 +59,10 @@ int nr_threads; /* The idle threads do int max_threads; /* tunable limit on nr_threads */ -DEFINE_PER_CPU(unsigned long, process_counts) = 0; - __cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ EXPORT_SYMBOL(tasklist_lock); -int nr_processes(void) -{ - int cpu; - int total = 0; - - for_each_online_cpu(cpu) - total += per_cpu(process_counts, cpu); - - return total; -} - #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR # define alloc_task_struct() kmem_cache_alloc(task_struct_cachep, GFP_KERNEL) # define free_task_struct(tsk) kmem_cache_free(task_struct_cachep, (tsk)) @@ -1166,7 +1153,7 @@ static task_t *copy_process(unsigned lon attach_pid(p, PIDTYPE_PGID, process_group(p)); attach_pid(p, PIDTYPE_SID, p->signal->session); if (p->pid) - __get_cpu_var(process_counts)++; + current->pspace->nr_processes++; } if (!current->signal->tty && p->signal->tty) diff --git a/kernel/pid.c b/kernel/pid.c index 118132f..4bd186f 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -53,12 +53,15 @@ int pid_max_max = PID_MAX_LIMIT; * the scheme scales to up to 4 million PIDs, runtime. */ struct pspace init_pspace = { - .count = ATOMIC_INIT(1), - .parent = NULL, - .last_pid = 0, - .offset = 0, - .min = RESERVED_PIDS, - .max = PID_MAX_DEFAULT, + .count = ATOMIC_INIT(1), + .parent = NULL, + .child_reaper = &init_task, + .nr_threads = 0, + .nr_processes = 0, + .last_pid = 0, + .offset = 0, + .min = RESERVED_PIDS, + .max = PID_MAX_DEFAULT, .pidmap = { [ 0 ... PIDMAP_ENTRIES-1] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } }, @@ -286,18 +289,14 @@ static struct pspace *new_pspace(int pid if (!pspace) return NULL; atomic_set(&pspace->count, 1); - pspace->parent = NULL; - pspace->nr_threads = 0; - pspace->last_pid = 0; - pspace->offset = offset; - pspace->min = 1; - pspace->max = pids; -#if 0 - if (proc_pspace_root_dentry(pspace)) { - kfree(pspace); - return NULL; - } -#endif + pspace->parent = NULL; + pspace->child_reaper = &init_task; + pspace->nr_threads = 0; + pspace->nr_processes = 0; + pspace->last_pid = 0; + pspace->offset = offset; + pspace->min = 1; + pspace->max = pids; for (i = 0; i < pages; i++) { atomic_set(&pspace->pidmap[i].nr_free, BITS_PER_PAGE); pspace->pidmap[i].page = NULL; @@ -350,6 +349,7 @@ int copy_pspace(int flags, struct task_s new->parent = p->pspace; p->pspace = new; p->pid = pid; + p->pspace->child_reaper = p; return 0; } -- 1.0.GIT