diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2024-02-05 00:51:23 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2024-03-22 17:33:11 -0400 |
commit | e5cf4d5ae338b4e3ac5ba6af3f2fb03306eaf5d9 (patch) | |
tree | 903c307b84c133175cf62b376de220b1c2bea316 /include | |
parent | d02f81d6093a8ffe1ca6673a118ca84a55c3cace (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.h | 79 | ||||
-rw-r--r-- | include/linux/thread_with_file_types.h | 25 |
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 */ |