summaryrefslogtreecommitdiff
path: root/fs/bcachefs/error.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-04-15 14:26:14 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:10:00 -0400
commit853b7393c20d5e129f2b16719102a05bbb5dc36f (patch)
treec9aabb2384e92de017639fd7cdd9cc1c5da2f46a /fs/bcachefs/error.c
parent6b9857b208d7566d8bfd332a543b1dca92202c2b (diff)
downloadlwn-853b7393c20d5e129f2b16719102a05bbb5dc36f.tar.gz
lwn-853b7393c20d5e129f2b16719102a05bbb5dc36f.zip
bcachefs: Allow answering y or n to all fsck errors of given type
This changes the ask_yn() function used by fsck to accept Y or N, meaning yes or no for all errors of a given type. With this, the user can be prompted only for distinct error types - useful when a filesystem has lots of errors. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/error.c')
-rw-r--r--fs/bcachefs/error.c63
1 files changed, 59 insertions, 4 deletions
diff --git a/fs/bcachefs/error.c b/fs/bcachefs/error.c
index 1dae649ff0e2..aa640284ed19 100644
--- a/fs/bcachefs/error.c
+++ b/fs/bcachefs/error.c
@@ -65,10 +65,51 @@ 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,Y,N) ", stdout);
+ fflush(stdout);
+
+ if (getline(&buf, &buflen, stdin) < 0)
+ die("error reading from standard input");
+
+ 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)
@@ -161,14 +202,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");