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!
From: Cyrill Gorcunov <[email protected]> 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 <[email protected]> Signed-off-by: Cyrill Gorcunov <[email protected]> CC: Vladimir Davydov <[email protected]> CC: Konstantin Khorenko <[email protected]> CC: Pavel Emelyanov <[email protected]> CC: Andrey Vagin <[email protected]> --- 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,
_______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
