Commit 889fb3dc authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Unlock trans when waiting for user input in fsck

We can't hold locks while waiting for user input, that's a deadlock.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 747d1d6c
...@@ -99,7 +99,7 @@ static enum ask_yn parse_yn_response(char *buf) ...@@ -99,7 +99,7 @@ static enum ask_yn parse_yn_response(char *buf)
} }
#ifdef __KERNEL__ #ifdef __KERNEL__
static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c) static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c, struct btree_trans *trans)
{ {
struct stdio_redirect *stdio = c->stdio; struct stdio_redirect *stdio = c->stdio;
...@@ -109,17 +109,33 @@ static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c) ...@@ -109,17 +109,33 @@ static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c)
if (!stdio) if (!stdio)
return YN_NO; return YN_NO;
if (trans)
bch2_trans_unlock(trans);
unsigned long unlock_long_at = trans ? jiffies + HZ * 2 : 0;
darray_char line = {}; darray_char line = {};
int ret; int ret;
do { do {
unsigned long t;
bch2_print(c, " (y,n, or Y,N for all errors of this type) "); bch2_print(c, " (y,n, or Y,N for all errors of this type) ");
rewait:
t = unlock_long_at
? max_t(long, unlock_long_at - jiffies, 0)
: MAX_SCHEDULE_TIMEOUT;
int r = bch2_stdio_redirect_readline_timeout(stdio, &line, t);
if (r == -ETIME) {
bch2_trans_unlock_long(trans);
unlock_long_at = 0;
goto rewait;
}
int r = bch2_stdio_redirect_readline(stdio, &line);
if (r < 0) { if (r < 0) {
ret = YN_NO; ret = YN_NO;
break; break;
} }
darray_last(line) = '\0'; darray_last(line) = '\0';
} while ((ret = parse_yn_response(line.data)) < 0); } while ((ret = parse_yn_response(line.data)) < 0);
...@@ -130,7 +146,7 @@ static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c) ...@@ -130,7 +146,7 @@ static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c)
#include "tools-util.h" #include "tools-util.h"
static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c) static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c, struct btree_trans *trans)
{ {
char *buf = NULL; char *buf = NULL;
size_t buflen = 0; size_t buflen = 0;
...@@ -326,7 +342,15 @@ int __bch2_fsck_err(struct bch_fs *c, ...@@ -326,7 +342,15 @@ int __bch2_fsck_err(struct bch_fs *c,
bch2_print_string_as_lines(KERN_ERR, out->buf); bch2_print_string_as_lines(KERN_ERR, out->buf);
print = false; print = false;
int ask = bch2_fsck_ask_yn(c); int ask = bch2_fsck_ask_yn(c, trans);
if (trans) {
ret = bch2_trans_relock(trans);
if (ret) {
mutex_unlock(&c->fsck_error_msgs_lock);
goto err;
}
}
if (ask >= YN_ALLNO && s) if (ask >= YN_ALLNO && s)
s->fix = ask == YN_ALLNO s->fix = ask == YN_ALLNO
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment