From: Pavel Tikhomirov <ptikhomi...@virtuozzo.com> By holding rcu lock we can have valid ve pointer. Next using css_tryget we can get reference on ve cgroup if it is not yet started to destroy. In case cgroup is destroying retry with cgroup_mutex.
https://jira.sw.ru/browse/PSBM-123766 Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com> ==================== cgroup: ifpriomap virtualization I've also added get_curr_ve() helper as it looks like in many places we rely that get_exec_env() gives us ve which would not free under us, but all processes can be moved easily from this ve in parallel and ve can be freed AFAICS. https://jira.sw.ru/browse/PSBM-123766 Signed-off-by: Kirill Tkhai <ktk...@virtuozzo.com> --- kernel/cgroup/cgroup.c | 25 +++++++++++++++++++++++-- kernel/ve/ve.c | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 04a5e1effbaf..05fe9436a9a3 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -1929,8 +1929,29 @@ struct ve_struct *get_curr_ve(void) struct ve_struct *ve; /* - * Under cgroup_mutex both current tasks ve cgroup and ->task_ve - * pointer can't change. Corresponding cgroup_mutex around + * If first thread loads current->task_ve pointer, and if just after + * that current is moved by other thread from this ve cgroup to some + * other and this ve cgroup gets destroyed, ve pointer gets freed, so + * first thread can't use such ve pointer safely. + */ + + /* + * Fast path: Let's make it safe with rcu lock, though current can be + * moved to other ve cgroup and our ve cgroup can start destroying, ve + * pointer would be still valid. As it is freed in ve_destroy. And + * ve_destroy is called from rcu callback after task_ve had changed. + */ + rcu_read_lock(); + ve = rcu_dereference(current->task_ve); + if (css_tryget(&ve->css)) { + rcu_read_unlock(); + return ve; + } + rcu_read_unlock(); + + /* + * Slow path: Under cgroup_mutex both current tasks ve cgroup and + * task_ve pointer can't change. Corresponding cgroup_mutex around * cgroup_attach_task() protects us from it. */ mutex_lock(&cgroup_mutex); diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c index af46a9b597df..ba5a3a63acec 100644 --- a/kernel/ve/ve.c +++ b/kernel/ve/ve.c @@ -900,7 +900,7 @@ static void ve_attach(struct cgroup_taskset *tset) if (cpuid_override_on()) set_tsk_thread_flag(task, TIF_CPUID_OVERRIDE); - task->task_ve = ve; + rcu_assign_pointer(task->task_ve, ve); } } _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel