Commit | Line | Data |
---|---|---|
1c6fdbd8 KO |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include "bcachefs.h" | |
a850bde6 | 3 | #include "btree_iter.h" |
1c6fdbd8 | 4 | #include "error.h" |
b3c7fd35 | 5 | #include "journal.h" |
d2554263 | 6 | #include "recovery_passes.h" |
1c6fdbd8 | 7 | #include "super.h" |
96f37eab | 8 | #include "thread_with_file.h" |
1c6fdbd8 | 9 | |
89b05118 KO |
10 | #define FSCK_ERR_RATELIMIT_NR 10 |
11 | ||
1c6fdbd8 KO |
12 | bool bch2_inconsistent_error(struct bch_fs *c) |
13 | { | |
3c471b65 | 14 | set_bit(BCH_FS_error, &c->flags); |
1c6fdbd8 KO |
15 | |
16 | switch (c->opts.errors) { | |
2436cb9f | 17 | case BCH_ON_ERROR_continue: |
1c6fdbd8 | 18 | return false; |
33dfafa9 | 19 | case BCH_ON_ERROR_fix_safe: |
2436cb9f | 20 | case BCH_ON_ERROR_ro: |
1c6fdbd8 | 21 | if (bch2_fs_emergency_read_only(c)) |
b3c7fd35 KO |
22 | bch_err(c, "inconsistency detected - emergency read only at journal seq %llu", |
23 | journal_cur_seq(&c->journal)); | |
1c6fdbd8 | 24 | return true; |
2436cb9f | 25 | case BCH_ON_ERROR_panic: |
1c6fdbd8 KO |
26 | panic(bch2_fmt(c, "panic after error")); |
27 | return true; | |
28 | default: | |
29 | BUG(); | |
30 | } | |
31 | } | |
32 | ||
52946d82 | 33 | int bch2_topology_error(struct bch_fs *c) |
aae15aaf | 34 | { |
3c471b65 | 35 | set_bit(BCH_FS_topology_error, &c->flags); |
52946d82 | 36 | if (!test_bit(BCH_FS_fsck_running, &c->flags)) { |
aae15aaf | 37 | bch2_inconsistent_error(c); |
52946d82 KO |
38 | return -BCH_ERR_btree_need_topology_repair; |
39 | } else { | |
40 | return bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_topology) ?: | |
41 | -BCH_ERR_btree_node_read_validate_error; | |
42 | } | |
aae15aaf KO |
43 | } |
44 | ||
1c6fdbd8 KO |
45 | void bch2_fatal_error(struct bch_fs *c) |
46 | { | |
47 | if (bch2_fs_emergency_read_only(c)) | |
b74b147d | 48 | bch_err(c, "fatal error - emergency read only"); |
1c6fdbd8 KO |
49 | } |
50 | ||
51 | void bch2_io_error_work(struct work_struct *work) | |
52 | { | |
53 | struct bch_dev *ca = container_of(work, struct bch_dev, io_error_work); | |
54 | struct bch_fs *c = ca->fs; | |
55 | bool dev; | |
56 | ||
1ada1606 | 57 | down_write(&c->state_lock); |
2436cb9f | 58 | dev = bch2_dev_state_allowed(c, ca, BCH_MEMBER_STATE_ro, |
1c6fdbd8 KO |
59 | BCH_FORCE_IF_DEGRADED); |
60 | if (dev | |
2436cb9f | 61 | ? __bch2_dev_set_state(c, ca, BCH_MEMBER_STATE_ro, |
1c6fdbd8 KO |
62 | BCH_FORCE_IF_DEGRADED) |
63 | : bch2_fs_emergency_read_only(c)) | |
64 | bch_err(ca, | |
65 | "too many IO errors, setting %s RO", | |
66 | dev ? "device" : "filesystem"); | |
1ada1606 | 67 | up_write(&c->state_lock); |
1c6fdbd8 KO |
68 | } |
69 | ||
94119eeb | 70 | void bch2_io_error(struct bch_dev *ca, enum bch_member_error_type type) |
1c6fdbd8 | 71 | { |
94119eeb | 72 | atomic64_inc(&ca->errors[type]); |
1c6fdbd8 KO |
73 | //queue_work(system_long_wq, &ca->io_error_work); |
74 | } | |
75 | ||
853b7393 KO |
76 | enum ask_yn { |
77 | YN_NO, | |
78 | YN_YES, | |
79 | YN_ALLNO, | |
80 | YN_ALLYES, | |
81 | }; | |
82 | ||
96f37eab KO |
83 | static enum ask_yn parse_yn_response(char *buf) |
84 | { | |
85 | buf = strim(buf); | |
86 | ||
87 | if (strlen(buf) == 1) | |
88 | switch (buf[0]) { | |
89 | case 'n': | |
90 | return YN_NO; | |
91 | case 'y': | |
92 | return YN_YES; | |
93 | case 'N': | |
94 | return YN_ALLNO; | |
95 | case 'Y': | |
96 | return YN_ALLYES; | |
97 | } | |
98 | return -1; | |
99 | } | |
100 | ||
1c6fdbd8 | 101 | #ifdef __KERNEL__ |
889fb3dc | 102 | static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c, struct btree_trans *trans) |
96f37eab KO |
103 | { |
104 | struct stdio_redirect *stdio = c->stdio; | |
105 | ||
106 | if (c->stdio_filter && c->stdio_filter != current) | |
107 | stdio = NULL; | |
108 | ||
109 | if (!stdio) | |
110 | return YN_NO; | |
111 | ||
889fb3dc KO |
112 | if (trans) |
113 | bch2_trans_unlock(trans); | |
114 | ||
115 | unsigned long unlock_long_at = trans ? jiffies + HZ * 2 : 0; | |
0c97c437 | 116 | darray_char line = {}; |
96f37eab KO |
117 | int ret; |
118 | ||
119 | do { | |
889fb3dc | 120 | unsigned long t; |
96f37eab | 121 | bch2_print(c, " (y,n, or Y,N for all errors of this type) "); |
889fb3dc KO |
122 | rewait: |
123 | t = unlock_long_at | |
124 | ? max_t(long, unlock_long_at - jiffies, 0) | |
125 | : MAX_SCHEDULE_TIMEOUT; | |
126 | ||
127 | int r = bch2_stdio_redirect_readline_timeout(stdio, &line, t); | |
128 | if (r == -ETIME) { | |
129 | bch2_trans_unlock_long(trans); | |
130 | unlock_long_at = 0; | |
131 | goto rewait; | |
132 | } | |
96f37eab | 133 | |
0c97c437 KO |
134 | if (r < 0) { |
135 | ret = YN_NO; | |
136 | break; | |
137 | } | |
889fb3dc | 138 | |
0c97c437 KO |
139 | darray_last(line) = '\0'; |
140 | } while ((ret = parse_yn_response(line.data)) < 0); | |
96f37eab | 141 | |
0c97c437 | 142 | darray_exit(&line); |
96f37eab KO |
143 | return ret; |
144 | } | |
1c6fdbd8 | 145 | #else |
853b7393 | 146 | |
1c6fdbd8 | 147 | #include "tools-util.h" |
853b7393 | 148 | |
889fb3dc | 149 | static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c, struct btree_trans *trans) |
853b7393 KO |
150 | { |
151 | char *buf = NULL; | |
152 | size_t buflen = 0; | |
96f37eab | 153 | int ret; |
853b7393 | 154 | |
96f37eab | 155 | do { |
4f2c166e | 156 | fputs(" (y,n, or Y,N for all errors of this type) ", stdout); |
853b7393 KO |
157 | fflush(stdout); |
158 | ||
159 | if (getline(&buf, &buflen, stdin) < 0) | |
160 | die("error reading from standard input"); | |
96f37eab | 161 | } while ((ret = parse_yn_response(buf)) < 0); |
853b7393 KO |
162 | |
163 | free(buf); | |
164 | return ret; | |
165 | } | |
166 | ||
1c6fdbd8 KO |
167 | #endif |
168 | ||
dbb9936b | 169 | static struct fsck_err_state *fsck_err_get(struct bch_fs *c, const char *fmt) |
1c6fdbd8 | 170 | { |
dbb9936b | 171 | struct fsck_err_state *s; |
1c6fdbd8 | 172 | |
d55ddf6e | 173 | if (!test_bit(BCH_FS_fsck_running, &c->flags)) |
dbb9936b | 174 | return NULL; |
1c6fdbd8 | 175 | |
f5d26fa3 | 176 | list_for_each_entry(s, &c->fsck_error_msgs, list) |
dbb9936b KO |
177 | if (s->fmt == fmt) { |
178 | /* | |
179 | * move it to the head of the list: repeated fsck errors | |
180 | * are common | |
181 | */ | |
f5d26fa3 | 182 | list_move(&s->list, &c->fsck_error_msgs); |
dbb9936b KO |
183 | return s; |
184 | } | |
1c6fdbd8 | 185 | |
beb6db68 | 186 | s = kzalloc(sizeof(*s), GFP_NOFS); |
1c6fdbd8 | 187 | if (!s) { |
f5d26fa3 | 188 | if (!c->fsck_alloc_msgs_err) |
1c6fdbd8 | 189 | bch_err(c, "kmalloc err, cannot ratelimit fsck errs"); |
f5d26fa3 | 190 | c->fsck_alloc_msgs_err = true; |
dbb9936b | 191 | return NULL; |
1c6fdbd8 KO |
192 | } |
193 | ||
194 | INIT_LIST_HEAD(&s->list); | |
195 | s->fmt = fmt; | |
f5d26fa3 | 196 | list_add(&s->list, &c->fsck_error_msgs); |
dbb9936b KO |
197 | return s; |
198 | } | |
199 | ||
19391b92 KO |
200 | /* s/fix?/fixing/ s/recreate?/recreating/ */ |
201 | static void prt_actioning(struct printbuf *out, const char *action) | |
202 | { | |
203 | unsigned len = strlen(action); | |
204 | ||
205 | BUG_ON(action[len - 1] != '?'); | |
206 | --len; | |
207 | ||
208 | if (action[len - 1] == 'e') | |
209 | --len; | |
210 | ||
211 | prt_bytes(out, action, len); | |
212 | prt_str(out, "ing"); | |
213 | } | |
214 | ||
33dfafa9 KO |
215 | static const u8 fsck_flags_extra[] = { |
216 | #define x(t, n, flags) [BCH_FSCK_ERR_##t] = flags, | |
217 | BCH_SB_ERRS() | |
218 | #undef x | |
219 | }; | |
220 | ||
a850bde6 KO |
221 | int __bch2_fsck_err(struct bch_fs *c, |
222 | struct btree_trans *trans, | |
b65db750 KO |
223 | enum bch_fsck_flags flags, |
224 | enum bch_sb_error_id err, | |
225 | const char *fmt, ...) | |
dbb9936b KO |
226 | { |
227 | struct fsck_err_state *s = NULL; | |
228 | va_list args; | |
22f51621 | 229 | bool print = true, suppressing = false, inconsistent = false; |
dbb9936b KO |
230 | struct printbuf buf = PRINTBUF, *out = &buf; |
231 | int ret = -BCH_ERR_fsck_ignore; | |
19391b92 | 232 | const char *action_orig = "fix?", *action = action_orig; |
dbb9936b | 233 | |
e76a2b65 KO |
234 | might_sleep(); |
235 | ||
33dfafa9 KO |
236 | if (!WARN_ON(err >= ARRAY_SIZE(fsck_flags_extra))) |
237 | flags |= fsck_flags_extra[err]; | |
238 | ||
a850bde6 KO |
239 | if (!c) |
240 | c = trans->c; | |
241 | ||
5612daaf KO |
242 | /* |
243 | * Ugly: if there's a transaction in the current task it has to be | |
244 | * passed in to unlock if we prompt for user input. | |
245 | * | |
246 | * But, plumbing a transaction and transaction restarts into | |
247 | * bkey_validate() is problematic. | |
248 | * | |
249 | * So: | |
250 | * - make all bkey errors AUTOFIX, they're simple anyways (we just | |
251 | * delete the key) | |
252 | * - and we don't need to warn if we're not prompting | |
253 | */ | |
254 | WARN_ON(!(flags & FSCK_AUTOFIX) && !trans && bch2_current_has_btree_trans(c)); | |
a850bde6 | 255 | |
a64a3733 KO |
256 | if ((flags & FSCK_CAN_FIX) && |
257 | test_bit(err, c->sb.errors_silent)) | |
8b16413c KO |
258 | return -BCH_ERR_fsck_fix; |
259 | ||
b65db750 KO |
260 | bch2_sb_error_count(c, err); |
261 | ||
9c5d38bb KO |
262 | va_start(args, fmt); |
263 | prt_vprintf(out, fmt, args); | |
264 | va_end(args); | |
265 | ||
19391b92 KO |
266 | /* Custom fix/continue/recreate/etc.? */ |
267 | if (out->buf[out->pos - 1] == '?') { | |
268 | const char *p = strrchr(out->buf, ','); | |
269 | if (p) { | |
270 | out->pos = p - out->buf; | |
271 | action = kstrdup(p + 2, GFP_KERNEL); | |
272 | if (!action) { | |
273 | ret = -ENOMEM; | |
274 | goto err; | |
275 | } | |
276 | } | |
277 | } | |
278 | ||
f5d26fa3 | 279 | mutex_lock(&c->fsck_error_msgs_lock); |
dbb9936b KO |
280 | s = fsck_err_get(c, fmt); |
281 | if (s) { | |
c8d5b714 KO |
282 | /* |
283 | * We may be called multiple times for the same error on | |
284 | * transaction restart - this memoizes instead of asking the user | |
285 | * multiple times for the same error: | |
286 | */ | |
9c5d38bb KO |
287 | if (s->last_msg && !strcmp(buf.buf, s->last_msg)) { |
288 | ret = s->ret; | |
f5d26fa3 | 289 | mutex_unlock(&c->fsck_error_msgs_lock); |
19391b92 | 290 | goto err; |
9c5d38bb KO |
291 | } |
292 | ||
293 | kfree(s->last_msg); | |
294 | s->last_msg = kstrdup(buf.buf, GFP_KERNEL); | |
19391b92 KO |
295 | if (!s->last_msg) { |
296 | mutex_unlock(&c->fsck_error_msgs_lock); | |
297 | ret = -ENOMEM; | |
298 | goto err; | |
299 | } | |
9c5d38bb | 300 | |
dbb9936b KO |
301 | if (c->opts.ratelimit_errors && |
302 | !(flags & FSCK_NO_RATELIMIT) && | |
303 | s->nr >= FSCK_ERR_RATELIMIT_NR) { | |
304 | if (s->nr == FSCK_ERR_RATELIMIT_NR) | |
305 | suppressing = true; | |
306 | else | |
307 | print = false; | |
308 | } | |
309 | ||
dbb9936b | 310 | s->nr++; |
e2ee3eaa | 311 | } |
dbb9936b | 312 | |
b2d1d56b | 313 | #ifdef BCACHEFS_LOG_PREFIX |
dbb9936b KO |
314 | if (!strncmp(fmt, "bcachefs:", 9)) |
315 | prt_printf(out, bch2_log_msg(c, "")); | |
b2d1d56b | 316 | #endif |
dbb9936b | 317 | |
33dfafa9 KO |
318 | if ((flags & FSCK_CAN_FIX) && |
319 | (flags & FSCK_AUTOFIX) && | |
320 | (c->opts.errors == BCH_ON_ERROR_continue || | |
321 | c->opts.errors == BCH_ON_ERROR_fix_safe)) { | |
322 | prt_str(out, ", "); | |
323 | prt_actioning(out, action); | |
324 | ret = -BCH_ERR_fsck_fix; | |
325 | } else if (!test_bit(BCH_FS_fsck_running, &c->flags)) { | |
dbb9936b KO |
326 | if (c->opts.errors != BCH_ON_ERROR_continue || |
327 | !(flags & (FSCK_CAN_FIX|FSCK_CAN_IGNORE))) { | |
328 | prt_str(out, ", shutting down"); | |
22f51621 | 329 | inconsistent = true; |
dbb9936b KO |
330 | ret = -BCH_ERR_fsck_errors_not_fixed; |
331 | } else if (flags & FSCK_CAN_FIX) { | |
19391b92 KO |
332 | prt_str(out, ", "); |
333 | prt_actioning(out, action); | |
dbb9936b KO |
334 | ret = -BCH_ERR_fsck_fix; |
335 | } else { | |
336 | prt_str(out, ", continuing"); | |
337 | ret = -BCH_ERR_fsck_ignore; | |
338 | } | |
a0f8faea | 339 | } else if (c->opts.fix_errors == FSCK_FIX_exit) { |
dbb9936b KO |
340 | prt_str(out, ", exiting"); |
341 | ret = -BCH_ERR_fsck_errors_not_fixed; | |
0bc166ff | 342 | } else if (flags & FSCK_CAN_FIX) { |
853b7393 KO |
343 | int fix = s && s->fix |
344 | ? s->fix | |
345 | : c->opts.fix_errors; | |
346 | ||
a0f8faea | 347 | if (fix == FSCK_FIX_ask) { |
19391b92 KO |
348 | prt_str(out, ", "); |
349 | prt_str(out, action); | |
853b7393 | 350 | |
96f37eab KO |
351 | if (bch2_fs_stdio_redirect(c)) |
352 | bch2_print(c, "%s", out->buf); | |
353 | else | |
354 | bch2_print_string_as_lines(KERN_ERR, out->buf); | |
dbb9936b | 355 | print = false; |
853b7393 | 356 | |
889fb3dc KO |
357 | int ask = bch2_fsck_ask_yn(c, trans); |
358 | ||
359 | if (trans) { | |
360 | ret = bch2_trans_relock(trans); | |
361 | if (ret) { | |
362 | mutex_unlock(&c->fsck_error_msgs_lock); | |
363 | goto err; | |
364 | } | |
365 | } | |
853b7393 KO |
366 | |
367 | if (ask >= YN_ALLNO && s) | |
368 | s->fix = ask == YN_ALLNO | |
a0f8faea KO |
369 | ? FSCK_FIX_no |
370 | : FSCK_FIX_yes; | |
853b7393 KO |
371 | |
372 | ret = ask & 1 | |
dbb9936b KO |
373 | ? -BCH_ERR_fsck_fix |
374 | : -BCH_ERR_fsck_ignore; | |
a0f8faea | 375 | } else if (fix == FSCK_FIX_yes || |
1c6fdbd8 KO |
376 | (c->opts.nochanges && |
377 | !(flags & FSCK_CAN_IGNORE))) { | |
19391b92 KO |
378 | prt_str(out, ", "); |
379 | prt_actioning(out, action); | |
dbb9936b | 380 | ret = -BCH_ERR_fsck_fix; |
1c6fdbd8 | 381 | } else { |
19391b92 KO |
382 | prt_str(out, ", not "); |
383 | prt_actioning(out, action); | |
1c6fdbd8 KO |
384 | } |
385 | } else if (flags & FSCK_NEED_FSCK) { | |
dbb9936b | 386 | prt_str(out, " (run fsck to correct)"); |
1c6fdbd8 | 387 | } else { |
dbb9936b | 388 | prt_str(out, " (repair unimplemented)"); |
1c6fdbd8 KO |
389 | } |
390 | ||
dbb9936b | 391 | if (ret == -BCH_ERR_fsck_ignore && |
a0f8faea | 392 | (c->opts.fix_errors == FSCK_FIX_exit || |
dbb9936b KO |
393 | !(flags & FSCK_CAN_IGNORE))) |
394 | ret = -BCH_ERR_fsck_errors_not_fixed; | |
395 | ||
492e24d7 KO |
396 | bool exiting = |
397 | test_bit(BCH_FS_fsck_running, &c->flags) && | |
398 | (ret != -BCH_ERR_fsck_fix && | |
399 | ret != -BCH_ERR_fsck_ignore); | |
400 | ||
401 | if (exiting) | |
402 | print = true; | |
403 | ||
96f37eab KO |
404 | if (print) { |
405 | if (bch2_fs_stdio_redirect(c)) | |
406 | bch2_print(c, "%s\n", out->buf); | |
407 | else | |
408 | bch2_print_string_as_lines(KERN_ERR, out->buf); | |
409 | } | |
dbb9936b | 410 | |
492e24d7 | 411 | if (exiting) |
dbb9936b KO |
412 | bch_err(c, "Unable to continue, halting"); |
413 | else if (suppressing) | |
1c6fdbd8 KO |
414 | bch_err(c, "Ratelimiting new instances of previous error"); |
415 | ||
9c5d38bb KO |
416 | if (s) |
417 | s->ret = ret; | |
418 | ||
f5d26fa3 | 419 | mutex_unlock(&c->fsck_error_msgs_lock); |
1c6fdbd8 | 420 | |
22f51621 KO |
421 | if (inconsistent) |
422 | bch2_inconsistent_error(c); | |
423 | ||
dbb9936b | 424 | if (ret == -BCH_ERR_fsck_fix) { |
3c471b65 | 425 | set_bit(BCH_FS_errors_fixed, &c->flags); |
0bc166ff | 426 | } else { |
3c471b65 KO |
427 | set_bit(BCH_FS_errors_not_fixed, &c->flags); |
428 | set_bit(BCH_FS_error, &c->flags); | |
0bc166ff | 429 | } |
19391b92 KO |
430 | err: |
431 | if (action != action_orig) | |
432 | kfree(action); | |
433 | printbuf_exit(&buf); | |
dbb9936b | 434 | return ret; |
1c6fdbd8 KO |
435 | } |
436 | ||
d97de0d0 KO |
437 | int __bch2_bkey_fsck_err(struct bch_fs *c, |
438 | struct bkey_s_c k, | |
658c82f4 | 439 | enum bch_validate_flags validate_flags, |
d97de0d0 KO |
440 | enum bch_sb_error_id err, |
441 | const char *fmt, ...) | |
442 | { | |
658c82f4 KO |
443 | if (validate_flags & BCH_VALIDATE_silent) |
444 | return -BCH_ERR_fsck_delete_bkey; | |
445 | ||
446 | unsigned fsck_flags = 0; | |
447 | if (!(validate_flags & (BCH_VALIDATE_write|BCH_VALIDATE_commit))) | |
448 | fsck_flags |= FSCK_AUTOFIX|FSCK_CAN_FIX; | |
449 | ||
d97de0d0 KO |
450 | struct printbuf buf = PRINTBUF; |
451 | va_list args; | |
452 | ||
453 | prt_str(&buf, "invalid bkey "); | |
454 | bch2_bkey_val_to_text(&buf, c, k); | |
455 | prt_str(&buf, "\n "); | |
456 | va_start(args, fmt); | |
457 | prt_vprintf(&buf, fmt, args); | |
458 | va_end(args); | |
459 | prt_str(&buf, ": delete?"); | |
460 | ||
658c82f4 | 461 | int ret = __bch2_fsck_err(c, NULL, fsck_flags, err, "%s", buf.buf); |
d97de0d0 KO |
462 | printbuf_exit(&buf); |
463 | return ret; | |
464 | } | |
465 | ||
1c6fdbd8 KO |
466 | void bch2_flush_fsck_errs(struct bch_fs *c) |
467 | { | |
468 | struct fsck_err_state *s, *n; | |
469 | ||
f5d26fa3 | 470 | mutex_lock(&c->fsck_error_msgs_lock); |
1c6fdbd8 | 471 | |
f5d26fa3 | 472 | list_for_each_entry_safe(s, n, &c->fsck_error_msgs, list) { |
9c5d38bb KO |
473 | if (s->ratelimited && s->last_msg) |
474 | bch_err(c, "Saw %llu errors like:\n %s", s->nr, s->last_msg); | |
1c6fdbd8 KO |
475 | |
476 | list_del(&s->list); | |
9c5d38bb | 477 | kfree(s->last_msg); |
1c6fdbd8 KO |
478 | kfree(s); |
479 | } | |
480 | ||
f5d26fa3 | 481 | mutex_unlock(&c->fsck_error_msgs_lock); |
1c6fdbd8 | 482 | } |