at v6.15 251 lines 7.2 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _BCACHEFS_ERROR_H 3#define _BCACHEFS_ERROR_H 4 5#include <linux/list.h> 6#include <linux/printk.h> 7#include "bkey_types.h" 8#include "sb-errors.h" 9 10struct bch_dev; 11struct bch_fs; 12struct work_struct; 13 14/* 15 * XXX: separate out errors that indicate on disk data is inconsistent, and flag 16 * superblock as such 17 */ 18 19/* Error messages: */ 20 21void bch2_log_msg_start(struct bch_fs *, struct printbuf *); 22 23/* 24 * Inconsistency errors: The on disk data is inconsistent. If these occur during 25 * initial recovery, they don't indicate a bug in the running code - we walk all 26 * the metadata before modifying anything. If they occur at runtime, they 27 * indicate either a bug in the running code or (less likely) data is being 28 * silently corrupted under us. 29 * 30 * XXX: audit all inconsistent errors and make sure they're all recoverable, in 31 * BCH_ON_ERROR_CONTINUE mode 32 */ 33 34bool __bch2_inconsistent_error(struct bch_fs *, struct printbuf *); 35bool bch2_inconsistent_error(struct bch_fs *); 36__printf(2, 3) 37bool bch2_fs_inconsistent(struct bch_fs *, const char *, ...); 38 39#define bch2_fs_inconsistent_on(cond, ...) \ 40({ \ 41 bool _ret = unlikely(!!(cond)); \ 42 if (_ret) \ 43 bch2_fs_inconsistent(__VA_ARGS__); \ 44 _ret; \ 45}) 46 47__printf(2, 3) 48bool bch2_trans_inconsistent(struct btree_trans *, const char *, ...); 49 50#define bch2_trans_inconsistent_on(cond, ...) \ 51({ \ 52 bool _ret = unlikely(!!(cond)); \ 53 if (_ret) \ 54 bch2_trans_inconsistent(__VA_ARGS__); \ 55 _ret; \ 56}) 57 58int __bch2_topology_error(struct bch_fs *, struct printbuf *); 59__printf(2, 3) 60int bch2_fs_topology_error(struct bch_fs *, const char *, ...); 61 62/* 63 * Fsck errors: inconsistency errors we detect at mount time, and should ideally 64 * be able to repair: 65 */ 66 67struct fsck_err_state { 68 struct list_head list; 69 enum bch_sb_error_id id; 70 u64 nr; 71 bool ratelimited; 72 int ret; 73 int fix; 74 char *last_msg; 75}; 76 77#define fsck_err_count(_c, _err) bch2_sb_err_count(_c, BCH_FSCK_ERR_##_err) 78 79void __bch2_count_fsck_err(struct bch_fs *, 80 enum bch_sb_error_id, const char *, 81 bool *, bool *, bool *); 82#define bch2_count_fsck_err(_c, _err, ...) \ 83 __bch2_count_fsck_err(_c, BCH_FSCK_ERR_##_err, __VA_ARGS__) 84 85__printf(5, 6) __cold 86int __bch2_fsck_err(struct bch_fs *, struct btree_trans *, 87 enum bch_fsck_flags, 88 enum bch_sb_error_id, 89 const char *, ...); 90#define bch2_fsck_err(c, _flags, _err_type, ...) \ 91 __bch2_fsck_err(type_is(c, struct bch_fs *) ? (struct bch_fs *) c : NULL,\ 92 type_is(c, struct btree_trans *) ? (struct btree_trans *) c : NULL,\ 93 _flags, BCH_FSCK_ERR_##_err_type, __VA_ARGS__) 94 95void bch2_flush_fsck_errs(struct bch_fs *); 96void bch2_free_fsck_errs(struct bch_fs *); 97 98#define fsck_err_wrap(_do) \ 99({ \ 100 int _ret = _do; \ 101 if (_ret != -BCH_ERR_fsck_fix && \ 102 _ret != -BCH_ERR_fsck_ignore) { \ 103 ret = _ret; \ 104 goto fsck_err; \ 105 } \ 106 \ 107 _ret == -BCH_ERR_fsck_fix; \ 108}) 109 110#define __fsck_err(...) fsck_err_wrap(bch2_fsck_err(__VA_ARGS__)) 111 112/* These macros return true if error should be fixed: */ 113 114/* XXX: mark in superblock that filesystem contains errors, if we ignore: */ 115 116#define __fsck_err_on(cond, c, _flags, _err_type, ...) \ 117({ \ 118 might_sleep(); \ 119 \ 120 if (type_is(c, struct bch_fs *)) \ 121 WARN_ON(bch2_current_has_btree_trans((struct bch_fs *) c));\ 122 \ 123 (unlikely(cond) ? __fsck_err(c, _flags, _err_type, __VA_ARGS__) : false);\ 124}) 125 126#define mustfix_fsck_err(c, _err_type, ...) \ 127 __fsck_err(c, FSCK_CAN_FIX, _err_type, __VA_ARGS__) 128 129#define mustfix_fsck_err_on(cond, c, _err_type, ...) \ 130 __fsck_err_on(cond, c, FSCK_CAN_FIX, _err_type, __VA_ARGS__) 131 132#define fsck_err(c, _err_type, ...) \ 133 __fsck_err(c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, _err_type, __VA_ARGS__) 134 135#define fsck_err_on(cond, c, _err_type, ...) \ 136 __fsck_err_on(cond, c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, _err_type, __VA_ARGS__) 137 138#define log_fsck_err(c, _err_type, ...) \ 139 __fsck_err(c, FSCK_CAN_IGNORE, _err_type, __VA_ARGS__) 140 141#define log_fsck_err_on(cond, ...) \ 142({ \ 143 bool _ret = unlikely(!!(cond)); \ 144 if (_ret) \ 145 log_fsck_err(__VA_ARGS__); \ 146 _ret; \ 147}) 148 149enum bch_validate_flags; 150__printf(5, 6) 151int __bch2_bkey_fsck_err(struct bch_fs *, 152 struct bkey_s_c, 153 struct bkey_validate_context from, 154 enum bch_sb_error_id, 155 const char *, ...); 156 157/* 158 * for now, bkey fsck errors are always handled by deleting the entire key - 159 * this will change at some point 160 */ 161#define bkey_fsck_err(c, _err_type, _err_msg, ...) \ 162do { \ 163 int _ret = __bch2_bkey_fsck_err(c, k, from, \ 164 BCH_FSCK_ERR_##_err_type, \ 165 _err_msg, ##__VA_ARGS__); \ 166 if (_ret != -BCH_ERR_fsck_fix && \ 167 _ret != -BCH_ERR_fsck_ignore) \ 168 ret = _ret; \ 169 ret = -BCH_ERR_fsck_delete_bkey; \ 170 goto fsck_err; \ 171} while (0) 172 173#define bkey_fsck_err_on(cond, ...) \ 174do { \ 175 if (unlikely(cond)) \ 176 bkey_fsck_err(__VA_ARGS__); \ 177} while (0) 178 179/* 180 * Fatal errors: these don't indicate a bug, but we can't continue running in RW 181 * mode - pretty much just due to metadata IO errors: 182 */ 183 184void bch2_fatal_error(struct bch_fs *); 185 186#define bch2_fs_fatal_error(c, _msg, ...) \ 187do { \ 188 bch_err(c, "%s(): fatal error " _msg, __func__, ##__VA_ARGS__); \ 189 bch2_fatal_error(c); \ 190} while (0) 191 192#define bch2_fs_fatal_err_on(cond, c, ...) \ 193({ \ 194 bool _ret = unlikely(!!(cond)); \ 195 \ 196 if (_ret) \ 197 bch2_fs_fatal_error(c, __VA_ARGS__); \ 198 _ret; \ 199}) 200 201/* 202 * IO errors: either recoverable metadata IO (because we have replicas), or data 203 * IO - we need to log it and print out a message, but we don't (necessarily) 204 * want to shut down the fs: 205 */ 206 207void bch2_io_error_work(struct work_struct *); 208 209/* Does the error handling without logging a message */ 210void bch2_io_error(struct bch_dev *, enum bch_member_error_type); 211 212#ifndef CONFIG_BCACHEFS_NO_LATENCY_ACCT 213void bch2_latency_acct(struct bch_dev *, u64, int); 214#else 215static inline void bch2_latency_acct(struct bch_dev *ca, u64 submit_time, int rw) {} 216#endif 217 218static inline void bch2_account_io_success_fail(struct bch_dev *ca, 219 enum bch_member_error_type type, 220 bool success) 221{ 222 if (likely(success)) { 223 if (type == BCH_MEMBER_ERROR_write && 224 ca->write_errors_start) 225 ca->write_errors_start = 0; 226 } else { 227 bch2_io_error(ca, type); 228 } 229} 230 231static inline void bch2_account_io_completion(struct bch_dev *ca, 232 enum bch_member_error_type type, 233 u64 submit_time, bool success) 234{ 235 if (unlikely(!ca)) 236 return; 237 238 if (type != BCH_MEMBER_ERROR_checksum) 239 bch2_latency_acct(ca, submit_time, type); 240 241 bch2_account_io_success_fail(ca, type, success); 242} 243 244int bch2_inum_offset_err_msg_trans(struct btree_trans *, struct printbuf *, subvol_inum, u64); 245 246void bch2_inum_offset_err_msg(struct bch_fs *, struct printbuf *, subvol_inum, u64); 247 248int bch2_inum_snap_offset_err_msg_trans(struct btree_trans *, struct printbuf *, struct bpos); 249void bch2_inum_snap_offset_err_msg(struct bch_fs *, struct printbuf *, struct bpos); 250 251#endif /* _BCACHEFS_ERROR_H */