From: Kent Overstreet <kent.overstreet@xxxxxxxxx> Signed-off-by: Kent Overstreet <kent.overstreet@xxxxxxxxx> Reviewed-by: Darrick J. Wong <djwong@xxxxxxxxxx> Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- fs/bcachefs/thread_with_file.c | 15 ++++++++------- fs/bcachefs/thread_with_file.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/fs/bcachefs/thread_with_file.c b/fs/bcachefs/thread_with_file.c index 830efb06ef0be..dde9679b68b42 100644 --- a/fs/bcachefs/thread_with_file.c +++ b/fs/bcachefs/thread_with_file.c @@ -76,16 +76,16 @@ static bool stdio_redirect_has_output(struct stdio_redirect *stdio) return stdio->output.buf.nr || stdio->done; } -#define WRITE_BUFFER 4096 +#define STDIO_REDIRECT_BUFSIZE 4096 static bool stdio_redirect_has_input_space(struct stdio_redirect *stdio) { - return stdio->input.buf.nr < WRITE_BUFFER || stdio->done; + return stdio->input.buf.nr < STDIO_REDIRECT_BUFSIZE || stdio->done; } static bool stdio_redirect_has_output_space(struct stdio_redirect *stdio) { - return stdio->output.buf.nr < WRITE_BUFFER || stdio->done; + return stdio->output.buf.nr < STDIO_REDIRECT_BUFSIZE || stdio->done; } static void stdio_buf_init(struct stdio_buf *buf) @@ -171,11 +171,12 @@ static ssize_t thread_with_stdio_write(struct file *file, const char __user *ubu } spin_lock(&buf->lock); - if (buf->buf.nr < WRITE_BUFFER) - darray_make_room_gfp(&buf->buf, min(b, WRITE_BUFFER - buf->buf.nr), __GFP_NOWARN); + if (buf->buf.nr < STDIO_REDIRECT_BUFSIZE) + darray_make_room_gfp(&buf->buf, + min(b, STDIO_REDIRECT_BUFSIZE - buf->buf.nr), GFP_NOWAIT); b = min(len, darray_room(buf->buf)); - if (b && !copy_from_user_nofault(&buf->buf.data[buf->buf.nr], ubuf, b)) { + if (b && !copy_from_user_nofault(&darray_top(buf->buf), ubuf, b)) { buf->buf.nr += b; ubuf += b; len -= b; @@ -338,7 +339,7 @@ void bch2_stdio_redirect_vprintf(struct stdio_redirect *stdio, bool nonblocking, return; spin_lock_irqsave(&buf->lock, flags); - bch2_darray_vprintf(&buf->buf, nonblocking ? __GFP_NOWARN : GFP_KERNEL, fmt, args); + bch2_darray_vprintf(&buf->buf, nonblocking ? GFP_NOWAIT : GFP_KERNEL, fmt, args); spin_unlock_irqrestore(&buf->lock, flags); wake_up(&buf->wait); diff --git a/fs/bcachefs/thread_with_file.h b/fs/bcachefs/thread_with_file.h index 66212fcae226a..f06f8ff19a790 100644 --- a/fs/bcachefs/thread_with_file.h +++ b/fs/bcachefs/thread_with_file.h @@ -4,6 +4,38 @@ #include "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 bch2_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 {