xref: /linux/fs/bcachefs/error.h (revision 0808ebf2f80b962e75741a41ced372a7116f1e26)
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 /*
22  * Inconsistency errors: The on disk data is inconsistent. If these occur during
23  * initial recovery, they don't indicate a bug in the running code - we walk all
24  * the metadata before modifying anything. If they occur at runtime, they
25  * indicate either a bug in the running code or (less likely) data is being
26  * silently corrupted under us.
27  *
28  * XXX: audit all inconsistent errors and make sure they're all recoverable, in
29  * BCH_ON_ERROR_CONTINUE mode
30  */
31 
32 bool bch2_inconsistent_error(struct bch_fs *);
33 
34 int 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 the
59  * entire filesystem:
60  */
61 
62 #define bch2_dev_inconsistent(ca, ...)					\
63 do {									\
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's
79  * 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 ideally
99  * be able to repair:
100  */
101 
102 struct 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) __cold
115 int __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 
124 void 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 
170 __printf(5, 6)
171 int __bch2_bkey_fsck_err(struct bch_fs *,
172 			 struct bkey_s_c,
173 			 enum bch_fsck_flags,
174 			 enum bch_sb_error_id,
175 			 const char *, ...);
176 
177 /*
178  * for now, bkey fsck errors are always handled by deleting the entire key -
179  * this will change at some point
180  */
181 #define bkey_fsck_err(c, _err_type, _err_msg, ...)			\
182 do {									\
183 	if ((flags & BCH_VALIDATE_silent)) {				\
184 		ret = -BCH_ERR_fsck_delete_bkey;			\
185 		goto fsck_err;						\
186 	}								\
187 	int _ret = __bch2_bkey_fsck_err(c, k, FSCK_CAN_FIX,		\
188 				BCH_FSCK_ERR_##_err_type,		\
189 				_err_msg, ##__VA_ARGS__);		\
190 	if (_ret != -BCH_ERR_fsck_fix &&				\
191 	    _ret != -BCH_ERR_fsck_ignore)				\
192 		ret = _ret;						\
193 	ret = -BCH_ERR_fsck_delete_bkey;				\
194 	goto fsck_err;							\
195 } while (0)
196 
197 #define bkey_fsck_err_on(cond, ...)					\
198 do {									\
199 	if (unlikely(cond))						\
200 		bkey_fsck_err(__VA_ARGS__);				\
201 } while (0)
202 
203 /*
204  * Fatal errors: these don't indicate a bug, but we can't continue running in RW
205  * mode - pretty much just due to metadata IO errors:
206  */
207 
208 void bch2_fatal_error(struct bch_fs *);
209 
210 #define bch2_fs_fatal_error(c, _msg, ...)				\
211 do {									\
212 	bch_err(c, "%s(): fatal error " _msg, __func__, ##__VA_ARGS__);	\
213 	bch2_fatal_error(c);						\
214 } while (0)
215 
216 #define bch2_fs_fatal_err_on(cond, c, ...)				\
217 ({									\
218 	bool _ret = unlikely(!!(cond));					\
219 									\
220 	if (_ret)							\
221 		bch2_fs_fatal_error(c, __VA_ARGS__);			\
222 	_ret;								\
223 })
224 
225 /*
226  * IO errors: either recoverable metadata IO (because we have replicas), or data
227  * IO - we need to log it and print out a message, but we don't (necessarily)
228  * want to shut down the fs:
229  */
230 
231 void bch2_io_error_work(struct work_struct *);
232 
233 /* Does the error handling without logging a message */
234 void bch2_io_error(struct bch_dev *, enum bch_member_error_type);
235 
236 #define bch2_dev_io_err_on(cond, ca, _type, ...)			\
237 ({									\
238 	bool _ret = (cond);						\
239 									\
240 	if (_ret) {							\
241 		bch_err_dev_ratelimited(ca, __VA_ARGS__);		\
242 		bch2_io_error(ca, _type);				\
243 	}								\
244 	_ret;								\
245 })
246 
247 #define bch2_dev_inum_io_err_on(cond, ca, _type, ...)			\
248 ({									\
249 	bool _ret = (cond);						\
250 									\
251 	if (_ret) {							\
252 		bch_err_inum_offset_ratelimited(ca, __VA_ARGS__);	\
253 		bch2_io_error(ca, _type);				\
254 	}								\
255 	_ret;								\
256 })
257 
258 #endif /* _BCACHEFS_ERROR_H */
259