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 10 struct bch_dev; 11 struct bch_fs; 12 struct 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 21 void 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 34 bool __bch2_inconsistent_error(struct bch_fs *, struct printbuf *); 35 bool bch2_inconsistent_error(struct bch_fs *); 36 __printf(2, 3) 37 bool 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) 48 bool 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 58 int __bch2_topology_error(struct bch_fs *, struct printbuf *); 59 __printf(2, 3) 60 int 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 67 struct 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 79 void __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 86 int __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 95 void bch2_flush_fsck_errs(struct bch_fs *); 96 void 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 149 enum bch_validate_flags; 150 __printf(5, 6) 151 int __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, ...) \ 162 do { \ 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, ...) \ 174 do { \ 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 184 void bch2_fatal_error(struct bch_fs *); 185 186 #define bch2_fs_fatal_error(c, _msg, ...) \ 187 do { \ 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 207 void bch2_io_error_work(struct work_struct *); 208 209 /* Does the error handling without logging a message */ 210 void bch2_io_error(struct bch_dev *, enum bch_member_error_type); 211 212 #ifndef CONFIG_BCACHEFS_NO_LATENCY_ACCT 213 void bch2_latency_acct(struct bch_dev *, u64, int); 214 #else 215 static inline void bch2_latency_acct(struct bch_dev *ca, u64 submit_time, int rw) {} 216 #endif 217 218 static 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 231 static 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 244 int bch2_inum_offset_err_msg_trans(struct btree_trans *, struct printbuf *, subvol_inum, u64); 245 246 void bch2_inum_offset_err_msg(struct bch_fs *, struct printbuf *, subvol_inum, u64); 247 248 int bch2_inum_snap_offset_err_msg_trans(struct btree_trans *, struct printbuf *, struct bpos); 249 void bch2_inum_snap_offset_err_msg(struct bch_fs *, struct printbuf *, struct bpos); 250 251 #endif /* _BCACHEFS_ERROR_H */ 252