xref: /linux/fs/bcachefs/error.h (revision 8f602276d3902642fdc3429b548d73c745446601)
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 enum bch_validate_flags;
171 __printf(5, 6)
172 int __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 point
181  */
182 #define bkey_fsck_err(c, _err_type, _err_msg, ...)			\
183 do {									\
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, ...)					\
195 do {									\
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 RW
202  * mode - pretty much just due to metadata IO errors:
203  */
204 
205 void bch2_fatal_error(struct bch_fs *);
206 
207 #define bch2_fs_fatal_error(c, _msg, ...)				\
208 do {									\
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 data
224  * 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 
228 void bch2_io_error_work(struct work_struct *);
229 
230 /* Does the error handling without logging a message */
231 void 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