]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - libbcachefs/error.c
Update bcachefs sources to 7c0fe6f104 bcachefs: Fix bch2_fsck_ask_yn()
[bcachefs-tools-debian] / libbcachefs / error.c
index 1dae649ff0e223386eefe0e1992ddd564f020197..b08cd23dee00576640a0919b401d1c5729a1af61 100644 (file)
@@ -65,10 +65,52 @@ void bch2_io_error(struct bch_dev *ca)
        //queue_work(system_long_wq, &ca->io_error_work);
 }
 
+enum ask_yn {
+       YN_NO,
+       YN_YES,
+       YN_ALLNO,
+       YN_ALLYES,
+};
+
 #ifdef __KERNEL__
-#define ask_yn()       false
+#define bch2_fsck_ask_yn()     YN_NO
 #else
+
 #include "tools-util.h"
+
+enum ask_yn bch2_fsck_ask_yn(void)
+{
+       char *buf = NULL;
+       size_t buflen = 0;
+       bool ret;
+
+       while (true) {
+               fputs(" (y,n, or Y,N for all errors of this type) ", stdout);
+               fflush(stdout);
+
+               if (getline(&buf, &buflen, stdin) < 0)
+                       die("error reading from standard input");
+
+               strim(buf);
+               if (strlen(buf) != 1)
+                       continue;
+
+               switch (buf[0]) {
+               case 'n':
+                       return YN_NO;
+               case 'y':
+                       return YN_YES;
+               case 'N':
+                       return YN_ALLNO;
+               case 'Y':
+                       return YN_ALLYES;
+               }
+       }
+
+       free(buf);
+       return ret;
+}
+
 #endif
 
 static struct fsck_err_state *fsck_err_get(struct bch_fs *c, const char *fmt)
@@ -117,6 +159,11 @@ int bch2_fsck_err(struct bch_fs *c, unsigned flags, const char *fmt, ...)
        mutex_lock(&c->fsck_error_lock);
        s = fsck_err_get(c, fmt);
        if (s) {
+               /*
+                * We may be called multiple times for the same error on
+                * transaction restart - this memoizes instead of asking the user
+                * multiple times for the same error:
+                */
                if (s->last_msg && !strcmp(buf.buf, s->last_msg)) {
                        ret = s->ret;
                        mutex_unlock(&c->fsck_error_lock);
@@ -161,14 +208,28 @@ int bch2_fsck_err(struct bch_fs *c, unsigned flags, const char *fmt, ...)
                prt_str(out, ", exiting");
                ret = -BCH_ERR_fsck_errors_not_fixed;
        } else if (flags & FSCK_CAN_FIX) {
-               if (c->opts.fix_errors == FSCK_OPT_ASK) {
+               int fix = s && s->fix
+                       ? s->fix
+                       : c->opts.fix_errors;
+
+               if (fix == FSCK_OPT_ASK) {
+                       int ask;
+
                        prt_str(out, ": fix?");
                        bch2_print_string_as_lines(KERN_ERR, out->buf);
                        print = false;
-                       ret = ask_yn()
+
+                       ask = bch2_fsck_ask_yn();
+
+                       if (ask >= YN_ALLNO && s)
+                               s->fix = ask == YN_ALLNO
+                                       ? FSCK_OPT_NO
+                                       : FSCK_OPT_YES;
+
+                       ret = ask & 1
                                ? -BCH_ERR_fsck_fix
                                : -BCH_ERR_fsck_ignore;
-               } else if (c->opts.fix_errors == FSCK_OPT_YES ||
+               } else if (fix == FSCK_OPT_YES ||
                           (c->opts.nochanges &&
                            !(flags & FSCK_CAN_IGNORE))) {
                        prt_str(out, ", fixing");