[Devel] [PATCH rh7 1/3] ve: Attach a ve cgroup from task_work
Kirill Tkhai
ktkhai at odin.com
Fri Oct 16 09:24:49 PDT 2015
We have many places where get_exec_env() is used.
Since a task may be attached to a ve not only by
itself, this may lead to a problem, when dereferenced
ve has changed, but a code is operating with the old
ve.
This patch makes task_ve to be changed using task_work,
i.e. in a place where we definitelly do not use
get_exec_env().
Suggested-by: Vladimir Davydov <vdavydov at odin.com>
Suggested-by: Pavel Emelyanov <xemul at odin.com>
Signed-off-by: Kirill Tkhai <ktkhai at odin.com>
---
include/linux/init_task.h | 3 ++-
include/linux/sched.h | 1 +
kernel/fork.c | 4 ++++
kernel/ve/ve.c | 19 ++++++++++++++++++-
4 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index d2cbad0..1d5e271 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -136,7 +136,8 @@ extern struct task_group root_task_group;
#endif
#ifdef CONFIG_VE
-#define INIT_TASK_VE(tsk) .task_ve = &ve0,
+#define INIT_TASK_VE(tsk) .task_ve = &ve0, \
+ .task_ve_work.func = NULL,
#else
#define INIT_TASK_VE(tsk)
#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index e1bcabe..20d2e4e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1564,6 +1564,7 @@ struct task_struct {
#endif
#ifdef CONFIG_VE
struct ve_struct *task_ve;
+ struct callback_head task_ve_work;
#endif
#ifdef CONFIG_MEMCG /* memcg uses this to do batch job */
struct memcg_batch_info {
diff --git a/kernel/fork.c b/kernel/fork.c
index 505fa21..b077751 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -73,6 +73,7 @@
#include <linux/uprobes.h>
#include <linux/aio.h>
#include <linux/ve.h>
+#include <linux/task_work.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -1377,6 +1378,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
p->sequential_io = 0;
p->sequential_io_avg = 0;
#endif
+#ifdef CONFIG_VE
+ init_task_work(&p->task_ve_work, NULL);
+#endif
/* Perform scheduler related setup. Assign this task to a CPU. */
sched_fork(clone_flags, p);
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index 12cfa33..23d5482 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -701,6 +701,15 @@ static void ve_destroy(struct cgroup *cg)
kmem_cache_free(ve_cachep, ve);
}
+static void ve_attach_work(struct callback_head *head)
+{
+ rcu_read_lock();
+ current->task_ve = cgroup_ve(task_cgroup(current, ve_subsys_id));
+ rcu_read_unlock();
+ smp_mb(); /* Pairs with smp_mb() in ve_can_attach() */
+ init_task_work(¤t->task_ve_work, NULL);
+}
+
static int ve_can_attach(struct cgroup *cg, struct cgroup_taskset *tset)
{
struct ve_struct *ve = cgroup_ve(cg);
@@ -733,6 +742,13 @@ static int ve_can_attach(struct cgroup *cg, struct cgroup_taskset *tset)
}
}
+ cgroup_taskset_for_each(task, cg, tset) {
+ /* Attaching is in process */
+ if (task->task_ve_work.func != NULL)
+ return -EAGAIN;
+ }
+ smp_mb(); /* Pairs with smp_mb() in ve_attach_work() */
+
return 0;
}
@@ -753,7 +769,8 @@ static void ve_attach(struct cgroup *cg, struct cgroup_taskset *tset)
/* Leave parent exec domain */
task->parent_exec_id--;
- task->task_ve = ve;
+ init_task_work(&task->task_ve_work, ve_attach_work);
+ task_work_add(task, &task->task_ve_work, true);
}
}
More information about the Devel
mailing list