The commit is pushed to "branch-rh7-3.10.0-123.1.2-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-123.1.2.vz7.5.1 ------> commit 729323172bc760a2daf4d790a5bffc74ec10c04d Author: Cyrill Gorcunov <gorcu...@odin.com> Date: Tue May 19 00:43:44 2015 +0400
ve/cgroups: Allow to attach non-self into ve cgroups, v3 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. khorenko@: Check for thread_group_empty(task) is enough to be sure the task is single-threaded. https://jira.sw.ru/browse/PSBM-33561 Reported-by: Nikita Spiridonov <nspirido...@odin.com> Signed-off-by: Cyrill Gorcunov <gorcu...@odin.com> CC: Vladimir Davydov <vdavy...@odin.com> CC: Konstantin Khorenko <khore...@odin.com> CC: Pavel Emelyanov <xe...@odin.com> CC: Andrey Vagin <ava...@odin.com> --- kernel/ve/ve.c | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c index e598d15..cf7c848 100644 --- a/kernel/ve/ve.c +++ b/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_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 *cg, struct cgroup_taskset *tset) static void ve_attach(struct cgroup *cg, struct cgroup_taskset *tset) { struct ve_struct *ve = cgroup_ve(cg); - struct task_struct *tsk = current; + struct task_struct *task; - /* 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; + 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. */ - tsk->signal->oom_score_adj = 0; - tsk->signal->oom_score_adj_min = 0; + /* 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 Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel