Commit | Line | Data |
---|---|---|
0b61f8a4 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 | 2 | /* |
7b718769 NS |
3 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. | |
1da177e4 | 5 | */ |
1da177e4 | 6 | #include "xfs.h" |
5467b34b | 7 | #include "xfs_shared.h" |
a4fbe6ab | 8 | #include "xfs_format.h" |
a844f451 | 9 | #include "xfs_fs.h" |
239880ef DC |
10 | #include "xfs_log_format.h" |
11 | #include "xfs_trans_resv.h" | |
1da177e4 | 12 | #include "xfs_mount.h" |
e9e899a2 | 13 | #include "xfs_errortag.h" |
1da177e4 | 14 | #include "xfs_error.h" |
c6840101 | 15 | #include "xfs_sysfs.h" |
22431bf3 | 16 | #include "xfs_inode.h" |
1da177e4 LT |
17 | |
18 | #ifdef DEBUG | |
19 | ||
31965ef3 DW |
20 | static unsigned int xfs_errortag_random_default[] = { |
21 | XFS_RANDOM_DEFAULT, | |
22 | XFS_RANDOM_IFLUSH_1, | |
23 | XFS_RANDOM_IFLUSH_2, | |
24 | XFS_RANDOM_IFLUSH_3, | |
25 | XFS_RANDOM_IFLUSH_4, | |
26 | XFS_RANDOM_IFLUSH_5, | |
27 | XFS_RANDOM_IFLUSH_6, | |
28 | XFS_RANDOM_DA_READ_BUF, | |
29 | XFS_RANDOM_BTREE_CHECK_LBLOCK, | |
30 | XFS_RANDOM_BTREE_CHECK_SBLOCK, | |
31 | XFS_RANDOM_ALLOC_READ_AGF, | |
32 | XFS_RANDOM_IALLOC_READ_AGI, | |
33 | XFS_RANDOM_ITOBP_INOTOBP, | |
34 | XFS_RANDOM_IUNLINK, | |
35 | XFS_RANDOM_IUNLINK_REMOVE, | |
36 | XFS_RANDOM_DIR_INO_VALIDATE, | |
37 | XFS_RANDOM_BULKSTAT_READ_CHUNK, | |
38 | XFS_RANDOM_IODONE_IOERR, | |
39 | XFS_RANDOM_STRATREAD_IOERR, | |
40 | XFS_RANDOM_STRATCMPL_IOERR, | |
41 | XFS_RANDOM_DIOWRITE_IOERR, | |
42 | XFS_RANDOM_BMAPIFORMAT, | |
43 | XFS_RANDOM_FREE_EXTENT, | |
44 | XFS_RANDOM_RMAP_FINISH_ONE, | |
45 | XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE, | |
46 | XFS_RANDOM_REFCOUNT_FINISH_ONE, | |
47 | XFS_RANDOM_BMAP_FINISH_ONE, | |
48 | XFS_RANDOM_AG_RESV_CRITICAL, | |
6e8af15c | 49 | 0, /* XFS_RANDOM_DROP_WRITES has been removed */ |
3e88a007 | 50 | XFS_RANDOM_LOG_BAD_CRC, |
7f4d01f3 | 51 | XFS_RANDOM_LOG_ITEM_PIN, |
7561d27e | 52 | XFS_RANDOM_BUF_LRU_REF, |
84d42ea6 | 53 | XFS_RANDOM_FORCE_SCRUB_REPAIR, |
f467cad9 | 54 | XFS_RANDOM_FORCE_SUMMARY_RECALC, |
9b247179 | 55 | XFS_RANDOM_IUNLINK_FALLBACK, |
7376d745 | 56 | XFS_RANDOM_BUF_IOERROR, |
f9fa8716 | 57 | XFS_RANDOM_REDUCE_MAX_IEXTENTS, |
30151967 | 58 | XFS_RANDOM_BMAP_ALLOC_MINLEN_EXTENT, |
2b92faed | 59 | XFS_RANDOM_AG_RESV_FAIL, |
abd61ca3 | 60 | XFS_RANDOM_LARP, |
c3b948be | 61 | XFS_RANDOM_DA_LEAF_SPLIT, |
c5218a7c | 62 | XFS_RANDOM_ATTR_LEAF_TO_NODE, |
c2beff99 | 63 | XFS_RANDOM_WB_DELAY_MS, |
254e3459 | 64 | XFS_RANDOM_WRITE_DELAY_MS, |
31965ef3 | 65 | }; |
1da177e4 | 66 | |
c6840101 DW |
67 | struct xfs_errortag_attr { |
68 | struct attribute attr; | |
69 | unsigned int tag; | |
70 | }; | |
71 | ||
72 | static inline struct xfs_errortag_attr * | |
73 | to_attr(struct attribute *attr) | |
74 | { | |
75 | return container_of(attr, struct xfs_errortag_attr, attr); | |
76 | } | |
77 | ||
78 | static inline struct xfs_mount * | |
79 | to_mp(struct kobject *kobject) | |
80 | { | |
81 | struct xfs_kobj *kobj = to_kobj(kobject); | |
82 | ||
83 | return container_of(kobj, struct xfs_mount, m_errortag_kobj); | |
84 | } | |
85 | ||
86 | STATIC ssize_t | |
87 | xfs_errortag_attr_store( | |
88 | struct kobject *kobject, | |
89 | struct attribute *attr, | |
90 | const char *buf, | |
91 | size_t count) | |
92 | { | |
93 | struct xfs_mount *mp = to_mp(kobject); | |
94 | struct xfs_errortag_attr *xfs_attr = to_attr(attr); | |
95 | int ret; | |
96 | unsigned int val; | |
97 | ||
98 | if (strcmp(buf, "default") == 0) { | |
99 | val = xfs_errortag_random_default[xfs_attr->tag]; | |
100 | } else { | |
101 | ret = kstrtouint(buf, 0, &val); | |
102 | if (ret) | |
103 | return ret; | |
104 | } | |
105 | ||
106 | ret = xfs_errortag_set(mp, xfs_attr->tag, val); | |
107 | if (ret) | |
108 | return ret; | |
109 | return count; | |
110 | } | |
111 | ||
112 | STATIC ssize_t | |
113 | xfs_errortag_attr_show( | |
114 | struct kobject *kobject, | |
115 | struct attribute *attr, | |
116 | char *buf) | |
117 | { | |
118 | struct xfs_mount *mp = to_mp(kobject); | |
119 | struct xfs_errortag_attr *xfs_attr = to_attr(attr); | |
120 | ||
121 | return snprintf(buf, PAGE_SIZE, "%u\n", | |
122 | xfs_errortag_get(mp, xfs_attr->tag)); | |
123 | } | |
124 | ||
125 | static const struct sysfs_ops xfs_errortag_sysfs_ops = { | |
126 | .show = xfs_errortag_attr_show, | |
127 | .store = xfs_errortag_attr_store, | |
128 | }; | |
129 | ||
130 | #define XFS_ERRORTAG_ATTR_RW(_name, _tag) \ | |
131 | static struct xfs_errortag_attr xfs_errortag_attr_##_name = { \ | |
132 | .attr = {.name = __stringify(_name), \ | |
133 | .mode = VERIFY_OCTAL_PERMISSIONS(S_IWUSR | S_IRUGO) }, \ | |
134 | .tag = (_tag), \ | |
135 | } | |
136 | ||
137 | #define XFS_ERRORTAG_ATTR_LIST(_name) &xfs_errortag_attr_##_name.attr | |
138 | ||
139 | XFS_ERRORTAG_ATTR_RW(noerror, XFS_ERRTAG_NOERROR); | |
140 | XFS_ERRORTAG_ATTR_RW(iflush1, XFS_ERRTAG_IFLUSH_1); | |
141 | XFS_ERRORTAG_ATTR_RW(iflush2, XFS_ERRTAG_IFLUSH_2); | |
142 | XFS_ERRORTAG_ATTR_RW(iflush3, XFS_ERRTAG_IFLUSH_3); | |
143 | XFS_ERRORTAG_ATTR_RW(iflush4, XFS_ERRTAG_IFLUSH_4); | |
144 | XFS_ERRORTAG_ATTR_RW(iflush5, XFS_ERRTAG_IFLUSH_5); | |
145 | XFS_ERRORTAG_ATTR_RW(iflush6, XFS_ERRTAG_IFLUSH_6); | |
146 | XFS_ERRORTAG_ATTR_RW(dareadbuf, XFS_ERRTAG_DA_READ_BUF); | |
147 | XFS_ERRORTAG_ATTR_RW(btree_chk_lblk, XFS_ERRTAG_BTREE_CHECK_LBLOCK); | |
148 | XFS_ERRORTAG_ATTR_RW(btree_chk_sblk, XFS_ERRTAG_BTREE_CHECK_SBLOCK); | |
149 | XFS_ERRORTAG_ATTR_RW(readagf, XFS_ERRTAG_ALLOC_READ_AGF); | |
150 | XFS_ERRORTAG_ATTR_RW(readagi, XFS_ERRTAG_IALLOC_READ_AGI); | |
151 | XFS_ERRORTAG_ATTR_RW(itobp, XFS_ERRTAG_ITOBP_INOTOBP); | |
152 | XFS_ERRORTAG_ATTR_RW(iunlink, XFS_ERRTAG_IUNLINK); | |
153 | XFS_ERRORTAG_ATTR_RW(iunlinkrm, XFS_ERRTAG_IUNLINK_REMOVE); | |
154 | XFS_ERRORTAG_ATTR_RW(dirinovalid, XFS_ERRTAG_DIR_INO_VALIDATE); | |
155 | XFS_ERRORTAG_ATTR_RW(bulkstat, XFS_ERRTAG_BULKSTAT_READ_CHUNK); | |
156 | XFS_ERRORTAG_ATTR_RW(logiodone, XFS_ERRTAG_IODONE_IOERR); | |
157 | XFS_ERRORTAG_ATTR_RW(stratread, XFS_ERRTAG_STRATREAD_IOERR); | |
158 | XFS_ERRORTAG_ATTR_RW(stratcmpl, XFS_ERRTAG_STRATCMPL_IOERR); | |
159 | XFS_ERRORTAG_ATTR_RW(diowrite, XFS_ERRTAG_DIOWRITE_IOERR); | |
160 | XFS_ERRORTAG_ATTR_RW(bmapifmt, XFS_ERRTAG_BMAPIFORMAT); | |
161 | XFS_ERRORTAG_ATTR_RW(free_extent, XFS_ERRTAG_FREE_EXTENT); | |
162 | XFS_ERRORTAG_ATTR_RW(rmap_finish_one, XFS_ERRTAG_RMAP_FINISH_ONE); | |
163 | XFS_ERRORTAG_ATTR_RW(refcount_continue_update, XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE); | |
164 | XFS_ERRORTAG_ATTR_RW(refcount_finish_one, XFS_ERRTAG_REFCOUNT_FINISH_ONE); | |
165 | XFS_ERRORTAG_ATTR_RW(bmap_finish_one, XFS_ERRTAG_BMAP_FINISH_ONE); | |
166 | XFS_ERRORTAG_ATTR_RW(ag_resv_critical, XFS_ERRTAG_AG_RESV_CRITICAL); | |
3e88a007 | 167 | XFS_ERRORTAG_ATTR_RW(log_bad_crc, XFS_ERRTAG_LOG_BAD_CRC); |
7f4d01f3 | 168 | XFS_ERRORTAG_ATTR_RW(log_item_pin, XFS_ERRTAG_LOG_ITEM_PIN); |
7561d27e | 169 | XFS_ERRORTAG_ATTR_RW(buf_lru_ref, XFS_ERRTAG_BUF_LRU_REF); |
84d42ea6 | 170 | XFS_ERRORTAG_ATTR_RW(force_repair, XFS_ERRTAG_FORCE_SCRUB_REPAIR); |
f467cad9 | 171 | XFS_ERRORTAG_ATTR_RW(bad_summary, XFS_ERRTAG_FORCE_SUMMARY_RECALC); |
9b247179 | 172 | XFS_ERRORTAG_ATTR_RW(iunlink_fallback, XFS_ERRTAG_IUNLINK_FALLBACK); |
7376d745 | 173 | XFS_ERRORTAG_ATTR_RW(buf_ioerror, XFS_ERRTAG_BUF_IOERROR); |
f9fa8716 | 174 | XFS_ERRORTAG_ATTR_RW(reduce_max_iextents, XFS_ERRTAG_REDUCE_MAX_IEXTENTS); |
30151967 | 175 | XFS_ERRORTAG_ATTR_RW(bmap_alloc_minlen_extent, XFS_ERRTAG_BMAP_ALLOC_MINLEN_EXTENT); |
2b92faed | 176 | XFS_ERRORTAG_ATTR_RW(ag_resv_fail, XFS_ERRTAG_AG_RESV_FAIL); |
abd61ca3 | 177 | XFS_ERRORTAG_ATTR_RW(larp, XFS_ERRTAG_LARP); |
c3b948be | 178 | XFS_ERRORTAG_ATTR_RW(da_leaf_split, XFS_ERRTAG_DA_LEAF_SPLIT); |
c5218a7c | 179 | XFS_ERRORTAG_ATTR_RW(attr_leaf_to_node, XFS_ERRTAG_ATTR_LEAF_TO_NODE); |
c2beff99 | 180 | XFS_ERRORTAG_ATTR_RW(wb_delay_ms, XFS_ERRTAG_WB_DELAY_MS); |
254e3459 | 181 | XFS_ERRORTAG_ATTR_RW(write_delay_ms, XFS_ERRTAG_WRITE_DELAY_MS); |
c6840101 DW |
182 | |
183 | static struct attribute *xfs_errortag_attrs[] = { | |
184 | XFS_ERRORTAG_ATTR_LIST(noerror), | |
185 | XFS_ERRORTAG_ATTR_LIST(iflush1), | |
186 | XFS_ERRORTAG_ATTR_LIST(iflush2), | |
187 | XFS_ERRORTAG_ATTR_LIST(iflush3), | |
188 | XFS_ERRORTAG_ATTR_LIST(iflush4), | |
189 | XFS_ERRORTAG_ATTR_LIST(iflush5), | |
190 | XFS_ERRORTAG_ATTR_LIST(iflush6), | |
191 | XFS_ERRORTAG_ATTR_LIST(dareadbuf), | |
192 | XFS_ERRORTAG_ATTR_LIST(btree_chk_lblk), | |
193 | XFS_ERRORTAG_ATTR_LIST(btree_chk_sblk), | |
194 | XFS_ERRORTAG_ATTR_LIST(readagf), | |
195 | XFS_ERRORTAG_ATTR_LIST(readagi), | |
196 | XFS_ERRORTAG_ATTR_LIST(itobp), | |
197 | XFS_ERRORTAG_ATTR_LIST(iunlink), | |
198 | XFS_ERRORTAG_ATTR_LIST(iunlinkrm), | |
199 | XFS_ERRORTAG_ATTR_LIST(dirinovalid), | |
200 | XFS_ERRORTAG_ATTR_LIST(bulkstat), | |
201 | XFS_ERRORTAG_ATTR_LIST(logiodone), | |
202 | XFS_ERRORTAG_ATTR_LIST(stratread), | |
203 | XFS_ERRORTAG_ATTR_LIST(stratcmpl), | |
204 | XFS_ERRORTAG_ATTR_LIST(diowrite), | |
205 | XFS_ERRORTAG_ATTR_LIST(bmapifmt), | |
206 | XFS_ERRORTAG_ATTR_LIST(free_extent), | |
207 | XFS_ERRORTAG_ATTR_LIST(rmap_finish_one), | |
208 | XFS_ERRORTAG_ATTR_LIST(refcount_continue_update), | |
209 | XFS_ERRORTAG_ATTR_LIST(refcount_finish_one), | |
210 | XFS_ERRORTAG_ATTR_LIST(bmap_finish_one), | |
211 | XFS_ERRORTAG_ATTR_LIST(ag_resv_critical), | |
3e88a007 | 212 | XFS_ERRORTAG_ATTR_LIST(log_bad_crc), |
7f4d01f3 | 213 | XFS_ERRORTAG_ATTR_LIST(log_item_pin), |
7561d27e | 214 | XFS_ERRORTAG_ATTR_LIST(buf_lru_ref), |
84d42ea6 | 215 | XFS_ERRORTAG_ATTR_LIST(force_repair), |
f467cad9 | 216 | XFS_ERRORTAG_ATTR_LIST(bad_summary), |
9b247179 | 217 | XFS_ERRORTAG_ATTR_LIST(iunlink_fallback), |
7376d745 | 218 | XFS_ERRORTAG_ATTR_LIST(buf_ioerror), |
f9fa8716 | 219 | XFS_ERRORTAG_ATTR_LIST(reduce_max_iextents), |
30151967 | 220 | XFS_ERRORTAG_ATTR_LIST(bmap_alloc_minlen_extent), |
2b92faed | 221 | XFS_ERRORTAG_ATTR_LIST(ag_resv_fail), |
abd61ca3 | 222 | XFS_ERRORTAG_ATTR_LIST(larp), |
c3b948be | 223 | XFS_ERRORTAG_ATTR_LIST(da_leaf_split), |
c5218a7c | 224 | XFS_ERRORTAG_ATTR_LIST(attr_leaf_to_node), |
c2beff99 | 225 | XFS_ERRORTAG_ATTR_LIST(wb_delay_ms), |
254e3459 | 226 | XFS_ERRORTAG_ATTR_LIST(write_delay_ms), |
c6840101 DW |
227 | NULL, |
228 | }; | |
219aac5d | 229 | ATTRIBUTE_GROUPS(xfs_errortag); |
c6840101 | 230 | |
2ee83335 | 231 | static const struct kobj_type xfs_errortag_ktype = { |
c6840101 DW |
232 | .release = xfs_sysfs_release, |
233 | .sysfs_ops = &xfs_errortag_sysfs_ops, | |
219aac5d | 234 | .default_groups = xfs_errortag_groups, |
c6840101 DW |
235 | }; |
236 | ||
1da177e4 | 237 | int |
31965ef3 DW |
238 | xfs_errortag_init( |
239 | struct xfs_mount *mp) | |
1da177e4 | 240 | { |
cf4f4c12 ZH |
241 | int ret; |
242 | ||
31965ef3 | 243 | mp->m_errortag = kmem_zalloc(sizeof(unsigned int) * XFS_ERRTAG_MAX, |
707e0dda | 244 | KM_MAYFAIL); |
31965ef3 DW |
245 | if (!mp->m_errortag) |
246 | return -ENOMEM; | |
c6840101 | 247 | |
cf4f4c12 ZH |
248 | ret = xfs_sysfs_init(&mp->m_errortag_kobj, &xfs_errortag_ktype, |
249 | &mp->m_kobj, "errortag"); | |
250 | if (ret) | |
251 | kmem_free(mp->m_errortag); | |
252 | return ret; | |
31965ef3 | 253 | } |
1da177e4 | 254 | |
31965ef3 DW |
255 | void |
256 | xfs_errortag_del( | |
257 | struct xfs_mount *mp) | |
258 | { | |
c6840101 | 259 | xfs_sysfs_del(&mp->m_errortag_kobj); |
31965ef3 DW |
260 | kmem_free(mp->m_errortag); |
261 | } | |
1da177e4 | 262 | |
6e8af15c DC |
263 | static bool |
264 | xfs_errortag_valid( | |
265 | unsigned int error_tag) | |
266 | { | |
267 | if (error_tag >= XFS_ERRTAG_MAX) | |
268 | return false; | |
269 | ||
270 | /* Error out removed injection types */ | |
271 | if (error_tag == XFS_ERRTAG_DROP_WRITES) | |
272 | return false; | |
273 | return true; | |
274 | } | |
275 | ||
c2beff99 DW |
276 | bool |
277 | xfs_errortag_enabled( | |
278 | struct xfs_mount *mp, | |
279 | unsigned int tag) | |
280 | { | |
281 | if (!mp->m_errortag) | |
282 | return false; | |
283 | if (!xfs_errortag_valid(tag)) | |
284 | return false; | |
285 | ||
286 | return mp->m_errortag[tag] != 0; | |
287 | } | |
288 | ||
31965ef3 DW |
289 | bool |
290 | xfs_errortag_test( | |
291 | struct xfs_mount *mp, | |
292 | const char *expression, | |
293 | const char *file, | |
294 | int line, | |
295 | unsigned int error_tag) | |
296 | { | |
297 | unsigned int randfactor; | |
1da177e4 | 298 | |
d04c241c CM |
299 | /* |
300 | * To be able to use error injection anywhere, we need to ensure error | |
301 | * injection mechanism is already initialized. | |
302 | * | |
303 | * Code paths like I/O completion can be called before the | |
304 | * initialization is complete, but be able to inject errors in such | |
305 | * places is still useful. | |
306 | */ | |
307 | if (!mp->m_errortag) | |
308 | return false; | |
309 | ||
6e8af15c DC |
310 | if (!xfs_errortag_valid(error_tag)) |
311 | return false; | |
312 | ||
31965ef3 | 313 | randfactor = mp->m_errortag[error_tag]; |
8032bf12 | 314 | if (!randfactor || get_random_u32_below(randfactor)) |
31965ef3 | 315 | return false; |
1da177e4 | 316 | |
31965ef3 DW |
317 | xfs_warn_ratelimited(mp, |
318 | "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"", | |
e1d3d218 | 319 | expression, file, line, mp->m_super->s_id); |
31965ef3 | 320 | return true; |
1da177e4 LT |
321 | } |
322 | ||
c6840101 DW |
323 | int |
324 | xfs_errortag_get( | |
325 | struct xfs_mount *mp, | |
326 | unsigned int error_tag) | |
327 | { | |
6e8af15c | 328 | if (!xfs_errortag_valid(error_tag)) |
c6840101 DW |
329 | return -EINVAL; |
330 | ||
331 | return mp->m_errortag[error_tag]; | |
332 | } | |
333 | ||
1da177e4 | 334 | int |
31965ef3 DW |
335 | xfs_errortag_set( |
336 | struct xfs_mount *mp, | |
337 | unsigned int error_tag, | |
338 | unsigned int tag_value) | |
1da177e4 | 339 | { |
6e8af15c | 340 | if (!xfs_errortag_valid(error_tag)) |
128f24d5 DW |
341 | return -EINVAL; |
342 | ||
31965ef3 DW |
343 | mp->m_errortag[error_tag] = tag_value; |
344 | return 0; | |
1da177e4 LT |
345 | } |
346 | ||
1da177e4 | 347 | int |
31965ef3 DW |
348 | xfs_errortag_add( |
349 | struct xfs_mount *mp, | |
350 | unsigned int error_tag) | |
1da177e4 | 351 | { |
b2c2974b GX |
352 | BUILD_BUG_ON(ARRAY_SIZE(xfs_errortag_random_default) != XFS_ERRTAG_MAX); |
353 | ||
6e8af15c | 354 | if (!xfs_errortag_valid(error_tag)) |
31965ef3 | 355 | return -EINVAL; |
1da177e4 | 356 | |
31965ef3 DW |
357 | return xfs_errortag_set(mp, error_tag, |
358 | xfs_errortag_random_default[error_tag]); | |
359 | } | |
1da177e4 | 360 | |
31965ef3 DW |
361 | int |
362 | xfs_errortag_clearall( | |
363 | struct xfs_mount *mp) | |
364 | { | |
365 | memset(mp->m_errortag, 0, sizeof(unsigned int) * XFS_ERRTAG_MAX); | |
1da177e4 LT |
366 | return 0; |
367 | } | |
1550d0b0 | 368 | #endif /* DEBUG */ |
1da177e4 | 369 | |
1da177e4 LT |
370 | void |
371 | xfs_error_report( | |
a0e856b0 AE |
372 | const char *tag, |
373 | int level, | |
374 | struct xfs_mount *mp, | |
375 | const char *filename, | |
376 | int linenum, | |
d9418ed0 | 377 | xfs_failaddr_t failaddr) |
1da177e4 LT |
378 | { |
379 | if (level <= xfs_error_level) { | |
6a19d939 | 380 | xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, |
65dd297a | 381 | "Internal error %s at line %d of file %s. Caller %pS", |
d9418ed0 | 382 | tag, linenum, filename, failaddr); |
1da177e4 LT |
383 | |
384 | xfs_stack_trace(); | |
385 | } | |
386 | } | |
387 | ||
1da177e4 LT |
388 | void |
389 | xfs_corruption_error( | |
a0e856b0 AE |
390 | const char *tag, |
391 | int level, | |
392 | struct xfs_mount *mp, | |
d243b89a | 393 | const void *buf, |
2551a530 | 394 | size_t bufsize, |
a0e856b0 AE |
395 | const char *filename, |
396 | int linenum, | |
d9418ed0 | 397 | xfs_failaddr_t failaddr) |
1da177e4 | 398 | { |
6519f708 | 399 | if (buf && level <= xfs_error_level) |
2551a530 | 400 | xfs_hex_dump(buf, bufsize); |
d9418ed0 | 401 | xfs_error_report(tag, level, mp, filename, linenum, failaddr); |
65333b4c | 402 | xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair"); |
1da177e4 | 403 | } |
ca23f8fd | 404 | |
a5155b87 DW |
405 | /* |
406 | * Complain about the kinds of metadata corruption that we can't detect from a | |
407 | * verifier, such as incorrect inter-block relationship data. Does not set | |
408 | * bp->b_error. | |
8d57c216 DW |
409 | * |
410 | * Call xfs_buf_mark_corrupt, not this function. | |
a5155b87 DW |
411 | */ |
412 | void | |
413 | xfs_buf_corruption_error( | |
e83cf875 DW |
414 | struct xfs_buf *bp, |
415 | xfs_failaddr_t fa) | |
a5155b87 DW |
416 | { |
417 | struct xfs_mount *mp = bp->b_mount; | |
418 | ||
419 | xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR, | |
420 | "Metadata corruption detected at %pS, %s block 0x%llx", | |
9343ee76 | 421 | fa, bp->b_ops->name, xfs_buf_daddr(bp)); |
a5155b87 DW |
422 | |
423 | xfs_alert(mp, "Unmount and run xfs_repair"); | |
424 | ||
425 | if (xfs_error_level >= XFS_ERRLEVEL_HIGH) | |
426 | xfs_stack_trace(); | |
427 | } | |
428 | ||
ca23f8fd ES |
429 | /* |
430 | * Warnings specifically for verifier errors. Differentiate CRC vs. invalid | |
431 | * values, and omit the stack trace unless the error level is tuned high. | |
432 | */ | |
433 | void | |
6edb1810 | 434 | xfs_buf_verifier_error( |
31ca03c9 | 435 | struct xfs_buf *bp, |
bc1a09b8 | 436 | int error, |
6edb1810 | 437 | const char *name, |
d243b89a | 438 | const void *buf, |
6edb1810 | 439 | size_t bufsz, |
bc1a09b8 | 440 | xfs_failaddr_t failaddr) |
ca23f8fd | 441 | { |
dbd329f1 | 442 | struct xfs_mount *mp = bp->b_mount; |
bc1a09b8 | 443 | xfs_failaddr_t fa; |
6edb1810 | 444 | int sz; |
ca23f8fd | 445 | |
bc1a09b8 DW |
446 | fa = failaddr ? failaddr : __return_address; |
447 | __xfs_buf_ioerror(bp, error, fa); | |
31ca03c9 | 448 | |
d519da41 MB |
449 | xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR, |
450 | "Metadata %s detected at %pS, %s block 0x%llx %s", | |
2451337d | 451 | bp->b_error == -EFSBADCRC ? "CRC error" : "corruption", |
9343ee76 | 452 | fa, bp->b_ops->name, xfs_buf_daddr(bp), name); |
ca23f8fd ES |
453 | |
454 | xfs_alert(mp, "Unmount and run xfs_repair"); | |
455 | ||
456 | if (xfs_error_level >= XFS_ERRLEVEL_LOW) { | |
6edb1810 | 457 | sz = min_t(size_t, XFS_CORRUPTION_DUMP_LEN, bufsz); |
9c712a13 | 458 | xfs_alert(mp, "First %d bytes of corrupted metadata buffer:", |
6edb1810 DW |
459 | sz); |
460 | xfs_hex_dump(buf, sz); | |
ca23f8fd ES |
461 | } |
462 | ||
463 | if (xfs_error_level >= XFS_ERRLEVEL_HIGH) | |
464 | xfs_stack_trace(); | |
465 | } | |
22431bf3 | 466 | |
6edb1810 DW |
467 | /* |
468 | * Warnings specifically for verifier errors. Differentiate CRC vs. invalid | |
469 | * values, and omit the stack trace unless the error level is tuned high. | |
470 | */ | |
471 | void | |
472 | xfs_verifier_error( | |
473 | struct xfs_buf *bp, | |
474 | int error, | |
475 | xfs_failaddr_t failaddr) | |
476 | { | |
477 | return xfs_buf_verifier_error(bp, error, "", xfs_buf_offset(bp, 0), | |
478 | XFS_CORRUPTION_DUMP_LEN, failaddr); | |
479 | } | |
480 | ||
22431bf3 DW |
481 | /* |
482 | * Warnings for inode corruption problems. Don't bother with the stack | |
483 | * trace unless the error level is turned up high. | |
484 | */ | |
485 | void | |
486 | xfs_inode_verifier_error( | |
487 | struct xfs_inode *ip, | |
488 | int error, | |
489 | const char *name, | |
d243b89a | 490 | const void *buf, |
22431bf3 DW |
491 | size_t bufsz, |
492 | xfs_failaddr_t failaddr) | |
493 | { | |
494 | struct xfs_mount *mp = ip->i_mount; | |
495 | xfs_failaddr_t fa; | |
496 | int sz; | |
497 | ||
498 | fa = failaddr ? failaddr : __return_address; | |
499 | ||
500 | xfs_alert(mp, "Metadata %s detected at %pS, inode 0x%llx %s", | |
501 | error == -EFSBADCRC ? "CRC error" : "corruption", | |
502 | fa, ip->i_ino, name); | |
503 | ||
504 | xfs_alert(mp, "Unmount and run xfs_repair"); | |
505 | ||
506 | if (buf && xfs_error_level >= XFS_ERRLEVEL_LOW) { | |
507 | sz = min_t(size_t, XFS_CORRUPTION_DUMP_LEN, bufsz); | |
508 | xfs_alert(mp, "First %d bytes of corrupted metadata buffer:", | |
509 | sz); | |
510 | xfs_hex_dump(buf, sz); | |
511 | } | |
512 | ||
513 | if (xfs_error_level >= XFS_ERRLEVEL_HIGH) | |
514 | xfs_stack_trace(); | |
515 | } |