summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-02-05 00:51:23 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2024-03-22 17:33:11 -0400
commite5cf4d5ae338b4e3ac5ba6af3f2fb03306eaf5d9 (patch)
tree903c307b84c133175cf62b376de220b1c2bea316 /include
parentd02f81d6093a8ffe1ca6673a118ca84a55c3cace (diff)
thread_with_file: Lift from bcachefstime_stats_twf
thread_with_file and thread_with_stdio are abstractions for connecting kthreads to file descriptors, which is handy for all sorts of things - the running kthread has its lifetime connected to the file descriptor, which means an asynchronous job running in the kernel can easily exit in response to a ctrl-c, and the file descriptor also provides a communications channel. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'include')
-rw-r--r--include/linux/thread_with_file.h79
-rw-r--r--include/linux/thread_with_file_types.h25
2 files changed, 104 insertions, 0 deletions
diff --git a/include/linux/thread_with_file.h b/include/linux/thread_with_file.h
new file mode 100644
index 000000000000..cf44337af3e9
--- /dev/null
+++ b/include/linux/thread_with_file.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) 2022-2024 Kent Overstreet <kent.overstreet@linux.dev>
+ */
+#ifndef _LINUX_THREAD_WITH_FILE_H
+#define _LINUX_THREAD_WITH_FILE_H
+
+#include <linux/thread_with_file_types.h>
+
+/*
+ * Thread with file: Run a kthread and connect it to a file descriptor, so that
+ * it can be interacted with via fd read/write methods and closing the file
+ * descriptor stops the kthread.
+ *
+ * We have two different APIs:
+ *
+ * thread_with_file, the low level version.
+ * You get to define the full file_operations, including your release function,
+ * which means that you must call thread_with_file_exit() from your
+ * .release method
+ *
+ * thread_with_stdio, the higher level version
+ * This implements full piping of input and output, including .poll.
+ *
+ * Notes on behaviour:
+ * - kthread shutdown behaves like writing or reading from a pipe that has been
+ * closed
+ * - Input and output buffers are 4096 bytes, although buffers may in some
+ * situations slightly exceed that limit so as to avoid chopping off a
+ * message in the middle in nonblocking mode.
+ * - Input/output buffers are lazily allocated, with GFP_NOWAIT allocations -
+ * should be fine but might change in future revisions.
+ * - Output buffer may grow past 4096 bytes to deal with messages that are
+ * bigger than 4096 bytes
+ * - Writing may be done blocking or nonblocking; in nonblocking mode, we only
+ * drop entire messages.
+ *
+ * To write, use stdio_redirect_printf()
+ * To read, use stdio_redirect_read() or stdio_redirect_readline()
+ */
+
+struct task_struct;
+
+struct thread_with_file {
+ struct task_struct *task;
+ int ret;
+ bool done;
+};
+
+void thread_with_file_exit(struct thread_with_file *);
+int run_thread_with_file(struct thread_with_file *,
+ const struct file_operations *,
+ int (*fn)(void *));
+
+struct thread_with_stdio;
+
+struct thread_with_stdio_ops {
+ void (*exit)(struct thread_with_stdio *);
+ int (*fn)(struct thread_with_stdio *);
+ long (*unlocked_ioctl)(struct thread_with_stdio *, unsigned int, unsigned long);
+};
+
+struct thread_with_stdio {
+ struct thread_with_file thr;
+ struct stdio_redirect stdio;
+ const struct thread_with_stdio_ops *ops;
+};
+
+int run_thread_with_stdio(struct thread_with_stdio *,
+ const struct thread_with_stdio_ops *);
+int run_thread_with_stdout(struct thread_with_stdio *,
+ const struct thread_with_stdio_ops *);
+int stdio_redirect_read(struct stdio_redirect *, char *, size_t);
+int stdio_redirect_readline(struct stdio_redirect *, char *, size_t);
+
+__printf(3, 0) ssize_t stdio_redirect_vprintf(struct stdio_redirect *, bool, const char *, va_list);
+__printf(3, 4) ssize_t stdio_redirect_printf(struct stdio_redirect *, bool, const char *, ...);
+
+#endif /* _LINUX_THREAD_WITH_FILE_H */
diff --git a/include/linux/thread_with_file_types.h b/include/linux/thread_with_file_types.h
new file mode 100644
index 000000000000..98d0ad125322
--- /dev/null
+++ b/include/linux/thread_with_file_types.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_THREAD_WITH_FILE_TYPES_H
+#define _LINUX_THREAD_WITH_FILE_TYPES_H
+
+#include <linux/darray_types.h>
+#include <linux/spinlock_types.h>
+#include <linux/wait.h>
+
+struct stdio_buf {
+ spinlock_t lock;
+ wait_queue_head_t wait;
+ darray_char buf;
+};
+
+struct stdio_redirect {
+ struct stdio_buf input;
+ struct stdio_buf output;
+
+ spinlock_t input_lock;
+ wait_queue_head_t input_wait;
+ darray_char input_buf;
+ bool done;
+};
+
+#endif /* _LINUX_THREAD_WITH_FILE_TYPES_H */