11c6fdbd8SKent Overstreet // SPDX-License-Identifier: GPL-2.0 21c6fdbd8SKent Overstreet #include "bcachefs.h" 31c6fdbd8SKent Overstreet #include "error.h" 41c6fdbd8SKent Overstreet #include "super.h" 596f37eabSKent Overstreet #include "thread_with_file.h" 61c6fdbd8SKent Overstreet 789b05118SKent Overstreet #define FSCK_ERR_RATELIMIT_NR 10 889b05118SKent Overstreet 91c6fdbd8SKent Overstreet bool bch2_inconsistent_error(struct bch_fs *c) 101c6fdbd8SKent Overstreet { 113c471b65SKent Overstreet set_bit(BCH_FS_error, &c->flags); 121c6fdbd8SKent Overstreet 131c6fdbd8SKent Overstreet switch (c->opts.errors) { 142436cb9fSKent Overstreet case BCH_ON_ERROR_continue: 151c6fdbd8SKent Overstreet return false; 162436cb9fSKent Overstreet case BCH_ON_ERROR_ro: 171c6fdbd8SKent Overstreet if (bch2_fs_emergency_read_only(c)) 18b74b147dSKent Overstreet bch_err(c, "inconsistency detected - emergency read only"); 191c6fdbd8SKent Overstreet return true; 202436cb9fSKent Overstreet case BCH_ON_ERROR_panic: 211c6fdbd8SKent Overstreet panic(bch2_fmt(c, "panic after error")); 221c6fdbd8SKent Overstreet return true; 231c6fdbd8SKent Overstreet default: 241c6fdbd8SKent Overstreet BUG(); 251c6fdbd8SKent Overstreet } 261c6fdbd8SKent Overstreet } 271c6fdbd8SKent Overstreet 28aae15aafSKent Overstreet void bch2_topology_error(struct bch_fs *c) 29aae15aafSKent Overstreet { 303c471b65SKent Overstreet set_bit(BCH_FS_topology_error, &c->flags); 31d55ddf6eSKent Overstreet if (!test_bit(BCH_FS_fsck_running, &c->flags)) 32aae15aafSKent Overstreet bch2_inconsistent_error(c); 33aae15aafSKent Overstreet } 34aae15aafSKent Overstreet 351c6fdbd8SKent Overstreet void bch2_fatal_error(struct bch_fs *c) 361c6fdbd8SKent Overstreet { 371c6fdbd8SKent Overstreet if (bch2_fs_emergency_read_only(c)) 38b74b147dSKent Overstreet bch_err(c, "fatal error - emergency read only"); 391c6fdbd8SKent Overstreet } 401c6fdbd8SKent Overstreet 411c6fdbd8SKent Overstreet void bch2_io_error_work(struct work_struct *work) 421c6fdbd8SKent Overstreet { 431c6fdbd8SKent Overstreet struct bch_dev *ca = container_of(work, struct bch_dev, io_error_work); 441c6fdbd8SKent Overstreet struct bch_fs *c = ca->fs; 451c6fdbd8SKent Overstreet bool dev; 461c6fdbd8SKent Overstreet 471ada1606SKent Overstreet down_write(&c->state_lock); 482436cb9fSKent Overstreet dev = bch2_dev_state_allowed(c, ca, BCH_MEMBER_STATE_ro, 491c6fdbd8SKent Overstreet BCH_FORCE_IF_DEGRADED); 501c6fdbd8SKent Overstreet if (dev 512436cb9fSKent Overstreet ? __bch2_dev_set_state(c, ca, BCH_MEMBER_STATE_ro, 521c6fdbd8SKent Overstreet BCH_FORCE_IF_DEGRADED) 531c6fdbd8SKent Overstreet : bch2_fs_emergency_read_only(c)) 541c6fdbd8SKent Overstreet bch_err(ca, 551c6fdbd8SKent Overstreet "too many IO errors, setting %s RO", 561c6fdbd8SKent Overstreet dev ? "device" : "filesystem"); 571ada1606SKent Overstreet up_write(&c->state_lock); 581c6fdbd8SKent Overstreet } 591c6fdbd8SKent Overstreet 6094119eebSKent Overstreet void bch2_io_error(struct bch_dev *ca, enum bch_member_error_type type) 611c6fdbd8SKent Overstreet { 6294119eebSKent Overstreet atomic64_inc(&ca->errors[type]); 631c6fdbd8SKent Overstreet //queue_work(system_long_wq, &ca->io_error_work); 641c6fdbd8SKent Overstreet } 651c6fdbd8SKent Overstreet 66853b7393SKent Overstreet enum ask_yn { 67853b7393SKent Overstreet YN_NO, 68853b7393SKent Overstreet YN_YES, 69853b7393SKent Overstreet YN_ALLNO, 70853b7393SKent Overstreet YN_ALLYES, 71853b7393SKent Overstreet }; 72853b7393SKent Overstreet 7396f37eabSKent Overstreet static enum ask_yn parse_yn_response(char *buf) 74853b7393SKent Overstreet { 7596f37eabSKent Overstreet buf = strim(buf); 76853b7393SKent Overstreet 7796f37eabSKent Overstreet if (strlen(buf) == 1) 78853b7393SKent Overstreet switch (buf[0]) { 79853b7393SKent Overstreet case 'n': 80853b7393SKent Overstreet return YN_NO; 81853b7393SKent Overstreet case 'y': 82853b7393SKent Overstreet return YN_YES; 83853b7393SKent Overstreet case 'N': 84853b7393SKent Overstreet return YN_ALLNO; 85853b7393SKent Overstreet case 'Y': 86853b7393SKent Overstreet return YN_ALLYES; 87853b7393SKent Overstreet } 8896f37eabSKent Overstreet return -1; 89853b7393SKent Overstreet } 90853b7393SKent Overstreet 9196f37eabSKent Overstreet #ifdef __KERNEL__ 9296f37eabSKent Overstreet static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c) 9396f37eabSKent Overstreet { 9496f37eabSKent Overstreet struct stdio_redirect *stdio = c->stdio; 9596f37eabSKent Overstreet 9696f37eabSKent Overstreet if (c->stdio_filter && c->stdio_filter != current) 9796f37eabSKent Overstreet stdio = NULL; 9896f37eabSKent Overstreet 9996f37eabSKent Overstreet if (!stdio) 10096f37eabSKent Overstreet return YN_NO; 10196f37eabSKent Overstreet 10296f37eabSKent Overstreet char buf[100]; 10396f37eabSKent Overstreet int ret; 10496f37eabSKent Overstreet 10596f37eabSKent Overstreet do { 10696f37eabSKent Overstreet bch2_print(c, " (y,n, or Y,N for all errors of this type) "); 10796f37eabSKent Overstreet 10896f37eabSKent Overstreet int r = bch2_stdio_redirect_readline(stdio, buf, sizeof(buf) - 1); 10996f37eabSKent Overstreet if (r < 0) 11096f37eabSKent Overstreet return YN_NO; 11196f37eabSKent Overstreet buf[r] = '\0'; 11296f37eabSKent Overstreet } while ((ret = parse_yn_response(buf)) < 0); 11396f37eabSKent Overstreet 11496f37eabSKent Overstreet return ret; 11596f37eabSKent Overstreet } 11696f37eabSKent Overstreet #else 11796f37eabSKent Overstreet 11896f37eabSKent Overstreet #include "tools-util.h" 11996f37eabSKent Overstreet 12096f37eabSKent Overstreet static enum ask_yn bch2_fsck_ask_yn(struct bch_fs *c) 12196f37eabSKent Overstreet { 12296f37eabSKent Overstreet char *buf = NULL; 12396f37eabSKent Overstreet size_t buflen = 0; 12496f37eabSKent Overstreet int ret; 12596f37eabSKent Overstreet 12696f37eabSKent Overstreet do { 12796f37eabSKent Overstreet fputs(" (y,n, or Y,N for all errors of this type) ", stdout); 12896f37eabSKent Overstreet fflush(stdout); 12996f37eabSKent Overstreet 13096f37eabSKent Overstreet if (getline(&buf, &buflen, stdin) < 0) 13196f37eabSKent Overstreet die("error reading from standard input"); 13296f37eabSKent Overstreet } while ((ret = parse_yn_response(buf)) < 0); 13396f37eabSKent Overstreet 134853b7393SKent Overstreet free(buf); 135853b7393SKent Overstreet return ret; 136853b7393SKent Overstreet } 137853b7393SKent Overstreet 1381c6fdbd8SKent Overstreet #endif 1391c6fdbd8SKent Overstreet 140dbb9936bSKent Overstreet static struct fsck_err_state *fsck_err_get(struct bch_fs *c, const char *fmt) 1411c6fdbd8SKent Overstreet { 142dbb9936bSKent Overstreet struct fsck_err_state *s; 1431c6fdbd8SKent Overstreet 144d55ddf6eSKent Overstreet if (!test_bit(BCH_FS_fsck_running, &c->flags)) 145dbb9936bSKent Overstreet return NULL; 1461c6fdbd8SKent Overstreet 147f5d26fa3SKent Overstreet list_for_each_entry(s, &c->fsck_error_msgs, list) 148dbb9936bSKent Overstreet if (s->fmt == fmt) { 149dbb9936bSKent Overstreet /* 150dbb9936bSKent Overstreet * move it to the head of the list: repeated fsck errors 151dbb9936bSKent Overstreet * are common 152dbb9936bSKent Overstreet */ 153f5d26fa3SKent Overstreet list_move(&s->list, &c->fsck_error_msgs); 154dbb9936bSKent Overstreet return s; 155dbb9936bSKent Overstreet } 1561c6fdbd8SKent Overstreet 157beb6db68SKent Overstreet s = kzalloc(sizeof(*s), GFP_NOFS); 1581c6fdbd8SKent Overstreet if (!s) { 159f5d26fa3SKent Overstreet if (!c->fsck_alloc_msgs_err) 1601c6fdbd8SKent Overstreet bch_err(c, "kmalloc err, cannot ratelimit fsck errs"); 161f5d26fa3SKent Overstreet c->fsck_alloc_msgs_err = true; 162dbb9936bSKent Overstreet return NULL; 1631c6fdbd8SKent Overstreet } 1641c6fdbd8SKent Overstreet 1651c6fdbd8SKent Overstreet INIT_LIST_HEAD(&s->list); 1661c6fdbd8SKent Overstreet s->fmt = fmt; 167f5d26fa3SKent Overstreet list_add(&s->list, &c->fsck_error_msgs); 168dbb9936bSKent Overstreet return s; 169dbb9936bSKent Overstreet } 170dbb9936bSKent Overstreet 171b65db750SKent Overstreet int bch2_fsck_err(struct bch_fs *c, 172b65db750SKent Overstreet enum bch_fsck_flags flags, 173b65db750SKent Overstreet enum bch_sb_error_id err, 174b65db750SKent Overstreet const char *fmt, ...) 175dbb9936bSKent Overstreet { 176dbb9936bSKent Overstreet struct fsck_err_state *s = NULL; 177dbb9936bSKent Overstreet va_list args; 17822f51621SKent Overstreet bool print = true, suppressing = false, inconsistent = false; 179dbb9936bSKent Overstreet struct printbuf buf = PRINTBUF, *out = &buf; 180dbb9936bSKent Overstreet int ret = -BCH_ERR_fsck_ignore; 181dbb9936bSKent Overstreet 182*a64a3733SKent Overstreet if ((flags & FSCK_CAN_FIX) && 183*a64a3733SKent Overstreet test_bit(err, c->sb.errors_silent)) 1848b16413cSKent Overstreet return -BCH_ERR_fsck_fix; 1858b16413cSKent Overstreet 186b65db750SKent Overstreet bch2_sb_error_count(c, err); 187b65db750SKent Overstreet 1889c5d38bbSKent Overstreet va_start(args, fmt); 1899c5d38bbSKent Overstreet prt_vprintf(out, fmt, args); 1909c5d38bbSKent Overstreet va_end(args); 1919c5d38bbSKent Overstreet 192f5d26fa3SKent Overstreet mutex_lock(&c->fsck_error_msgs_lock); 193dbb9936bSKent Overstreet s = fsck_err_get(c, fmt); 194dbb9936bSKent Overstreet if (s) { 195c8d5b714SKent Overstreet /* 196c8d5b714SKent Overstreet * We may be called multiple times for the same error on 197c8d5b714SKent Overstreet * transaction restart - this memoizes instead of asking the user 198c8d5b714SKent Overstreet * multiple times for the same error: 199c8d5b714SKent Overstreet */ 2009c5d38bbSKent Overstreet if (s->last_msg && !strcmp(buf.buf, s->last_msg)) { 2019c5d38bbSKent Overstreet ret = s->ret; 202f5d26fa3SKent Overstreet mutex_unlock(&c->fsck_error_msgs_lock); 2039c5d38bbSKent Overstreet printbuf_exit(&buf); 2049c5d38bbSKent Overstreet return ret; 2059c5d38bbSKent Overstreet } 2069c5d38bbSKent Overstreet 2079c5d38bbSKent Overstreet kfree(s->last_msg); 2089c5d38bbSKent Overstreet s->last_msg = kstrdup(buf.buf, GFP_KERNEL); 2099c5d38bbSKent Overstreet 210e2ee3eaaSKent Overstreet if (c->opts.ratelimit_errors && 21108061519SKent Overstreet !(flags & FSCK_NO_RATELIMIT) && 212e2ee3eaaSKent Overstreet s->nr >= FSCK_ERR_RATELIMIT_NR) { 213e2ee3eaaSKent Overstreet if (s->nr == FSCK_ERR_RATELIMIT_NR) 214e2ee3eaaSKent Overstreet suppressing = true; 215e2ee3eaaSKent Overstreet else 216e2ee3eaaSKent Overstreet print = false; 217e2ee3eaaSKent Overstreet } 218dbb9936bSKent Overstreet 219dbb9936bSKent Overstreet s->nr++; 220dbb9936bSKent Overstreet } 221dbb9936bSKent Overstreet 222b2d1d56bSKent Overstreet #ifdef BCACHEFS_LOG_PREFIX 223dbb9936bSKent Overstreet if (!strncmp(fmt, "bcachefs:", 9)) 224dbb9936bSKent Overstreet prt_printf(out, bch2_log_msg(c, "")); 225b2d1d56bSKent Overstreet #endif 226dbb9936bSKent Overstreet 227d55ddf6eSKent Overstreet if (!test_bit(BCH_FS_fsck_running, &c->flags)) { 228dbb9936bSKent Overstreet if (c->opts.errors != BCH_ON_ERROR_continue || 229dbb9936bSKent Overstreet !(flags & (FSCK_CAN_FIX|FSCK_CAN_IGNORE))) { 230dbb9936bSKent Overstreet prt_str(out, ", shutting down"); 23122f51621SKent Overstreet inconsistent = true; 232dbb9936bSKent Overstreet ret = -BCH_ERR_fsck_errors_not_fixed; 233dbb9936bSKent Overstreet } else if (flags & FSCK_CAN_FIX) { 234dbb9936bSKent Overstreet prt_str(out, ", fixing"); 235dbb9936bSKent Overstreet ret = -BCH_ERR_fsck_fix; 236dbb9936bSKent Overstreet } else { 237dbb9936bSKent Overstreet prt_str(out, ", continuing"); 238dbb9936bSKent Overstreet ret = -BCH_ERR_fsck_ignore; 239dbb9936bSKent Overstreet } 240a0f8faeaSKent Overstreet } else if (c->opts.fix_errors == FSCK_FIX_exit) { 241dbb9936bSKent Overstreet prt_str(out, ", exiting"); 242dbb9936bSKent Overstreet ret = -BCH_ERR_fsck_errors_not_fixed; 2430bc166ffSKent Overstreet } else if (flags & FSCK_CAN_FIX) { 244853b7393SKent Overstreet int fix = s && s->fix 245853b7393SKent Overstreet ? s->fix 246853b7393SKent Overstreet : c->opts.fix_errors; 247853b7393SKent Overstreet 248a0f8faeaSKent Overstreet if (fix == FSCK_FIX_ask) { 249853b7393SKent Overstreet int ask; 250853b7393SKent Overstreet 251dbb9936bSKent Overstreet prt_str(out, ": fix?"); 25296f37eabSKent Overstreet if (bch2_fs_stdio_redirect(c)) 25396f37eabSKent Overstreet bch2_print(c, "%s", out->buf); 25496f37eabSKent Overstreet else 255dbb9936bSKent Overstreet bch2_print_string_as_lines(KERN_ERR, out->buf); 256dbb9936bSKent Overstreet print = false; 257853b7393SKent Overstreet 25896f37eabSKent Overstreet ask = bch2_fsck_ask_yn(c); 259853b7393SKent Overstreet 260853b7393SKent Overstreet if (ask >= YN_ALLNO && s) 261853b7393SKent Overstreet s->fix = ask == YN_ALLNO 262a0f8faeaSKent Overstreet ? FSCK_FIX_no 263a0f8faeaSKent Overstreet : FSCK_FIX_yes; 264853b7393SKent Overstreet 265853b7393SKent Overstreet ret = ask & 1 266dbb9936bSKent Overstreet ? -BCH_ERR_fsck_fix 267dbb9936bSKent Overstreet : -BCH_ERR_fsck_ignore; 268a0f8faeaSKent Overstreet } else if (fix == FSCK_FIX_yes || 2691c6fdbd8SKent Overstreet (c->opts.nochanges && 2701c6fdbd8SKent Overstreet !(flags & FSCK_CAN_IGNORE))) { 271dbb9936bSKent Overstreet prt_str(out, ", fixing"); 272dbb9936bSKent Overstreet ret = -BCH_ERR_fsck_fix; 2731c6fdbd8SKent Overstreet } else { 274dbb9936bSKent Overstreet prt_str(out, ", not fixing"); 2751c6fdbd8SKent Overstreet } 2761c6fdbd8SKent Overstreet } else if (flags & FSCK_NEED_FSCK) { 277dbb9936bSKent Overstreet prt_str(out, " (run fsck to correct)"); 2781c6fdbd8SKent Overstreet } else { 279dbb9936bSKent Overstreet prt_str(out, " (repair unimplemented)"); 2801c6fdbd8SKent Overstreet } 2811c6fdbd8SKent Overstreet 282dbb9936bSKent Overstreet if (ret == -BCH_ERR_fsck_ignore && 283a0f8faeaSKent Overstreet (c->opts.fix_errors == FSCK_FIX_exit || 284dbb9936bSKent Overstreet !(flags & FSCK_CAN_IGNORE))) 285dbb9936bSKent Overstreet ret = -BCH_ERR_fsck_errors_not_fixed; 286dbb9936bSKent Overstreet 28796f37eabSKent Overstreet if (print) { 28896f37eabSKent Overstreet if (bch2_fs_stdio_redirect(c)) 28996f37eabSKent Overstreet bch2_print(c, "%s\n", out->buf); 29096f37eabSKent Overstreet else 291dbb9936bSKent Overstreet bch2_print_string_as_lines(KERN_ERR, out->buf); 29296f37eabSKent Overstreet } 293dbb9936bSKent Overstreet 294d55ddf6eSKent Overstreet if (test_bit(BCH_FS_fsck_running, &c->flags) && 295dbb9936bSKent Overstreet (ret != -BCH_ERR_fsck_fix && 296dbb9936bSKent Overstreet ret != -BCH_ERR_fsck_ignore)) 297dbb9936bSKent Overstreet bch_err(c, "Unable to continue, halting"); 298dbb9936bSKent Overstreet else if (suppressing) 2991c6fdbd8SKent Overstreet bch_err(c, "Ratelimiting new instances of previous error"); 3001c6fdbd8SKent Overstreet 3019c5d38bbSKent Overstreet if (s) 3029c5d38bbSKent Overstreet s->ret = ret; 3039c5d38bbSKent Overstreet 304f5d26fa3SKent Overstreet mutex_unlock(&c->fsck_error_msgs_lock); 3051c6fdbd8SKent Overstreet 306dbb9936bSKent Overstreet printbuf_exit(&buf); 307dbb9936bSKent Overstreet 30822f51621SKent Overstreet if (inconsistent) 30922f51621SKent Overstreet bch2_inconsistent_error(c); 31022f51621SKent Overstreet 311dbb9936bSKent Overstreet if (ret == -BCH_ERR_fsck_fix) { 3123c471b65SKent Overstreet set_bit(BCH_FS_errors_fixed, &c->flags); 3130bc166ffSKent Overstreet } else { 3143c471b65SKent Overstreet set_bit(BCH_FS_errors_not_fixed, &c->flags); 3153c471b65SKent Overstreet set_bit(BCH_FS_error, &c->flags); 3160bc166ffSKent Overstreet } 317dbb9936bSKent Overstreet 318dbb9936bSKent Overstreet return ret; 3191c6fdbd8SKent Overstreet } 3201c6fdbd8SKent Overstreet 3211c6fdbd8SKent Overstreet void bch2_flush_fsck_errs(struct bch_fs *c) 3221c6fdbd8SKent Overstreet { 3231c6fdbd8SKent Overstreet struct fsck_err_state *s, *n; 3241c6fdbd8SKent Overstreet 325f5d26fa3SKent Overstreet mutex_lock(&c->fsck_error_msgs_lock); 3261c6fdbd8SKent Overstreet 327f5d26fa3SKent Overstreet list_for_each_entry_safe(s, n, &c->fsck_error_msgs, list) { 3289c5d38bbSKent Overstreet if (s->ratelimited && s->last_msg) 3299c5d38bbSKent Overstreet bch_err(c, "Saw %llu errors like:\n %s", s->nr, s->last_msg); 3301c6fdbd8SKent Overstreet 3311c6fdbd8SKent Overstreet list_del(&s->list); 3329c5d38bbSKent Overstreet kfree(s->last_msg); 3331c6fdbd8SKent Overstreet kfree(s); 3341c6fdbd8SKent Overstreet } 3351c6fdbd8SKent Overstreet 336f5d26fa3SKent Overstreet mutex_unlock(&c->fsck_error_msgs_lock); 3371c6fdbd8SKent Overstreet } 338