]> www.infradead.org Git - nvme.git/commitdiff
bcachefs: twf: convert bch2_stdio_redirect_readline() to darray
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 30 May 2024 00:34:48 +0000 (20:34 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 14 Jul 2024 23:00:14 +0000 (19:00 -0400)
We now read the line from the buffer atomically, which means we have to
allow the buffer to grow past STDIO_REDIRECT_BUFSIZE if we're waiting
for a full line - this behaviour is necessary for
stdio_redirect_readline_timeout() in the next patch.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/error.c
fs/bcachefs/thread_with_file.c
fs/bcachefs/thread_with_file.h
fs/bcachefs/thread_with_file_types.h

index 3a9d0a03fecf3484a9ab39108042e57b8655a2dd..cfe7912159154dc05a25f4835353814955f5291a 100644 (file)
@@ -109,18 +109,21 @@ static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c)
        if (!stdio)
                return YN_NO;
 
-       char buf[100];
+       darray_char line = {};
        int ret;
 
        do {
                bch2_print(c, " (y,n, or Y,N for all errors of this type) ");
 
-               int r = bch2_stdio_redirect_readline(stdio, buf, sizeof(buf) - 1);
-               if (r < 0)
-                       return YN_NO;
-               buf[r] = '\0';
-       } while ((ret = parse_yn_response(buf)) < 0);
+               int r = bch2_stdio_redirect_readline(stdio, &line);
+               if (r < 0) {
+                       ret = YN_NO;
+                       break;
+               }
+               darray_last(line) = '\0';
+       } while ((ret = parse_yn_response(line.data)) < 0);
 
+       darray_exit(&line);
        return ret;
 }
 #else
index b1af7ac430f662aa2b827d0c6550ef6187089352..080afa7eff25c306ed1f75d74b24f135a156d770 100644 (file)
@@ -67,9 +67,14 @@ err:
 
 /* stdio_redirect */
 
+static bool stdio_redirect_has_more_input(struct stdio_redirect *stdio, size_t seen)
+{
+       return stdio->input.buf.nr > seen || stdio->done;
+}
+
 static bool stdio_redirect_has_input(struct stdio_redirect *stdio)
 {
-       return stdio->input.buf.nr || stdio->done;
+       return stdio_redirect_has_more_input(stdio, 0);
 }
 
 static bool stdio_redirect_has_output(struct stdio_redirect *stdio)
@@ -181,9 +186,13 @@ static ssize_t thread_with_stdio_write(struct file *file, const char __user *ubu
                }
 
                spin_lock(&buf->lock);
-               if (buf->buf.nr < STDIO_REDIRECT_BUFSIZE)
-                       darray_make_room_gfp(&buf->buf,
-                               min(b, STDIO_REDIRECT_BUFSIZE - buf->buf.nr), GFP_NOWAIT);
+               size_t makeroom = b;
+               if (!buf->waiting_for_line || memchr(buf->buf.data, '\n', buf->buf.nr))
+                       makeroom = min_t(ssize_t, makeroom,
+                                  max_t(ssize_t, STDIO_REDIRECT_BUFSIZE - buf->buf.nr,
+                                                 0));
+               darray_make_room_gfp(&buf->buf, makeroom, GFP_NOWAIT);
+
                b = min(len, darray_room(buf->buf));
 
                if (b && !copy_from_user_nofault(&darray_top(buf->buf), ubuf, b)) {
@@ -355,43 +364,48 @@ int bch2_stdio_redirect_read(struct stdio_redirect *stdio, char *ubuf, size_t le
        return ret;
 }
 
-int bch2_stdio_redirect_readline(struct stdio_redirect *stdio, char *ubuf, size_t len)
+int bch2_stdio_redirect_readline(struct stdio_redirect *stdio, darray_char *line)
 {
        struct stdio_buf *buf = &stdio->input;
-       size_t copied = 0;
-       ssize_t ret = 0;
+       size_t seen = 0;
 again:
-       do {
-               wait_event_timeout(buf->wait, stdio_redirect_has_input(stdio),
-                                  sysctl_hung_task_timeout_secs * HZ / 2);
-       } while (!stdio_redirect_has_input(stdio));
+       wait_event_timeout(buf->wait, stdio_redirect_has_more_input(stdio, seen),
+                          sysctl_hung_task_timeout_secs * HZ / 2);
 
-       if (stdio->done) {
-               ret = -1;
-               goto out;
-       }
+       if (stdio->done)
+               return -1;
 
        spin_lock(&buf->lock);
-       size_t b = min(len, buf->buf.nr);
-       char *n = memchr(buf->buf.data, '\n', b);
-       if (n)
-               b = min_t(size_t, b, n + 1 - buf->buf.data);
+       seen = buf->buf.nr;
+       char *n = memchr(buf->buf.data, '\n', seen);
+       if (!n) {
+               buf->waiting_for_line = true;
+               spin_unlock(&buf->lock);
+               goto again;
+       }
+
+       size_t b = n + 1 - buf->buf.data;
+       if (b > line->size) {
+               spin_unlock(&buf->lock);
+               int ret = darray_resize(line, b);
+               if (ret)
+                       return ret;
+               seen = 0;
+               goto again;
+       }
+
        buf->buf.nr -= b;
-       memcpy(ubuf, buf->buf.data, b);
+       memcpy(line->data, buf->buf.data, b);
        memmove(buf->buf.data,
                buf->buf.data + b,
                buf->buf.nr);
-       ubuf += b;
-       len -= b;
-       copied += b;
+       line->nr = b;
+
+       buf->waiting_for_line = false;
        spin_unlock(&buf->lock);
 
        wake_up(&buf->wait);
-
-       if (!n && len)
-               goto again;
-out:
-       return copied ?: ret;
+       return 0;
 }
 
 __printf(3, 0)
index 1d63d14d7dcae811a21e49a0cc509407daf7584c..e415dc2e2fb1fabed4a1dc0fe98838374bcdeac5 100644 (file)
@@ -71,7 +71,8 @@ int bch2_run_thread_with_stdio(struct thread_with_stdio *,
 int bch2_run_thread_with_stdout(struct thread_with_stdio *,
                                const struct thread_with_stdio_ops *);
 int bch2_stdio_redirect_read(struct stdio_redirect *, char *, size_t);
-int bch2_stdio_redirect_readline(struct stdio_redirect *, char *, size_t);
+
+int bch2_stdio_redirect_readline(struct stdio_redirect *, darray_char *);
 
 __printf(3, 0) ssize_t bch2_stdio_redirect_vprintf(struct stdio_redirect *, bool, const char *, va_list);
 __printf(3, 4) ssize_t bch2_stdio_redirect_printf(struct stdio_redirect *, bool, const char *, ...);
index e0daf4eec341e04a0924343fb58b9186eb845026..12668ff3d65db511e3fb7ea91284db86dfd29074 100644 (file)
@@ -8,6 +8,7 @@ struct stdio_buf {
        spinlock_t              lock;
        wait_queue_head_t       wait;
        darray_char             buf;
+       bool                    waiting_for_line;
 };
 
 struct stdio_redirect {