256 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2#ifndef _BCACHEFS_ERROR_H3#define _BCACHEFS_ERROR_H4 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 flag16 * superblock as such17 */18 19/* Error messages: */20 21/*22 * Inconsistency errors: The on disk data is inconsistent. If these occur during23 * initial recovery, they don't indicate a bug in the running code - we walk all24 * the metadata before modifying anything. If they occur at runtime, they25 * indicate either a bug in the running code or (less likely) data is being26 * silently corrupted under us.27 *28 * XXX: audit all inconsistent errors and make sure they're all recoverable, in29 * BCH_ON_ERROR_CONTINUE mode30 */31 32bool bch2_inconsistent_error(struct bch_fs *);33 34int bch2_topology_error(struct bch_fs *);35 36#define bch2_fs_topology_error(c, ...) \37({ \38 bch_err(c, "btree topology error: " __VA_ARGS__); \39 bch2_topology_error(c); \40})41 42#define bch2_fs_inconsistent(c, ...) \43({ \44 bch_err(c, __VA_ARGS__); \45 bch2_inconsistent_error(c); \46})47 48#define bch2_fs_inconsistent_on(cond, c, ...) \49({ \50 bool _ret = unlikely(!!(cond)); \51 \52 if (_ret) \53 bch2_fs_inconsistent(c, __VA_ARGS__); \54 _ret; \55})56 57/*58 * Later we might want to mark only the particular device inconsistent, not the59 * entire filesystem:60 */61 62#define bch2_dev_inconsistent(ca, ...) \63do { \64 bch_err(ca, __VA_ARGS__); \65 bch2_inconsistent_error((ca)->fs); \66} while (0)67 68#define bch2_dev_inconsistent_on(cond, ca, ...) \69({ \70 bool _ret = unlikely(!!(cond)); \71 \72 if (_ret) \73 bch2_dev_inconsistent(ca, __VA_ARGS__); \74 _ret; \75})76 77/*78 * When a transaction update discovers or is causing a fs inconsistency, it's79 * helpful to also dump the pending updates:80 */81#define bch2_trans_inconsistent(trans, ...) \82({ \83 bch_err(trans->c, __VA_ARGS__); \84 bch2_dump_trans_updates(trans); \85 bch2_inconsistent_error(trans->c); \86})87 88#define bch2_trans_inconsistent_on(cond, trans, ...) \89({ \90 bool _ret = unlikely(!!(cond)); \91 \92 if (_ret) \93 bch2_trans_inconsistent(trans, __VA_ARGS__); \94 _ret; \95})96 97/*98 * Fsck errors: inconsistency errors we detect at mount time, and should ideally99 * be able to repair:100 */101 102struct fsck_err_state {103 struct list_head list;104 const char *fmt;105 u64 nr;106 bool ratelimited;107 int ret;108 int fix;109 char *last_msg;110};111 112#define fsck_err_count(_c, _err) bch2_sb_err_count(_c, BCH_FSCK_ERR_##_err)113 114__printf(5, 6) __cold115int __bch2_fsck_err(struct bch_fs *, struct btree_trans *,116 enum bch_fsck_flags,117 enum bch_sb_error_id,118 const char *, ...);119#define bch2_fsck_err(c, _flags, _err_type, ...) \120 __bch2_fsck_err(type_is(c, struct bch_fs *) ? (struct bch_fs *) c : NULL,\121 type_is(c, struct btree_trans *) ? (struct btree_trans *) c : NULL,\122 _flags, BCH_FSCK_ERR_##_err_type, __VA_ARGS__)123 124void bch2_flush_fsck_errs(struct bch_fs *);125 126#define __fsck_err(c, _flags, _err_type, ...) \127({ \128 int _ret = bch2_fsck_err(c, _flags, _err_type, __VA_ARGS__); \129 if (_ret != -BCH_ERR_fsck_fix && \130 _ret != -BCH_ERR_fsck_ignore) { \131 ret = _ret; \132 goto fsck_err; \133 } \134 \135 _ret == -BCH_ERR_fsck_fix; \136})137 138/* These macros return true if error should be fixed: */139 140/* XXX: mark in superblock that filesystem contains errors, if we ignore: */141 142#define __fsck_err_on(cond, c, _flags, _err_type, ...) \143({ \144 might_sleep(); \145 \146 if (type_is(c, struct bch_fs *)) \147 WARN_ON(bch2_current_has_btree_trans((struct bch_fs *) c));\148 \149 (unlikely(cond) ? __fsck_err(c, _flags, _err_type, __VA_ARGS__) : false);\150})151 152#define need_fsck_err_on(cond, c, _err_type, ...) \153 __fsck_err_on(cond, c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, _err_type, __VA_ARGS__)154 155#define need_fsck_err(c, _err_type, ...) \156 __fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, _err_type, __VA_ARGS__)157 158#define mustfix_fsck_err(c, _err_type, ...) \159 __fsck_err(c, FSCK_CAN_FIX, _err_type, __VA_ARGS__)160 161#define mustfix_fsck_err_on(cond, c, _err_type, ...) \162 __fsck_err_on(cond, c, FSCK_CAN_FIX, _err_type, __VA_ARGS__)163 164#define fsck_err(c, _err_type, ...) \165 __fsck_err(c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, _err_type, __VA_ARGS__)166 167#define fsck_err_on(cond, c, _err_type, ...) \168 __fsck_err_on(cond, c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, _err_type, __VA_ARGS__)169 170enum bch_validate_flags;171__printf(5, 6)172int __bch2_bkey_fsck_err(struct bch_fs *,173 struct bkey_s_c,174 enum bch_validate_flags,175 enum bch_sb_error_id,176 const char *, ...);177 178/*179 * for now, bkey fsck errors are always handled by deleting the entire key -180 * this will change at some point181 */182#define bkey_fsck_err(c, _err_type, _err_msg, ...) \183do { \184 int _ret = __bch2_bkey_fsck_err(c, k, flags, \185 BCH_FSCK_ERR_##_err_type, \186 _err_msg, ##__VA_ARGS__); \187 if (_ret != -BCH_ERR_fsck_fix && \188 _ret != -BCH_ERR_fsck_ignore) \189 ret = _ret; \190 ret = -BCH_ERR_fsck_delete_bkey; \191 goto fsck_err; \192} while (0)193 194#define bkey_fsck_err_on(cond, ...) \195do { \196 if (unlikely(cond)) \197 bkey_fsck_err(__VA_ARGS__); \198} while (0)199 200/*201 * Fatal errors: these don't indicate a bug, but we can't continue running in RW202 * mode - pretty much just due to metadata IO errors:203 */204 205void bch2_fatal_error(struct bch_fs *);206 207#define bch2_fs_fatal_error(c, _msg, ...) \208do { \209 bch_err(c, "%s(): fatal error " _msg, __func__, ##__VA_ARGS__); \210 bch2_fatal_error(c); \211} while (0)212 213#define bch2_fs_fatal_err_on(cond, c, ...) \214({ \215 bool _ret = unlikely(!!(cond)); \216 \217 if (_ret) \218 bch2_fs_fatal_error(c, __VA_ARGS__); \219 _ret; \220})221 222/*223 * IO errors: either recoverable metadata IO (because we have replicas), or data224 * IO - we need to log it and print out a message, but we don't (necessarily)225 * want to shut down the fs:226 */227 228void bch2_io_error_work(struct work_struct *);229 230/* Does the error handling without logging a message */231void bch2_io_error(struct bch_dev *, enum bch_member_error_type);232 233#define bch2_dev_io_err_on(cond, ca, _type, ...) \234({ \235 bool _ret = (cond); \236 \237 if (_ret) { \238 bch_err_dev_ratelimited(ca, __VA_ARGS__); \239 bch2_io_error(ca, _type); \240 } \241 _ret; \242})243 244#define bch2_dev_inum_io_err_on(cond, ca, _type, ...) \245({ \246 bool _ret = (cond); \247 \248 if (_ret) { \249 bch_err_inum_offset_ratelimited(ca, __VA_ARGS__); \250 bch2_io_error(ca, _type); \251 } \252 _ret; \253})254 255#endif /* _BCACHEFS_ERROR_H */256