xref: /linux/fs/bcachefs/error.h (revision 59fff63cc2b75dcfe08f9eeb4b2187d73e53843d)
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 
8 struct bch_dev;
9 struct bch_fs;
10 struct work_struct;
11 
12 /*
13  * XXX: separate out errors that indicate on disk data is inconsistent, and flag
14  * superblock as such
15  */
16 
17 /* Error messages: */
18 
19 /*
20  * Inconsistency errors: The on disk data is inconsistent. If these occur during
21  * initial recovery, they don't indicate a bug in the running code - we walk all
22  * the metadata before modifying anything. If they occur at runtime, they
23  * indicate either a bug in the running code or (less likely) data is being
24  * silently corrupted under us.
25  *
26  * XXX: audit all inconsistent errors and make sure they're all recoverable, in
27  * BCH_ON_ERROR_CONTINUE mode
28  */
29 
30 bool bch2_inconsistent_error(struct bch_fs *);
31 
32 void bch2_topology_error(struct bch_fs *);
33 
34 #define bch2_fs_inconsistent(c, ...)					\
35 ({									\
36 	bch_err(c, __VA_ARGS__);					\
37 	bch2_inconsistent_error(c);					\
38 })
39 
40 #define bch2_fs_inconsistent_on(cond, c, ...)				\
41 ({									\
42 	bool _ret = unlikely(!!(cond));					\
43 									\
44 	if (_ret)							\
45 		bch2_fs_inconsistent(c, __VA_ARGS__);			\
46 	_ret;								\
47 })
48 
49 /*
50  * Later we might want to mark only the particular device inconsistent, not the
51  * entire filesystem:
52  */
53 
54 #define bch2_dev_inconsistent(ca, ...)					\
55 do {									\
56 	bch_err(ca, __VA_ARGS__);					\
57 	bch2_inconsistent_error((ca)->fs);				\
58 } while (0)
59 
60 #define bch2_dev_inconsistent_on(cond, ca, ...)				\
61 ({									\
62 	bool _ret = unlikely(!!(cond));					\
63 									\
64 	if (_ret)							\
65 		bch2_dev_inconsistent(ca, __VA_ARGS__);			\
66 	_ret;								\
67 })
68 
69 /*
70  * When a transaction update discovers or is causing a fs inconsistency, it's
71  * helpful to also dump the pending updates:
72  */
73 #define bch2_trans_inconsistent(trans, ...)				\
74 ({									\
75 	bch_err(trans->c, __VA_ARGS__);					\
76 	bch2_dump_trans_updates(trans);					\
77 	bch2_inconsistent_error(trans->c);				\
78 })
79 
80 #define bch2_trans_inconsistent_on(cond, trans, ...)			\
81 ({									\
82 	bool _ret = unlikely(!!(cond));					\
83 									\
84 	if (_ret)							\
85 		bch2_trans_inconsistent(trans, __VA_ARGS__);		\
86 	_ret;								\
87 })
88 
89 /*
90  * Fsck errors: inconsistency errors we detect at mount time, and should ideally
91  * be able to repair:
92  */
93 
94 struct fsck_err_state {
95 	struct list_head	list;
96 	const char		*fmt;
97 	u64			nr;
98 	bool			ratelimited;
99 	int			ret;
100 	int			fix;
101 	char			*last_msg;
102 };
103 
104 #define FSCK_CAN_FIX		(1 << 0)
105 #define FSCK_CAN_IGNORE		(1 << 1)
106 #define FSCK_NEED_FSCK		(1 << 2)
107 #define FSCK_NO_RATELIMIT	(1 << 3)
108 
109 __printf(3, 4) __cold
110 int bch2_fsck_err(struct bch_fs *, unsigned, const char *, ...);
111 void bch2_flush_fsck_errs(struct bch_fs *);
112 
113 #define __fsck_err(c, _flags, msg, ...)					\
114 ({									\
115 	int _ret = bch2_fsck_err(c, _flags, msg, ##__VA_ARGS__);	\
116 									\
117 	if (_ret != -BCH_ERR_fsck_fix &&				\
118 	    _ret != -BCH_ERR_fsck_ignore) {				\
119 		ret = _ret;						\
120 		goto fsck_err;						\
121 	}								\
122 									\
123 	_ret == -BCH_ERR_fsck_fix;					\
124 })
125 
126 /* These macros return true if error should be fixed: */
127 
128 /* XXX: mark in superblock that filesystem contains errors, if we ignore: */
129 
130 #define __fsck_err_on(cond, c, _flags, ...)				\
131 	(unlikely(cond) ? __fsck_err(c, _flags,	##__VA_ARGS__) : false)
132 
133 #define need_fsck_err_on(cond, c, ...)					\
134 	__fsck_err_on(cond, c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, ##__VA_ARGS__)
135 
136 #define need_fsck_err(c, ...)						\
137 	__fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, ##__VA_ARGS__)
138 
139 #define mustfix_fsck_err(c, ...)					\
140 	__fsck_err(c, FSCK_CAN_FIX, ##__VA_ARGS__)
141 
142 #define mustfix_fsck_err_on(cond, c, ...)				\
143 	__fsck_err_on(cond, c, FSCK_CAN_FIX, ##__VA_ARGS__)
144 
145 #define fsck_err(c, ...)						\
146 	__fsck_err(c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, ##__VA_ARGS__)
147 
148 #define fsck_err_on(cond, c, ...)					\
149 	__fsck_err_on(cond, c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, ##__VA_ARGS__)
150 
151 /*
152  * Fatal errors: these don't indicate a bug, but we can't continue running in RW
153  * mode - pretty much just due to metadata IO errors:
154  */
155 
156 void bch2_fatal_error(struct bch_fs *);
157 
158 #define bch2_fs_fatal_error(c, ...)					\
159 do {									\
160 	bch_err(c, __VA_ARGS__);					\
161 	bch2_fatal_error(c);						\
162 } while (0)
163 
164 #define bch2_fs_fatal_err_on(cond, c, ...)				\
165 ({									\
166 	bool _ret = unlikely(!!(cond));					\
167 									\
168 	if (_ret)							\
169 		bch2_fs_fatal_error(c, __VA_ARGS__);			\
170 	_ret;								\
171 })
172 
173 /*
174  * IO errors: either recoverable metadata IO (because we have replicas), or data
175  * IO - we need to log it and print out a message, but we don't (necessarily)
176  * want to shut down the fs:
177  */
178 
179 void bch2_io_error_work(struct work_struct *);
180 
181 /* Does the error handling without logging a message */
182 void bch2_io_error(struct bch_dev *);
183 
184 #define bch2_dev_io_err_on(cond, ca, ...)				\
185 ({									\
186 	bool _ret = (cond);						\
187 									\
188 	if (_ret) {							\
189 		bch_err_dev_ratelimited(ca, __VA_ARGS__);		\
190 		bch2_io_error(ca);					\
191 	}								\
192 	_ret;								\
193 })
194 
195 #define bch2_dev_inum_io_err_on(cond, ca, ...)				\
196 ({									\
197 	bool _ret = (cond);						\
198 									\
199 	if (_ret) {							\
200 		bch_err_inum_offset_ratelimited(ca, __VA_ARGS__);	\
201 		bch2_io_error(ca);					\
202 	}								\
203 	_ret;								\
204 })
205 
206 #endif /* _BCACHEFS_ERROR_H */
207