Subject: Re: [vserver] Getting a real pid 1 init in a container
From: Grzegorz Nosek <grzegorz.nosek@gmail.com>
Date: Wed, 21 Mar 2012 19:22:20 +0100
Wed, 21 Mar 2012 19:22:20 +0100
W dniu 21.03.2012 16:47, Grzegorz Nosek pisze:
> A basically working patch attached. One weird side effect is that the
> container init and its children are not visible in `vps auxf` (they
> remain visible in `vps aux` though).

Attached v2, this one is actually working *too* well -- the process tree 
is shown *twice* on some occasions ;) Also, upstart works like a charm 
(start/stop etc.)

This is another bug I won't fix today -- gotta go:

debian:/proc/sys/vserver# grep Tgid /proc/1/status
Tgid:	1
debian:/proc/sys/vserver# chcontext --xid 1 -- grep Tgid /proc/1/status
Tgid:	1
debian:/proc/sys/vserver# chcontext --xid 948 -- grep Tgid /proc/1/status
Tgid:	1
debian:/proc/sys/vserver# chcontext --xid 1 -- grep Tgid /proc/1/status
Tgid:	2219

Basically in xid==1 /proc/1 contains info about the last visited fakeinit.

Best regards,
  Grzegorz Nosek


From c897c155a81ad4c9689b7f9936d68b08554063cd Mon Sep 17 00:00:00 2001
From: Grzegorz Nosek <root@localdomain.pl>
Date: Wed, 21 Mar 2012 15:45:08 +0100
Subject: [PATCH] Actually use VServer context reaper

---
 kernel/exit.c |   21 ++++++++++++++++++---
 1 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/kernel/exit.c b/kernel/exit.c
index 45f0658..e1bfed0 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -859,6 +859,8 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
 {
 	struct pid_namespace *pid_ns = task_active_pid_ns(father);
 	struct task_struct *thread;
+	struct vx_info *vxi = father->vx_info;
+	struct task_struct *reaper;
 
 	thread = father;
 	while_each_thread(father, thread) {
@@ -869,6 +871,15 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
 		return thread;
 	}
 
+	reaper = pid_ns->child_reaper;
+	if (vxi) {
+		BUG_ON(!vxi->vx_reaper);
+		if (vxi->vx_reaper != init_pid_ns.child_reaper &&
+		    vxi->vx_reaper != father) {
+			reaper = vxi->vx_reaper;
+		}
+	}
+
 	if (unlikely(pid_ns->child_reaper == father)) {
 		write_unlock_irq(&tasklist_lock);
 		if (unlikely(pid_ns == &init_pid_ns))
@@ -884,12 +895,12 @@ static struct task_struct *find_new_reaper(struct task_struct
*father)
 		pid_ns->child_reaper = init_pid_ns.child_reaper;
 	}
 
-	return pid_ns->child_reaper;
+	return reaper;
 }
 
 static void forget_original_parent(struct task_struct *father)
 {
-	struct task_struct *p, *n, *reaper;
+	struct task_struct *p, *n, *reaper, *new_parent;
 	LIST_HEAD(ptrace_dead);
 
 	write_lock_irq(&tasklist_lock);
@@ -900,7 +911,11 @@ static void forget_original_parent(struct task_struct *father)
 	ptrace_exit(father, &ptrace_dead);
 
 	list_for_each_entry_safe(p, n, &father->children, sibling) {
-		p->real_parent = reaper;
+		new_parent = reaper;
+		if (unlikely(p == reaper))
+		    new_parent = task_active_pid_ns(p)->child_reaper;
+
+		p->real_parent = new_parent;
 		if (p->parent == father) {
 			BUG_ON(p->ptrace);
 			p->parent = p->real_parent;
-- 
1.7.2.3