Merge tag 'net-6.12-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux-block.git] / fs / bcachefs / error.h
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|FSCK_AUTOFIX,\
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 */