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