[Devel] [PATCH rh7] ve: cgroups -- Allow to attach non-self into ve cgroups, v3

Cyrill Gorcunov gorcunov at odin.com
Mon May 18 10:47:13 PDT 2015


On Mon, May 18, 2015 at 08:41:33PM +0300, Vladimir Davydov wrote:
> 
> OK, I see, thanks.
> 
> But if we are attaching one thread which is thread_group_leader, we will
> not fail even if the thread group is not empty and other threads are not
> moved, will we?

Yeah ;) It should be OR here. Thank you!
-------------- next part --------------
From: Cyrill Gorcunov <gorcunov at odin.com>
Subject: ve: cgroups -- Allow to attach non-self into ve cgroups

In vzctl/libvzctl bundle we restore container like

 - create ve/$ctid cgroup
 - move self into this cgroup
 - run criu from inside

So that kernel code passes ve_can_attach test. In turn for
our P.Haul project (which is managing live migration) the
situation is different -- it opens ve/$ctid but moves
criu service pid instead (so that the service will
start restore procedure). Which leads to situation
where ve_can_attach fails with -EINVAL.

Basically we need to

1) Check that in case if task is getting attached to
   VE cgroup it should be a single threaded task.

2) In case of multithread task all threads should be
   moved in one pass (this actually prepared by
   cgroup_attach_task caller).

3) In case if VE is stopping or starting only kernel
   threads can attach.

Reported-by: Nikita Spiridonov <nspiridonov at odin.com>
Signed-off-by: Cyrill Gorcunov <gorcunov at odin.com>
CC: Vladimir Davydov <vdavydov at odin.com>
CC: Konstantin Khorenko <khorenko at odin.com>
CC: Pavel Emelyanov <xemul at odin.com>
CC: Andrey Vagin <avagin at odin.com>
---
 kernel/ve/ve.c |   53 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 31 insertions(+), 22 deletions(-)

Index: linux-pcs7.git/kernel/ve/ve.c
===================================================================
--- linux-pcs7.git.orig/kernel/ve/ve.c
+++ linux-pcs7.git/kernel/ve/ve.c
@@ -775,24 +775,31 @@ static void ve_destroy(struct cgroup *cg
 static int ve_can_attach(struct cgroup *cg, struct cgroup_taskset *tset)
 {
 	struct ve_struct *ve = cgroup_ve(cg);
-	struct task_struct *task = current;
-
-	if (cgroup_taskset_size(tset) != 1 ||
-	    cgroup_taskset_first(tset) != task ||
-	    !thread_group_leader(task) ||
-	    !thread_group_empty(task))
-		return -EINVAL;
+	struct task_struct *task;
 
 	if (ve->is_locked)
 		return -EBUSY;
 
 	/*
+	 * We either moving the whole group of threads,
+	 * either a single thread process.
+	 */
+	if (cgroup_taskset_size(tset) == 1) {
+		task = cgroup_taskset_first(tset);
+		if (!thread_group_leader(task) || !thread_group_empty(task))
+			return -EINVAL;
+	}
+
+	/*
 	 * Forbid userspace tasks to enter during starting or stopping.
-	 * Permit attaching kernel threads and init task for this containers.
+	 * Permit attaching kernel threads for this containers.
 	 */
-	if (!ve->is_running && (ve->ve_ns || nr_threads_ve(ve)) &&
-			!(task->flags & PF_KTHREAD))
-		return -EPIPE;
+	if (!ve->is_running && (ve->ve_ns || nr_threads_ve(ve))) {
+		cgroup_taskset_for_each(task, cg, tset) {
+			if (!(task->flags & PF_KTHREAD))
+				return -EPIPE;
+		}
+	}
 
 	return 0;
 }
@@ -800,20 +807,22 @@ static int ve_can_attach(struct cgroup *
 static void ve_attach(struct cgroup *cg, struct cgroup_taskset *tset)
 {
 	struct ve_struct *ve = cgroup_ve(cg);
-	struct task_struct *tsk = current;
-
-	/* this probihibts ptracing of task entered to VE from host system */
-	if (ve->is_running && tsk->mm)
-		tsk->mm->vps_dumpable = VD_VE_ENTER_TASK;
+	struct task_struct *task;
 
-	/* Drop OOM protection. */
-	tsk->signal->oom_score_adj = 0;
-	tsk->signal->oom_score_adj_min = 0;
+	cgroup_taskset_for_each(task, cg, tset) {
+		/* this probihibts ptracing of task entered to VE from host system */
+		if (ve->is_running && task->mm)
+			task->mm->vps_dumpable = VD_VE_ENTER_TASK;
+
+		/* Drop OOM protection. */
+		task->signal->oom_score_adj = 0;
+		task->signal->oom_score_adj_min = 0;
 
-	/* Leave parent exec domain */
-	tsk->parent_exec_id--;
+		/* Leave parent exec domain */
+		task->parent_exec_id--;
 
-	tsk->task_ve = ve;
+		task->task_ve = ve;
+	}
 }
 
 static int ve_state_read(struct cgroup *cg, struct cftype *cft,


More information about the Devel mailing list