]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Online fsck
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 5 Dec 2023 00:49:21 +0000 (19:49 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 7 Dec 2023 17:04:24 +0000 (12:04 -0500)
This hooks up cmd_fsck to the new BCH_IOCTL_FSCK_ONLINE: if a filesystem
is mounted, we now use that instead of bailing out with an error.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
cmd_fsck.c

index f7dcae98e518917d9fa3ba5636233111fb4aa8d9..0c9663d3eb7f8c880a80832cbb100d17d2ae420d 100644 (file)
@@ -1,5 +1,7 @@
 
 #include <getopt.h>
+#include <sys/uio.h>
+#include <unistd.h>
 #include "cmds.h"
 #include "libbcachefs/error.h"
 #include "libbcachefs.h"
@@ -23,6 +25,62 @@ static void usage(void)
             "Report bugs to <linux-bcachefs@vger.kernel.org>");
 }
 
+static void setnonblocking(int fd)
+{
+       int flags = fcntl(fd, F_GETFL);
+       if (fcntl(fd, F_SETFL, flags|O_NONBLOCK))
+               die("fcntl error: %m");
+}
+
+static int do_splice(int rfd, int wfd)
+{
+       char buf[4096];
+
+       int r = read(rfd, buf, sizeof(buf));
+       if (r < 0 && errno == EAGAIN)
+               return 0;
+       if (r < 0)
+               return r;
+       if (!r)
+               return 1;
+       if (write(wfd, buf, r) != r)
+               die("write error");
+       return 0;
+}
+
+static int fsck_online(const char *dev_path)
+{
+       int dev_idx;
+       struct bchfs_handle fs = bchu_fs_open_by_dev(dev_path, &dev_idx);
+
+       struct bch_ioctl_fsck_online fsck = { 0 };
+
+       int fsck_fd = ioctl(fs.ioctl_fd, BCH_IOCTL_FSCK_ONLINE, &fsck);
+       if (fsck_fd < 0)
+               die("BCH_IOCTL_FSCK_ONLINE error: %s", bch2_err_str(fsck_fd));
+
+       setnonblocking(STDIN_FILENO);
+       setnonblocking(fsck_fd);
+
+       while (true) {
+               fd_set fds;
+
+               FD_ZERO(&fds);
+               FD_SET(STDIN_FILENO, &fds);
+               FD_SET(fsck_fd, &fds);
+
+               select(fsck_fd + 1, &fds, NULL, NULL, NULL);
+
+               int r = do_splice(fsck_fd, STDOUT_FILENO) ?:
+                       do_splice(STDIN_FILENO, fsck_fd);
+               if (r)
+                       return r < 0 ? r : 0;
+       }
+
+       pr_info("done");
+       return 0;
+}
+
 int cmd_fsck(int argc, char *argv[])
 {
        static const struct option longopts[] = {
@@ -80,16 +138,9 @@ int cmd_fsck(int argc, char *argv[])
                exit(8);
        }
 
-       for (i = 0; i < argc; i++) {
-               switch (dev_mounted(argv[i])) {
-               case 1:
-                       ret |= 2;
-                       break;
-               case 2:
-                       fprintf(stderr, "%s is mounted read-write - aborting\n", argv[i]);
-                       exit(8);
-               }
-       }
+       for (i = 0; i < argc; i++)
+               if (dev_mounted(argv[i]))
+                       return fsck_online(argv[i]);
 
        struct bch_fs *c = bch2_fs_open(argv, argc, opts);
        if (IS_ERR(c)) {