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_more_input(struct stdio_redirect *stdio, size_t seen)
72 return stdio->input.buf.nr > seen || stdio->done;
75 static bool stdio_redirect_has_input(struct stdio_redirect *stdio)
77 return stdio_redirect_has_more_input(stdio, 0);
80 static bool stdio_redirect_has_output(struct stdio_redirect *stdio)
82 return stdio->output.buf.nr || stdio->done;
85 #define STDIO_REDIRECT_BUFSIZE 4096
87 static bool stdio_redirect_has_input_space(struct stdio_redirect *stdio)
89 return stdio->input.buf.nr < STDIO_REDIRECT_BUFSIZE || stdio->done;
92 static bool stdio_redirect_has_output_space(struct stdio_redirect *stdio)
94 return stdio->output.buf.nr < STDIO_REDIRECT_BUFSIZE || stdio->done;
97 static void stdio_buf_init(struct stdio_buf *buf)
99 spin_lock_init(&buf->lock);
100 init_waitqueue_head(&buf->wait);
101 darray_init(&buf->buf);
104 /* thread_with_stdio */
106 static void thread_with_stdio_done(struct thread_with_stdio *thr)
108 thr->thr.done = true;
109 thr->stdio.done = true;
110 wake_up(&thr->stdio.input.wait);
111 wake_up(&thr->stdio.output.wait);
114 static ssize_t thread_with_stdio_read(struct file *file, char __user *ubuf,
115 size_t len, loff_t *ppos)
117 struct thread_with_stdio *thr =
118 container_of(file->private_data, struct thread_with_stdio, thr);
119 struct stdio_buf *buf = &thr->stdio.output;
120 size_t copied = 0, b;
123 if (!(file->f_flags & O_NONBLOCK)) {
124 ret = wait_event_interruptible(buf->wait, stdio_redirect_has_output(&thr->stdio));
127 } else if (!stdio_redirect_has_output(&thr->stdio))
130 while (len && buf->buf.nr) {
131 if (fault_in_writeable(ubuf, len) == len) {
136 spin_lock_irq(&buf->lock);
137 b = min_t(size_t, len, buf->buf.nr);
139 if (b && !copy_to_user_nofault(ubuf, buf->buf.data, b)) {
144 memmove(buf->buf.data,
148 spin_unlock_irq(&buf->lock);
151 return copied ?: ret;
154 static int thread_with_stdio_release(struct inode *inode, struct file *file)
156 struct thread_with_stdio *thr =
157 container_of(file->private_data, struct thread_with_stdio, thr);
159 thread_with_stdio_done(thr);
160 bch2_thread_with_file_exit(&thr->thr);
161 darray_exit(&thr->stdio.input.buf);
162 darray_exit(&thr->stdio.output.buf);
167 static ssize_t thread_with_stdio_write(struct file *file, const char __user *ubuf,
168 size_t len, loff_t *ppos)
170 struct thread_with_stdio *thr =
171 container_of(file->private_data, struct thread_with_stdio, thr);
172 struct stdio_buf *buf = &thr->stdio.input;
182 size_t b = len - fault_in_readable(ubuf, len);
188 spin_lock(&buf->lock);
190 if (!buf->waiting_for_line || memchr(buf->buf.data, '\n', buf->buf.nr))
191 makeroom = min_t(ssize_t, makeroom,
192 max_t(ssize_t, STDIO_REDIRECT_BUFSIZE - buf->buf.nr,
194 darray_make_room_gfp(&buf->buf, makeroom, GFP_NOWAIT);
196 b = min(len, darray_room(buf->buf));
198 if (b && !copy_from_user_nofault(&darray_top(buf->buf), ubuf, b)) {
204 spin_unlock(&buf->lock);
209 if ((file->f_flags & O_NONBLOCK)) {
214 ret = wait_event_interruptible(buf->wait,
215 stdio_redirect_has_input_space(&thr->stdio));
221 return copied ?: ret;
224 static __poll_t thread_with_stdio_poll(struct file *file, struct poll_table_struct *wait)
226 struct thread_with_stdio *thr =
227 container_of(file->private_data, struct thread_with_stdio, thr);
229 poll_wait(file, &thr->stdio.output.wait, wait);
230 poll_wait(file, &thr->stdio.input.wait, wait);
234 if (stdio_redirect_has_output(&thr->stdio))
236 if (stdio_redirect_has_input_space(&thr->stdio))
239 mask |= EPOLLHUP|EPOLLERR;
243 static __poll_t thread_with_stdout_poll(struct file *file, struct poll_table_struct *wait)
245 struct thread_with_stdio *thr =
246 container_of(file->private_data, struct thread_with_stdio, thr);
248 poll_wait(file, &thr->stdio.output.wait, wait);
252 if (stdio_redirect_has_output(&thr->stdio))
255 mask |= EPOLLHUP|EPOLLERR;
259 static int thread_with_stdio_flush(struct file *file, fl_owner_t id)
261 struct thread_with_stdio *thr =
262 container_of(file->private_data, struct thread_with_stdio, thr);
267 static long thread_with_stdio_ioctl(struct file *file, unsigned int cmd, unsigned long p)
269 struct thread_with_stdio *thr =
270 container_of(file->private_data, struct thread_with_stdio, thr);
272 if (thr->ops->unlocked_ioctl)
273 return thr->ops->unlocked_ioctl(thr, cmd, p);
277 static const struct file_operations thread_with_stdio_fops = {
278 .read = thread_with_stdio_read,
279 .write = thread_with_stdio_write,
280 .poll = thread_with_stdio_poll,
281 .flush = thread_with_stdio_flush,
282 .release = thread_with_stdio_release,
283 .unlocked_ioctl = thread_with_stdio_ioctl,
286 static const struct file_operations thread_with_stdout_fops = {
287 .read = thread_with_stdio_read,
288 .poll = thread_with_stdout_poll,
289 .flush = thread_with_stdio_flush,
290 .release = thread_with_stdio_release,
291 .unlocked_ioctl = thread_with_stdio_ioctl,
294 static int thread_with_stdio_fn(void *arg)
296 struct thread_with_stdio *thr = arg;
298 thr->thr.ret = thr->ops->fn(thr);
300 thread_with_stdio_done(thr);
304 void bch2_thread_with_stdio_init(struct thread_with_stdio *thr,
305 const struct thread_with_stdio_ops *ops)
307 stdio_buf_init(&thr->stdio.input);
308 stdio_buf_init(&thr->stdio.output);
312 int __bch2_run_thread_with_stdio(struct thread_with_stdio *thr)
314 return bch2_run_thread_with_file(&thr->thr, &thread_with_stdio_fops, thread_with_stdio_fn);
317 int bch2_run_thread_with_stdio(struct thread_with_stdio *thr,
318 const struct thread_with_stdio_ops *ops)
320 bch2_thread_with_stdio_init(thr, ops);
322 return __bch2_run_thread_with_stdio(thr);
325 int bch2_run_thread_with_stdout(struct thread_with_stdio *thr,
326 const struct thread_with_stdio_ops *ops)
328 stdio_buf_init(&thr->stdio.input);
329 stdio_buf_init(&thr->stdio.output);
332 return bch2_run_thread_with_file(&thr->thr, &thread_with_stdout_fops, thread_with_stdio_fn);
334 EXPORT_SYMBOL_GPL(bch2_run_thread_with_stdout);
336 int bch2_stdio_redirect_read(struct stdio_redirect *stdio, char *ubuf, size_t len)
338 struct stdio_buf *buf = &stdio->input;
341 * we're waiting on user input (or for the file descriptor to be
342 * closed), don't want a hung task warning:
345 wait_event_timeout(buf->wait, stdio_redirect_has_input(stdio),
346 sysctl_hung_task_timeout_secs * HZ / 2);
347 } while (!stdio_redirect_has_input(stdio));
352 spin_lock(&buf->lock);
353 int ret = min(len, buf->buf.nr);
355 memcpy(ubuf, buf->buf.data, ret);
356 memmove(buf->buf.data,
359 spin_unlock(&buf->lock);
365 int bch2_stdio_redirect_readline_timeout(struct stdio_redirect *stdio,
367 unsigned long timeout)
369 unsigned long until = jiffies + timeout, t;
370 struct stdio_buf *buf = &stdio->input;
373 t = timeout != MAX_SCHEDULE_TIMEOUT
374 ? max_t(long, until - jiffies, 0)
377 t = min(t, sysctl_hung_task_timeout_secs * HZ / 2);
379 wait_event_timeout(buf->wait, stdio_redirect_has_more_input(stdio, seen), t);
384 spin_lock(&buf->lock);
386 char *n = memchr(buf->buf.data, '\n', seen);
388 if (!n && timeout != MAX_SCHEDULE_TIMEOUT && time_after_eq(jiffies, until)) {
389 spin_unlock(&buf->lock);
394 buf->waiting_for_line = true;
395 spin_unlock(&buf->lock);
399 size_t b = n + 1 - buf->buf.data;
400 if (b > line->size) {
401 spin_unlock(&buf->lock);
402 int ret = darray_resize(line, b);
410 memcpy(line->data, buf->buf.data, b);
411 memmove(buf->buf.data,
416 buf->waiting_for_line = false;
417 spin_unlock(&buf->lock);
423 int bch2_stdio_redirect_readline(struct stdio_redirect *stdio, darray_char *line)
425 return bch2_stdio_redirect_readline_timeout(stdio, line, MAX_SCHEDULE_TIMEOUT);
429 static ssize_t bch2_darray_vprintf(darray_char *out, gfp_t gfp, const char *fmt, va_list args)
437 va_copy(args2, args);
438 len = vsnprintf(out->data + out->nr, darray_room(*out), fmt, args2);
441 if (len + 1 <= darray_room(*out)) {
446 ret = darray_make_room_gfp(out, len + 1, gfp);
452 ssize_t bch2_stdio_redirect_vprintf(struct stdio_redirect *stdio, bool nonblocking,
453 const char *fmt, va_list args)
455 struct stdio_buf *buf = &stdio->output;
460 spin_lock_irqsave(&buf->lock, flags);
461 ret = bch2_darray_vprintf(&buf->buf, GFP_NOWAIT, fmt, args);
462 spin_unlock_irqrestore(&buf->lock, flags);
468 ret = wait_event_interruptible(buf->wait,
469 stdio_redirect_has_output_space(stdio));
479 ssize_t bch2_stdio_redirect_printf(struct stdio_redirect *stdio, bool nonblocking,
480 const char *fmt, ...)
486 ret = bch2_stdio_redirect_vprintf(stdio, nonblocking, fmt, args);
492 #endif /* NO_BCACHEFS_FS */