[Devel] [PATCH RHEL COMMIT] ve/kthreadd: create kthreadd in a containers pid ns

Konstantin Khorenko khorenko at virtuozzo.com
Tue Sep 28 14:42:34 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 74116ac9747f54416882cd312b68ae3fbd63bd6b
Author: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
Date:   Tue Sep 28 14:42:34 2021 +0300

    ve/kthreadd: create kthreadd in a containers pid ns
    
    The idea is simple: create another kworker in the one, attached to CT.
    The latter has containers pid ns for children, so the former will appear in
    containers pid ns.
    The latter then can be destroyed, thus leaving us "kthreadd" kernel thread not
    just attached, but also visible in the desired container.
    
    Notes:
    1) We create new kthread by using per-container creation helper.
    2) We don't need original attached worker when we have this new fully entered
    kthreadd, so this patch destroys original worker.
    3) New kthreadd is forked with CLONE_PARENT flag and thus will be reparented
    to host kthreadd.
    
    Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
    
    (cherry-picked from vz8 commit 2f1fad726487 ("ve/kthreadd: create kthreadd
    in a containers pid ns"))
    
    Signed-off-by: Nikita Yushchenko <nikita.yushchenko at virtuozzo.com>
---
 include/linux/ve.h |  1 +
 kernel/ve/ve.c     | 41 ++++++++++++++++++++++++++++++++++++++---
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/include/linux/ve.h b/include/linux/ve.h
index 6f75bd084e2e..cea4fa48d939 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -61,6 +61,7 @@ struct ve_struct {
 	int			_randomize_va_space;
 
 	struct kthread_worker	*kthreadd_worker;
+	struct task_struct	*kthreadd_task;
 };
 
 extern int nr_ve;
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index da86dae1a5f4..9c0070c39eb4 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -267,7 +267,9 @@ static void ve_drop_context(struct ve_struct *ve)
 
 static void ve_stop_kthreadd(struct ve_struct *ve)
 {
-	kthread_destroy_worker(ve->kthreadd_worker);
+	kthread_flush_worker(ve->kthreadd_worker);
+	kthread_stop(ve->kthreadd_task);
+	kfree(ve->kthreadd_worker);
 	ve->kthreadd_worker = NULL;
 }
 
@@ -334,16 +336,49 @@ static struct kthread_worker *ve_create_kworker(struct ve_struct *ve)
 	return w;
 }
 
+static int ve_create_kthreadd(struct ve_struct *ve,
+			      struct kthread_worker *gastarbeiter)
+{
+	struct kthread_worker *w;
+	struct task_struct *task;
+
+	w = kmalloc(sizeof(struct kthread_worker), GFP_KERNEL);
+	if (!w)
+		return -ENOMEM;
+	kthread_init_worker(w);
+
+	/* This is a trick to fork kthread in a container */
+	ve->kthreadd_worker = gastarbeiter;
+
+	/* We create kthread with CLONE_PARENT flags, because otherwise when
+	 * gastarbeiter will be stopped, kthreadd will be reparented to idle,
+	 * while we want to keep all the threads in kthreadd pool */
+	task = kthread_create_on_node_ve_flags(ve, CLONE_PARENT, kthread_worker_fn,
+					       w, NUMA_NO_NODE, "kthreadd");
+	if (IS_ERR(task)) {
+		kfree(w);
+		return PTR_ERR(task);
+	}
+	wake_up_process(task);
+
+	ve->kthreadd_task = task;
+	ve->kthreadd_worker = w;
+	return 0;
+}
+
 static int ve_start_kthreadd(struct ve_struct *ve)
 {
 	struct kthread_worker *w;
+	int err;
 
 	w = ve_create_kworker(ve);
 	if (IS_ERR(w))
 		return PTR_ERR(w);
 
-	ve->kthreadd_worker = w;
-	return 0;
+	err = ve_create_kthreadd(ve, w);
+
+	kthread_destroy_worker(w);
+	return err;
 }
 
 /* under ve->op_sem write-lock */


More information about the Devel mailing list