diff -NurpP --minimal linux-2.6.16-rc5-vs2.0.2-rc10.2/include/linux/vserver/context.h linux-2.6.16-rc5-vs2.0.2-rc10.x/include/linux/vserver/context.h --- linux-2.6.16-rc5-vs2.0.2-rc10.2/include/linux/vs_context.h 2006-02-17 22:18:51 +0100 +++ linux-2.6.16-rc5-vs2.0.2-rc10.x/include/linux/vs_context.h 2006-03-10 22:47:50 +0100 @@ -165,6 +170,29 @@ static inline void __wakeup_vx_info(stru wake_up_interruptible(&vxi->vx_wait); } +extern void exit_vx_info(struct task_struct *); + +static inline +struct task_struct *vx_child_reaper(struct task_struct *p) +{ + struct vx_info *vxi = p->vx_info; + struct task_struct *reaper = child_reaper; + + if (!vxi) + goto out; + + BUG_ON(!p->vx_info->vx_reaper); + + /* child reaper for the guest reaper */ + if (vxi->vx_reaper == p) + goto out; + + reaper = vxi->vx_reaper; +out: + return reaper; +} + + #else #warning duplicate inclusion #endif diff -NurpP --minimal linux-2.6.16-rc5-vs2.0.2-rc10.2/include/linux/vs_network.h linux-2.6.16-rc5-vs2.0.2-rc10.x/include/linux/vs_network.h --- linux-2.6.16-rc5-vs2.0.2-rc10.2/include/linux/vs_network.h 2006-02-17 22:18:51 +0100 +++ linux-2.6.16-rc5-vs2.0.2-rc10.x/include/linux/vs_network.h 2006-03-10 22:27:15 +0100 @@ -203,6 +203,12 @@ static inline int addr_in_nx_info(struct return 0; } +static inline void exit_nx_info(struct task_struct *p) +{ + if (p->nx_info) + release_nx_info(p->nx_info, p); +} + #else #warning duplicate inclusion diff -NurpP --minimal linux-2.6.16-rc5-vs2.0.2-rc10.2/kernel/exit.c linux-2.6.16-rc5-vs2.0.2-rc10.x/kernel/exit.c --- linux-2.6.16-rc5-vs2.0.2-rc10.2/kernel/exit.c 2006-02-28 15:23:49 +0100 +++ linux-2.6.16-rc5-vs2.0.2-rc10.x/kernel/exit.c 2006-03-10 22:28:54 +0100 @@ -51,11 +51,6 @@ static void exit_mm(struct task_struct * static void __unhash_process(struct task_struct *p) { nr_threads--; - /* tasklist_lock is held */ - if (p->vx_info) { - atomic_dec(&p->vx_info->cvirt.nr_threads); - vx_nproc_dec(p); - } detach_pid(p, PIDTYPE_PID); detach_pid(p, PIDTYPE_TGID); if (thread_group_leader(p)) { @@ -116,10 +111,6 @@ repeat: spin_unlock(&p->proc_lock); proc_pid_flush(proc_dentry); release_thread(p); - if (p->vx_info) - release_vx_info(p->vx_info, p); - if (p->nx_info) - release_nx_info(p->nx_info, p); put_task_struct(p); p = leader; @@ -551,7 +542,7 @@ static void exit_mm(struct task_struct * mmput(mm); } -static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_reaper) +static inline void choose_new_parent(task_t *p, task_t *reaper) { /* * Make sure we're not reparenting to ourselves and that @@ -635,7 +626,7 @@ static void forget_original_parent(struc do { reaper = next_thread(reaper); if (reaper == father) { - reaper = child_reaper; + reaper = vx_child_reaper(father); break; } } while (reaper->exit_state); @@ -659,7 +650,7 @@ static void forget_original_parent(struc 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, vx_child_reaper(p)); reparent_thread(p, father, 0); } else { /* reparent ptraced task to its real parent */ @@ -680,7 +671,11 @@ static void forget_original_parent(struc } 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); + + /* check for reaper context */ + BUG_ON(p->xid != reaper->xid); + + choose_new_parent(p, reaper); reparent_thread(p, father, 1); } } @@ -874,6 +869,8 @@ fastcall NORET_TYPE void do_exit(long co __exit_files(tsk); __exit_fs(tsk); exit_namespace(tsk); + exit_vx_info(tsk); + exit_nx_info(tsk); exit_thread(); cpuset_exit(tsk); exit_keys(tsk); diff -NurpP --minimal linux-2.6.16-rc5-vs2.0.2-rc10.2/kernel/vserver/context.c linux-2.6.16-rc5-vs2.0.2-rc10.x/kernel/vserver/context.c --- linux-2.6.16-rc5-vs2.0.2-rc10.2/kernel/vserver/context.c 2006-02-17 22:18:51 +0100 +++ linux-2.6.16-rc5-vs2.0.2-rc10.x/kernel/vserver/context.c 2006-03-10 23:28:19 +0100 @@ -594,6 +617,35 @@ int vx_set_init(struct vx_info *vxi, str return 0; } +void vx_exit_init(struct vx_info *vxi, struct task_struct *p) +{ + vxdprintk(VXD_CBIT(xid, 6), + "vx_exit_init(%p[#%d],%p[#%d,%d,%d])", + vxi, vxi->vx_id, p, p->xid, p->pid, p->tgid); + + vxi->vx_initpid = 0; +} + + + +/* task must be current or locked */ + +void exit_vx_info(struct task_struct *p) +{ + struct vx_info *vxi = p->vx_info; + + if (vxi) { + atomic_dec(&vxi->cvirt.nr_threads); + vx_nproc_dec(p); + + if (vxi->vx_initpid == p->tgid) + vx_exit_init(vxi, p); + if (vxi->vx_reaper == p) + vx_set_reaper(vxi, child_reaper); + release_vx_info(vxi, p); + } +} + /* vserver syscall commands below here */