xref: /linux/fs/bcachefs/error.h (revision 2622f290417001b0440f4a48dc6978f5f1e12a56)
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, ...)				\
49 ({									\
50 	bool _ret = unlikely(!!(cond));					\
51 	if (_ret)							\
52 		bch2_fs_inconsistent(__VA_ARGS__);			\
53 	_ret;								\
54 })
55 
56 /*
57  * When a transaction update discovers or is causing a fs inconsistency, it's
58  * helpful to also dump the pending updates:
59  */
60 #define bch2_trans_inconsistent(trans, ...)				\
61 ({									\
62 	bch_err(trans->c, __VA_ARGS__);					\
63 	bch2_dump_trans_updates(trans);					\
64 	bch2_inconsistent_error(trans->c);				\
65 })
66 
67 #define bch2_trans_inconsistent_on(cond, trans, ...)			\
68 ({									\
69 	bool _ret = unlikely(!!(cond));					\
70 									\
71 	if (_ret)							\
72 		bch2_trans_inconsistent(trans, __VA_ARGS__);		\
73 	_ret;								\
74 })
75 
76 /*
77  * Fsck errors: inconsistency errors we detect at mount time, and should ideally
78  * be able to repair:
79  */
80 
81 struct fsck_err_state {
82 	struct list_head	list;
83 	const char		*fmt;
84 	u64			nr;
85 	bool			ratelimited;
86 	int			ret;
87 	int			fix;
88 	char			*last_msg;
89 };
90 
91 #define fsck_err_count(_c, _err)	bch2_sb_err_count(_c, BCH_FSCK_ERR_##_err)
92 
93 __printf(5, 6) __cold
94 int __bch2_fsck_err(struct bch_fs *, struct btree_trans *,
95 		  enum bch_fsck_flags,
96 		  enum bch_sb_error_id,
97 		  const char *, ...);
98 #define bch2_fsck_err(c, _flags, _err_type, ...)				\
99 	__bch2_fsck_err(type_is(c, struct bch_fs *) ? (struct bch_fs *) c : NULL,\
100 			type_is(c, struct btree_trans *) ? (struct btree_trans *) c : NULL,\
101 			_flags, BCH_FSCK_ERR_##_err_type, __VA_ARGS__)
102 
103 void bch2_flush_fsck_errs(struct bch_fs *);
104 
105 #define fsck_err_wrap(_do)						\
106 ({									\
107 	int _ret = _do;							\
108 	if (_ret != -BCH_ERR_fsck_fix &&				\
109 	    _ret != -BCH_ERR_fsck_ignore) {				\
110 		ret = _ret;						\
111 		goto fsck_err;						\
112 	}								\
113 									\
114 	_ret == -BCH_ERR_fsck_fix;					\
115 })
116 
117 #define __fsck_err(...)		fsck_err_wrap(bch2_fsck_err(__VA_ARGS__))
118 
119 /* These macros return true if error should be fixed: */
120 
121 /* XXX: mark in superblock that filesystem contains errors, if we ignore: */
122 
123 #define __fsck_err_on(cond, c, _flags, _err_type, ...)			\
124 ({									\
125 	might_sleep();							\
126 									\
127 	if (type_is(c, struct bch_fs *))				\
128 		WARN_ON(bch2_current_has_btree_trans((struct bch_fs *) c));\
129 									\
130 	(unlikely(cond) ? __fsck_err(c, _flags, _err_type, __VA_ARGS__) : false);\
131 })
132 
133 #define mustfix_fsck_err(c, _err_type, ...)				\
134 	__fsck_err(c, FSCK_CAN_FIX, _err_type, __VA_ARGS__)
135 
136 #define mustfix_fsck_err_on(cond, c, _err_type, ...)			\
137 	__fsck_err_on(cond, c, FSCK_CAN_FIX, _err_type, __VA_ARGS__)
138 
139 #define fsck_err(c, _err_type, ...)					\
140 	__fsck_err(c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, _err_type, __VA_ARGS__)
141 
142 #define fsck_err_on(cond, c, _err_type, ...)				\
143 	__fsck_err_on(cond, c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, _err_type, __VA_ARGS__)
144 
145 #define log_fsck_err(c, _err_type, ...)					\
146 	__fsck_err(c, FSCK_CAN_IGNORE, _err_type, __VA_ARGS__)
147 
148 #define log_fsck_err_on(cond, ...)					\
149 ({									\
150 	bool _ret = unlikely(!!(cond));					\
151 	if (_ret)							\
152 		log_fsck_err(__VA_ARGS__);				\
153 	_ret;								\
154 })
155 
156 enum bch_validate_flags;
157 __printf(5, 6)
158 int __bch2_bkey_fsck_err(struct bch_fs *,
159 			 struct bkey_s_c,
160 			 struct bkey_validate_context from,
161 			 enum bch_sb_error_id,
162 			 const char *, ...);
163 
164 /*
165  * for now, bkey fsck errors are always handled by deleting the entire key -
166  * this will change at some point
167  */
168 #define bkey_fsck_err(c, _err_type, _err_msg, ...)			\
169 do {									\
170 	int _ret = __bch2_bkey_fsck_err(c, k, from,			\
171 				BCH_FSCK_ERR_##_err_type,		\
172 				_err_msg, ##__VA_ARGS__);		\
173 	if (_ret != -BCH_ERR_fsck_fix &&				\
174 	    _ret != -BCH_ERR_fsck_ignore)				\
175 		ret = _ret;						\
176 	ret = -BCH_ERR_fsck_delete_bkey;				\
177 	goto fsck_err;							\
178 } while (0)
179 
180 #define bkey_fsck_err_on(cond, ...)					\
181 do {									\
182 	if (unlikely(cond))						\
183 		bkey_fsck_err(__VA_ARGS__);				\
184 } while (0)
185 
186 /*
187  * Fatal errors: these don't indicate a bug, but we can't continue running in RW
188  * mode - pretty much just due to metadata IO errors:
189  */
190 
191 void bch2_fatal_error(struct bch_fs *);
192 
193 #define bch2_fs_fatal_error(c, _msg, ...)				\
194 do {									\
195 	bch_err(c, "%s(): fatal error " _msg, __func__, ##__VA_ARGS__);	\
196 	bch2_fatal_error(c);						\
197 } while (0)
198 
199 #define bch2_fs_fatal_err_on(cond, c, ...)				\
200 ({									\
201 	bool _ret = unlikely(!!(cond));					\
202 									\
203 	if (_ret)							\
204 		bch2_fs_fatal_error(c, __VA_ARGS__);			\
205 	_ret;								\
206 })
207 
208 /*
209  * IO errors: either recoverable metadata IO (because we have replicas), or data
210  * IO - we need to log it and print out a message, but we don't (necessarily)
211  * want to shut down the fs:
212  */
213 
214 void bch2_io_error_work(struct work_struct *);
215 
216 /* Does the error handling without logging a message */
217 void bch2_io_error(struct bch_dev *, enum bch_member_error_type);
218 
219 #define bch2_dev_io_err_on(cond, ca, _type, ...)			\
220 ({									\
221 	bool _ret = (cond);						\
222 									\
223 	if (_ret) {							\
224 		bch_err_dev_ratelimited(ca, __VA_ARGS__);		\
225 		bch2_io_error(ca, _type);				\
226 	}								\
227 	_ret;								\
228 })
229 
230 #define bch2_dev_inum_io_err_on(cond, ca, _type, ...)			\
231 ({									\
232 	bool _ret = (cond);						\
233 									\
234 	if (_ret) {							\
235 		bch_err_inum_offset_ratelimited(ca, __VA_ARGS__);	\
236 		bch2_io_error(ca, _type);				\
237 	}								\
238 	_ret;								\
239 })
240 
241 int bch2_inum_err_msg_trans(struct btree_trans *, struct printbuf *, subvol_inum);
242 int bch2_inum_offset_err_msg_trans(struct btree_trans *, struct printbuf *, subvol_inum, u64);
243 
244 void bch2_inum_err_msg(struct bch_fs *, struct printbuf *, subvol_inum);
245 void bch2_inum_offset_err_msg(struct bch_fs *, struct printbuf *, subvol_inum, u64);
246 
247 #endif /* _BCACHEFS_ERROR_H */
248