public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Christian Brauner <brauner@kernel.org>
To: linux-fsdevel@vger.kernel.org,
	 Linus Torvalds <torvalds@linux-foundation.org>
Cc: linux-kernel@vger.kernel.org,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	 Jens Axboe <axboe@kernel.dk>, Jan Kara <jack@suse.cz>,
	 Tejun Heo <tj@kernel.org>, Jann Horn <jannh@google.com>,
	 Christian Brauner <brauner@kernel.org>
Subject: [PATCH RFC DRAFT POC 01/11] kthread: refactor __kthread_create_on_node() to take a struct argument
Date: Tue, 03 Mar 2026 14:49:12 +0100	[thread overview]
Message-ID: <20260303-work-kthread-nullfs-v1-1-87e559b94375@kernel.org> (raw)
In-Reply-To: <20260303-work-kthread-nullfs-v1-0-87e559b94375@kernel.org>

Refactor __kthread_create_on_node() to take a const struct
kthread_create_info pointer instead of individual parameters. The
caller fills in the relevant fields in a stack-local struct and the
helper heap-copies it, making it trivial to add new kthread creation
options without changing the function signature.

As part of this, collapse __kthread_create_worker_on_node() into
__kthread_create_on_node() by adding a kthread_worker:1 bitfield to
struct kthread_create_info. When set, the unified helper allocates and
initializes the kthread_worker internally, removing the need for a
separate helper.

Also switch create_kthread() from the kernel_thread() wrapper to
constructing struct kernel_clone_args directly and calling
kernel_clone(). This makes the clone flags explicit and prepares for
passing richer per-kthread arguments through kernel_clone_args in
subsequent patches.

No functional change.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 kernel/kthread.c | 87 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 48 insertions(+), 39 deletions(-)

diff --git a/kernel/kthread.c b/kernel/kthread.c
index 791210daf8b4..84d535c7a635 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -45,6 +45,7 @@ struct kthread_create_info
 	int (*threadfn)(void *data);
 	void *data;
 	int node;
+	u32 kthread_worker:1;
 
 	/* Result passed back to kthread_create() from kthreadd. */
 	struct task_struct *result;
@@ -451,13 +452,20 @@ int tsk_fork_get_node(struct task_struct *tsk)
 static void create_kthread(struct kthread_create_info *create)
 {
 	int pid;
+	struct kernel_clone_args args = {
+		.flags		= CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED,
+		.exit_signal	= SIGCHLD,
+		.fn		= kthread,
+		.fn_arg		= create,
+		.name		= create->full_name,
+		.kthread	= 1,
+	};
 
 #ifdef CONFIG_NUMA
 	current->pref_node_fork = create->node;
 #endif
 	/* We want our own signal handler (we take no signals by default). */
-	pid = kernel_thread(kthread, create, create->full_name,
-			    CLONE_FS | CLONE_FILES | SIGCHLD);
+	pid = kernel_clone(&args);
 	if (pid < 0) {
 		/* Release the structure when caller killed by a fatal signal. */
 		struct completion *done = xchg(&create->done, NULL);
@@ -472,21 +480,32 @@ 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,
+static struct task_struct *__kthread_create_on_node(const struct kthread_create_info *info,
 						    const char namefmt[],
 						    va_list args)
 {
 	DECLARE_COMPLETION_ONSTACK(done);
+	struct kthread_worker *worker = NULL;
 	struct task_struct *task;
-	struct kthread_create_info *create = kmalloc_obj(*create);
+	struct kthread_create_info *create;
 
+	create = kmalloc_obj(*create);
 	if (!create)
 		return ERR_PTR(-ENOMEM);
-	create->threadfn = threadfn;
-	create->data = data;
-	create->node = node;
+
+	*create = *info;
+
+	if (create->kthread_worker) {
+		worker = kzalloc_obj(*worker);
+		if (!worker) {
+			kfree(create);
+			return ERR_PTR(-ENOMEM);
+		}
+		kthread_init_worker(worker);
+		create->threadfn = kthread_worker_fn;
+		create->data = worker;
+	}
+
 	create->done = &done;
 	create->full_name = kvasprintf(GFP_KERNEL, namefmt, args);
 	if (!create->full_name) {
@@ -520,6 +539,8 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
 	}
 	task = create->result;
 free_create:
+	if (IS_ERR(task))
+		kfree(worker);
 	kfree(create);
 	return task;
 }
@@ -552,11 +573,16 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
 					   const char namefmt[],
 					   ...)
 {
+	struct kthread_create_info info = {
+		.threadfn	= threadfn,
+		.data		= data,
+		.node		= node,
+	};
 	struct task_struct *task;
 	va_list args;
 
 	va_start(args, namefmt);
-	task = __kthread_create_on_node(threadfn, data, node, namefmt, args);
+	task = __kthread_create_on_node(&info, namefmt, args);
 	va_end(args);
 
 	return task;
@@ -1045,34 +1071,6 @@ int kthread_worker_fn(void *worker_ptr)
 }
 EXPORT_SYMBOL_GPL(kthread_worker_fn);
 
-static __printf(3, 0) struct kthread_worker *
-__kthread_create_worker_on_node(unsigned int flags, int node,
-				const char namefmt[], va_list args)
-{
-	struct kthread_worker *worker;
-	struct task_struct *task;
-
-	worker = kzalloc_obj(*worker);
-	if (!worker)
-		return ERR_PTR(-ENOMEM);
-
-	kthread_init_worker(worker);
-
-	task = __kthread_create_on_node(kthread_worker_fn, worker,
-					node, namefmt, args);
-	if (IS_ERR(task))
-		goto fail_task;
-
-	worker->flags = flags;
-	worker->task = task;
-
-	return worker;
-
-fail_task:
-	kfree(worker);
-	return ERR_CAST(task);
-}
-
 /**
  * kthread_create_worker_on_node - create a kthread worker
  * @flags: flags modifying the default behavior of the worker
@@ -1086,13 +1084,24 @@ __kthread_create_worker_on_node(unsigned int flags, int node,
 struct kthread_worker *
 kthread_create_worker_on_node(unsigned int flags, int node, const char namefmt[], ...)
 {
+	struct kthread_create_info info = {
+		.node		= node,
+		.kthread_worker	= 1,
+	};
 	struct kthread_worker *worker;
+	struct task_struct *task;
 	va_list args;
 
 	va_start(args, namefmt);
-	worker = __kthread_create_worker_on_node(flags, node, namefmt, args);
+	task = __kthread_create_on_node(&info, namefmt, args);
 	va_end(args);
 
+	if (IS_ERR(task))
+		return ERR_CAST(task);
+
+	worker = kthread_data(task);
+	worker->flags = flags;
+	worker->task = task;
 	return worker;
 }
 EXPORT_SYMBOL(kthread_create_worker_on_node);

-- 
2.47.3


  reply	other threads:[~2026-03-03 13:49 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-03 13:49 [PATCH RFC DRAFT POC 00/11] fs,kthread: isolate all kthreads in nullfs Christian Brauner
2026-03-03 13:49 ` Christian Brauner [this message]
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 02/11] kthread: remove unused flags argument from kthread worker creation API Christian Brauner
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 03/11] kthread: add extensible kthread_create()/kthread_run() pattern Christian Brauner
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 04/11] fs: notice when init abandons fs sharing Christian Brauner
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 05/11] fs: add LOOKUP_IN_INIT Christian Brauner
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 06/11] fs: add file_open_init() Christian Brauner
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 07/11] block: add bdev_file_open_init() Christian Brauner
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 08/11] fs: allow to pass lookup flags to filename_*() Christian Brauner
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 09/11] fs: add init_root() Christian Brauner
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 10/11] tree-wide: make all kthread path lookups to use LOOKUP_IN_INIT Christian Brauner
2026-03-03 15:03   ` Christoph Hellwig
2026-03-03 13:49 ` [PATCH RFC DRAFT POC 11/11] fs: isolate all kthreads in nullfs Christian Brauner
2026-03-06  7:26 ` [PATCH RFC DRAFT POC 00/11] fs,kthread: " Askar Safin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260303-work-kthread-nullfs-v1-1-87e559b94375@kernel.org \
    --to=brauner@kernel.org \
    --cc=axboe@kernel.dk \
    --cc=jack@suse.cz \
    --cc=jannh@google.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tj@kernel.org \
    --cc=torvalds@linux-foundation.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox