1 // SPDX-License-Identifier: GPL-2.0
5 #include "thread_with_file.h"
7 #include <linux/anon_inodes.h>
8 #include <linux/file.h>
9 #include <linux/kthread.h>
10 #include <linux/pagemap.h>
11 #include <linux/poll.h>
12 #include <linux/sched/sysctl.h>
14 void bch2_thread_with_file_exit(struct thread_with_file *thr)
17 kthread_stop(thr->task);
18 put_task_struct(thr->task);
22 int bch2_run_thread_with_file(struct thread_with_file *thr,
23 const struct file_operations *fops,
26 struct file *file = NULL;
28 unsigned fd_flags = O_CLOEXEC;
30 if (fops->read && fops->write)
37 char name[TASK_COMM_LEN];
38 get_task_comm(name, current);
41 thr->task = kthread_create(fn, thr, "%s", name);
42 ret = PTR_ERR_OR_ZERO(thr->task);
46 ret = get_unused_fd_flags(fd_flags);
51 file = anon_inode_getfile(name, fops, thr, fd_flags);
52 ret = PTR_ERR_OR_ZERO(file);
56 get_task_struct(thr->task);
57 wake_up_process(thr->task);
64 kthread_stop(thr->task);
70 static bool stdio_redirect_has_input(struct stdio_redirect *stdio)
72 return stdio->input.buf.nr || stdio->done;
75 static bool stdio_redirect_has_output(struct stdio_redirect *stdio)
77 return stdio->output.buf.nr || stdio->done;
80 #define STDIO_REDIRECT_BUFSIZE 4096
82 static bool stdio_redirect_has_input_space(struct stdio_redirect *stdio)
84 return stdio->input.buf.nr < STDIO_REDIRECT_BUFSIZE || stdio->done;
87 static bool stdio_redirect_has_output_space(struct stdio_redirect *stdio)
89 return stdio->output.buf.nr < STDIO_REDIRECT_BUFSIZE || stdio->done;
92 static void stdio_buf_init(struct stdio_buf *buf)
94 spin_lock_init(&buf->lock);
95 init_waitqueue_head(&buf->wait);
96 darray_init(&buf->buf);
99 /* thread_with_stdio */
101 static void thread_with_stdio_done(struct thread_with_stdio *thr)
103 thr->thr.done = true;
104 thr->stdio.done = true;
105 wake_up(&thr->stdio.input.wait);
106 wake_up(&thr->stdio.output.wait);
109 static ssize_t thread_with_stdio_read(struct file *file, char __user *ubuf,
110 size_t len, loff_t *ppos)
112 struct thread_with_stdio *thr =
113 container_of(file->private_data, struct thread_with_stdio, thr);
114 struct stdio_buf *buf = &thr->stdio.output;
115 size_t copied = 0, b;
118 if (!(file->f_flags & O_NONBLOCK)) {
119 ret = wait_event_interruptible(buf->wait, stdio_redirect_has_output(&thr->stdio));
122 } else if (!stdio_redirect_has_output(&thr->stdio))
125 while (len && buf->buf.nr) {
126 if (fault_in_writeable(ubuf, len) == len) {
131 spin_lock_irq(&buf->lock);
132 b = min_t(size_t, len, buf->buf.nr);
134 if (b && !copy_to_user_nofault(ubuf, buf->buf.data, b)) {
139 memmove(buf->buf.data,
143 spin_unlock_irq(&buf->lock);
146 return copied ?: ret;
149 static int thread_with_stdio_release(struct inode *inode, struct file *file)
151 struct thread_with_stdio *thr =
152 container_of(file->private_data, struct thread_with_stdio, thr);
154 thread_with_stdio_done(thr);
155 bch2_thread_with_file_exit(&thr->thr);
156 darray_exit(&thr->stdio.input.buf);
157 darray_exit(&thr->stdio.output.buf);
162 static ssize_t thread_with_stdio_write(struct file *file, const char __user *ubuf,
163 size_t len, loff_t *ppos)
165 struct thread_with_stdio *thr =
166 container_of(file->private_data, struct thread_with_stdio, thr);
167 struct stdio_buf *buf = &thr->stdio.input;
177 size_t b = len - fault_in_readable(ubuf, len);
183 spin_lock(&buf->lock);
184 if (buf->buf.nr < STDIO_REDIRECT_BUFSIZE)
185 darray_make_room_gfp(&buf->buf,
186 min(b, STDIO_REDIRECT_BUFSIZE - buf->buf.nr), GFP_NOWAIT);
187 b = min(len, darray_room(buf->buf));
189 if (b && !copy_from_user_nofault(&darray_top(buf->buf), ubuf, b)) {
195 spin_unlock(&buf->lock);
200 if ((file->f_flags & O_NONBLOCK)) {
205 ret = wait_event_interruptible(buf->wait,
206 stdio_redirect_has_input_space(&thr->stdio));
212 return copied ?: ret;
215 static __poll_t thread_with_stdio_poll(struct file *file, struct poll_table_struct *wait)
217 struct thread_with_stdio *thr =
218 container_of(file->private_data, struct thread_with_stdio, thr);
220 poll_wait(file, &thr->stdio.output.wait, wait);
221 poll_wait(file, &thr->stdio.input.wait, wait);
225 if (stdio_redirect_has_output(&thr->stdio))
227 if (stdio_redirect_has_input_space(&thr->stdio))
230 mask |= EPOLLHUP|EPOLLERR;
234 static __poll_t thread_with_stdout_poll(struct file *file, struct poll_table_struct *wait)
236 struct thread_with_stdio *thr =
237 container_of(file->private_data, struct thread_with_stdio, thr);
239 poll_wait(file, &thr->stdio.output.wait, wait);
243 if (stdio_redirect_has_output(&thr->stdio))
246 mask |= EPOLLHUP|EPOLLERR;
250 static int thread_with_stdio_flush(struct file *file, fl_owner_t id)
252 struct thread_with_stdio *thr =
253 container_of(file->private_data, struct thread_with_stdio, thr);
258 static long thread_with_stdio_ioctl(struct file *file, unsigned int cmd, unsigned long p)
260 struct thread_with_stdio *thr =
261 container_of(file->private_data, struct thread_with_stdio, thr);
263 if (thr->ops->unlocked_ioctl)
264 return thr->ops->unlocked_ioctl(thr, cmd, p);
268 static const struct file_operations thread_with_stdio_fops = {
270 .read = thread_with_stdio_read,
271 .write = thread_with_stdio_write,
272 .poll = thread_with_stdio_poll,
273 .flush = thread_with_stdio_flush,
274 .release = thread_with_stdio_release,
275 .unlocked_ioctl = thread_with_stdio_ioctl,
278 static const struct file_operations thread_with_stdout_fops = {
280 .read = thread_with_stdio_read,
281 .poll = thread_with_stdout_poll,
282 .flush = thread_with_stdio_flush,
283 .release = thread_with_stdio_release,
284 .unlocked_ioctl = thread_with_stdio_ioctl,
287 static int thread_with_stdio_fn(void *arg)
289 struct thread_with_stdio *thr = arg;
291 thr->thr.ret = thr->ops->fn(thr);
293 thread_with_stdio_done(thr);
297 void bch2_thread_with_stdio_init(struct thread_with_stdio *thr,
298 const struct thread_with_stdio_ops *ops)
300 stdio_buf_init(&thr->stdio.input);
301 stdio_buf_init(&thr->stdio.output);
305 int __bch2_run_thread_with_stdio(struct thread_with_stdio *thr)
307 return bch2_run_thread_with_file(&thr->thr, &thread_with_stdio_fops, thread_with_stdio_fn);
310 int bch2_run_thread_with_stdio(struct thread_with_stdio *thr,
311 const struct thread_with_stdio_ops *ops)
313 bch2_thread_with_stdio_init(thr, ops);
315 return __bch2_run_thread_with_stdio(thr);
318 int bch2_run_thread_with_stdout(struct thread_with_stdio *thr,
319 const struct thread_with_stdio_ops *ops)
321 stdio_buf_init(&thr->stdio.input);
322 stdio_buf_init(&thr->stdio.output);
325 return bch2_run_thread_with_file(&thr->thr, &thread_with_stdout_fops, thread_with_stdio_fn);
327 EXPORT_SYMBOL_GPL(bch2_run_thread_with_stdout);
329 int bch2_stdio_redirect_read(struct stdio_redirect *stdio, char *ubuf, size_t len)
331 struct stdio_buf *buf = &stdio->input;
334 * we're waiting on user input (or for the file descriptor to be
335 * closed), don't want a hung task warning:
338 wait_event_timeout(buf->wait, stdio_redirect_has_input(stdio),
339 sysctl_hung_task_timeout_secs * HZ / 2);
340 } while (!stdio_redirect_has_input(stdio));
345 spin_lock(&buf->lock);
346 int ret = min(len, buf->buf.nr);
348 memcpy(ubuf, buf->buf.data, ret);
349 memmove(buf->buf.data,
352 spin_unlock(&buf->lock);
358 int bch2_stdio_redirect_readline(struct stdio_redirect *stdio, char *ubuf, size_t len)
360 struct stdio_buf *buf = &stdio->input;
365 wait_event_timeout(buf->wait, stdio_redirect_has_input(stdio),
366 sysctl_hung_task_timeout_secs * HZ / 2);
367 } while (!stdio_redirect_has_input(stdio));
374 spin_lock(&buf->lock);
375 size_t b = min(len, buf->buf.nr);
376 char *n = memchr(buf->buf.data, '\n', b);
378 b = min_t(size_t, b, n + 1 - buf->buf.data);
380 memcpy(ubuf, buf->buf.data, b);
381 memmove(buf->buf.data,
387 spin_unlock(&buf->lock);
394 return copied ?: ret;
398 static ssize_t bch2_darray_vprintf(darray_char *out, gfp_t gfp, const char *fmt, va_list args)
406 va_copy(args2, args);
407 len = vsnprintf(out->data + out->nr, darray_room(*out), fmt, args2);
410 if (len + 1 <= darray_room(*out)) {
415 ret = darray_make_room_gfp(out, len + 1, gfp);
421 ssize_t bch2_stdio_redirect_vprintf(struct stdio_redirect *stdio, bool nonblocking,
422 const char *fmt, va_list args)
424 struct stdio_buf *buf = &stdio->output;
429 spin_lock_irqsave(&buf->lock, flags);
430 ret = bch2_darray_vprintf(&buf->buf, GFP_NOWAIT, fmt, args);
431 spin_unlock_irqrestore(&buf->lock, flags);
437 ret = wait_event_interruptible(buf->wait,
438 stdio_redirect_has_output_space(stdio));
448 ssize_t bch2_stdio_redirect_printf(struct stdio_redirect *stdio, bool nonblocking,
449 const char *fmt, ...)
455 ret = bch2_stdio_redirect_vprintf(stdio, nonblocking, fmt, args);
461 #endif /* NO_BCACHEFS_FS */