[Devel] [PATCH RHEL COMMIT] ve/kthreadd: add per-ve kthreads creation interface
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Sep 28 14:42:33 MSK 2021
The commit is pushed to "branch-rh9-5.14.vz9.1.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after ark-5.14
------>
commit 016e0ef689badaaa0efc95463900cfd31b9d6798
Author: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
Date: Tue Sep 28 14:42:33 2021 +0300
ve/kthreadd: add per-ve kthreads creation interface
Patch introduces new function kthread_create_on_node_ve_flags and a few helpers:
1) kthread_create_on_node_ve and
1) kthread_run_ve and
2) kthread_create_ve
Note: we need to able to provide fork flags to kthread creation to be able to
fork one kthread from another as a sibling (this is needed to be able to put
kthreadd in contianer pid ns, but keep global kthreadd as its parent).
Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
+++
ve, kthread: Remove some useless crud.
Simplify the code by removing useless macroses.
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
+++
ve,kthread: fix use-after-return.
__kthread_create_ve() passes pointer to the data on stack to
another thread, and return immidiately causing use-after-return.
Fix this by moving all in upper function which waits
another thread finishes it's job.
https://jira.sw.ru/browse/PSBM-93708
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
(cherry-picked from vz8 commit 9aea2bf6c848 ("ve/kthreadd: add per-ve kthreads
creation interface"))
Signed-off-by: Nikita Yushchenko <nikita.yushchenko at virtuozzo.com>
---
include/linux/kthread.h | 10 +++++
kernel/kthread.c | 97 +++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 95 insertions(+), 12 deletions(-)
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index 346b0f269161..6d5827ab4bf8 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -56,6 +56,16 @@ bool kthread_is_per_cpu(struct task_struct *k);
__k; \
})
+#ifdef CONFIG_VE
+
+__printf(6, 7)
+struct task_struct *kthread_create_on_node_ve_flags(struct ve_struct *ve,
+ unsigned long flags,
+ int (*threadfn)(void *data),
+ void *data, int node,
+ const char namefmt[],
+ ...);
+#endif
void free_kthread_struct(struct task_struct *k);
void kthread_bind(struct task_struct *k, unsigned int cpu);
void kthread_bind_mask(struct task_struct *k, const struct cpumask *mask);
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 5b37a8567168..127ecaa457b5 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -28,6 +28,7 @@
#include <linux/uaccess.h>
#include <linux/numa.h>
#include <linux/sched/isolation.h>
+#include <linux/ve.h>
#include <trace/events/sched.h>
@@ -331,7 +332,8 @@ int tsk_fork_get_node(struct task_struct *tsk)
return NUMA_NO_NODE;
}
-static void create_kthread(struct kthread_create_info *create)
+static void create_kthread_flags(struct kthread_create_info *create,
+ unsigned long flags)
{
int pid;
@@ -339,7 +341,8 @@ static void create_kthread(struct kthread_create_info *create)
current->pref_node_fork = create->node;
#endif
/* We want our own signal handler (we take no signals by default). */
- pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
+ pid = kernel_thread(kthread, create,
+ flags | CLONE_FS | CLONE_FILES | SIGCHLD);
if (pid < 0) {
/* If user was SIGKILLed, I release the structure. */
struct completion *done = xchg(&create->done, NULL);
@@ -353,13 +356,48 @@ static void create_kthread(struct kthread_create_info *create)
}
}
-static __printf(4, 0)
-struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
- void *data, int node,
- const char namefmt[],
- va_list args)
+static void create_kthread(struct kthread_create_info *create)
+{
+ return create_kthread_flags(create, 0);
+}
+
+#ifdef CONFIG_VE
+struct kthread_create_work {
+ struct kthread_work work;
+ struct kthread_create_info *info;
+ unsigned long flags;
+};
+
+static void kthread_create_fn(struct kthread_work *w)
+{
+ struct kthread_create_work *work = container_of(w,
+ struct kthread_create_work, work);
+
+ create_kthread_flags(work->info, work->flags);
+}
+
+#endif
+static void kthread_create_add(struct kthread_create_info *create)
+{
+ spin_lock(&kthread_create_lock);
+ list_add_tail(&create->list, &kthread_create_list);
+ spin_unlock(&kthread_create_lock);
+
+ wake_up_process(kthreadd_task);
+}
+
+static __printf(6, 0)
+struct task_struct *__kthread_create_on_node_ve(struct ve_struct *ve,
+ unsigned long flags,
+ int (*threadfn)(void *data),
+ void *data, int node,
+ const char namefmt[],
+ va_list args)
{
DECLARE_COMPLETION_ONSTACK(done);
+ struct kthread_create_work work = {
+ KTHREAD_WORK_INIT(work.work, kthread_create_fn),
+ };
struct task_struct *task;
struct kthread_create_info *create = kmalloc(sizeof(*create),
GFP_KERNEL);
@@ -371,11 +409,15 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
create->node = node;
create->done = &done;
- spin_lock(&kthread_create_lock);
- list_add_tail(&create->list, &kthread_create_list);
- spin_unlock(&kthread_create_lock);
-
- wake_up_process(kthreadd_task);
+#ifdef CONFIG_VE
+ if (!ve_is_super(ve))
+ {
+ work.info = create;
+ work.flags = flags;
+ kthread_queue_work(ve->kthreadd_worker, &work.work);
+ } else
+#endif
+ kthread_create_add(create);
/*
* Wait for completion in killable state, for I might be chosen by
* the OOM killer while kthreadd is trying to allocate memory for
@@ -418,6 +460,16 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
return task;
}
+static __printf(4, 0)
+struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
+ void *data, int node,
+ const char namefmt[],
+ va_list args)
+{
+ return __kthread_create_on_node_ve(get_ve0(), 0,
+ threadfn, data, node, namefmt, args);
+}
+
/**
* kthread_create_on_node - create a kthread.
* @threadfn: the function to run until signal_pending(current).
@@ -457,6 +509,27 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
}
EXPORT_SYMBOL(kthread_create_on_node);
+#ifdef CONFIG_VE
+struct task_struct *kthread_create_on_node_ve_flags(struct ve_struct *ve,
+ unsigned long flags,
+ int (*threadfn)(void *data),
+ void *data, int node,
+ const char namefmt[],
+ ...)
+{
+ struct task_struct *task;
+ va_list args;
+
+ va_start(args, namefmt);
+ task = __kthread_create_on_node_ve(ve, flags,
+ threadfn, data, node, namefmt, args);
+ va_end(args);
+
+ return task;
+}
+EXPORT_SYMBOL(kthread_create_on_node_ve_flags);
+#endif
+
static void __kthread_bind_mask(struct task_struct *p, const struct cpumask *mask, unsigned int state)
{
unsigned long flags;
More information about the Devel
mailing list