1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. |
5 | */ |
6 | #include "xfs.h" |
7 | #include "xfs_shared.h" |
8 | #include "xfs_format.h" |
9 | #include "xfs_fs.h" |
10 | #include "xfs_log_format.h" |
11 | #include "xfs_trans_resv.h" |
12 | #include "xfs_mount.h" |
13 | #include "xfs_errortag.h" |
14 | #include "xfs_error.h" |
15 | #include "xfs_sysfs.h" |
16 | #include "xfs_inode.h" |
17 | |
18 | #ifdef DEBUG |
19 | |
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, |
49 | 0, /* XFS_RANDOM_DROP_WRITES has been removed */ |
50 | XFS_RANDOM_LOG_BAD_CRC, |
51 | XFS_RANDOM_LOG_ITEM_PIN, |
52 | XFS_RANDOM_BUF_LRU_REF, |
53 | XFS_RANDOM_FORCE_SCRUB_REPAIR, |
54 | XFS_RANDOM_FORCE_SUMMARY_RECALC, |
55 | XFS_RANDOM_IUNLINK_FALLBACK, |
56 | XFS_RANDOM_BUF_IOERROR, |
57 | XFS_RANDOM_REDUCE_MAX_IEXTENTS, |
58 | XFS_RANDOM_BMAP_ALLOC_MINLEN_EXTENT, |
59 | XFS_RANDOM_AG_RESV_FAIL, |
60 | XFS_RANDOM_LARP, |
61 | XFS_RANDOM_DA_LEAF_SPLIT, |
62 | XFS_RANDOM_ATTR_LEAF_TO_NODE, |
63 | XFS_RANDOM_WB_DELAY_MS, |
64 | XFS_RANDOM_WRITE_DELAY_MS, |
65 | }; |
66 | |
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(s: buf, base: 0, res: &val); |
102 | if (ret) |
103 | return ret; |
104 | } |
105 | |
106 | ret = xfs_errortag_set(mp, error_tag: xfs_attr->tag, tag_value: 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, fmt: "%u\n" , |
122 | xfs_errortag_get(mp, error_tag: 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); |
167 | XFS_ERRORTAG_ATTR_RW(log_bad_crc, XFS_ERRTAG_LOG_BAD_CRC); |
168 | XFS_ERRORTAG_ATTR_RW(log_item_pin, XFS_ERRTAG_LOG_ITEM_PIN); |
169 | XFS_ERRORTAG_ATTR_RW(buf_lru_ref, XFS_ERRTAG_BUF_LRU_REF); |
170 | XFS_ERRORTAG_ATTR_RW(force_repair, XFS_ERRTAG_FORCE_SCRUB_REPAIR); |
171 | XFS_ERRORTAG_ATTR_RW(bad_summary, XFS_ERRTAG_FORCE_SUMMARY_RECALC); |
172 | XFS_ERRORTAG_ATTR_RW(iunlink_fallback, XFS_ERRTAG_IUNLINK_FALLBACK); |
173 | XFS_ERRORTAG_ATTR_RW(buf_ioerror, XFS_ERRTAG_BUF_IOERROR); |
174 | XFS_ERRORTAG_ATTR_RW(reduce_max_iextents, XFS_ERRTAG_REDUCE_MAX_IEXTENTS); |
175 | XFS_ERRORTAG_ATTR_RW(bmap_alloc_minlen_extent, XFS_ERRTAG_BMAP_ALLOC_MINLEN_EXTENT); |
176 | XFS_ERRORTAG_ATTR_RW(ag_resv_fail, XFS_ERRTAG_AG_RESV_FAIL); |
177 | XFS_ERRORTAG_ATTR_RW(larp, XFS_ERRTAG_LARP); |
178 | XFS_ERRORTAG_ATTR_RW(da_leaf_split, XFS_ERRTAG_DA_LEAF_SPLIT); |
179 | XFS_ERRORTAG_ATTR_RW(attr_leaf_to_node, XFS_ERRTAG_ATTR_LEAF_TO_NODE); |
180 | XFS_ERRORTAG_ATTR_RW(wb_delay_ms, XFS_ERRTAG_WB_DELAY_MS); |
181 | XFS_ERRORTAG_ATTR_RW(write_delay_ms, XFS_ERRTAG_WRITE_DELAY_MS); |
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), |
212 | XFS_ERRORTAG_ATTR_LIST(log_bad_crc), |
213 | XFS_ERRORTAG_ATTR_LIST(log_item_pin), |
214 | XFS_ERRORTAG_ATTR_LIST(buf_lru_ref), |
215 | XFS_ERRORTAG_ATTR_LIST(force_repair), |
216 | XFS_ERRORTAG_ATTR_LIST(bad_summary), |
217 | XFS_ERRORTAG_ATTR_LIST(iunlink_fallback), |
218 | XFS_ERRORTAG_ATTR_LIST(buf_ioerror), |
219 | XFS_ERRORTAG_ATTR_LIST(reduce_max_iextents), |
220 | XFS_ERRORTAG_ATTR_LIST(bmap_alloc_minlen_extent), |
221 | XFS_ERRORTAG_ATTR_LIST(ag_resv_fail), |
222 | XFS_ERRORTAG_ATTR_LIST(larp), |
223 | XFS_ERRORTAG_ATTR_LIST(da_leaf_split), |
224 | XFS_ERRORTAG_ATTR_LIST(attr_leaf_to_node), |
225 | XFS_ERRORTAG_ATTR_LIST(wb_delay_ms), |
226 | XFS_ERRORTAG_ATTR_LIST(write_delay_ms), |
227 | NULL, |
228 | }; |
229 | ATTRIBUTE_GROUPS(xfs_errortag); |
230 | |
231 | static const struct kobj_type xfs_errortag_ktype = { |
232 | .release = xfs_sysfs_release, |
233 | .sysfs_ops = &xfs_errortag_sysfs_ops, |
234 | .default_groups = xfs_errortag_groups, |
235 | }; |
236 | |
237 | int |
238 | xfs_errortag_init( |
239 | struct xfs_mount *mp) |
240 | { |
241 | int ret; |
242 | |
243 | mp->m_errortag = kmem_zalloc(sizeof(unsigned int) * XFS_ERRTAG_MAX, |
244 | KM_MAYFAIL); |
245 | if (!mp->m_errortag) |
246 | return -ENOMEM; |
247 | |
248 | ret = xfs_sysfs_init(kobj: &mp->m_errortag_kobj, ktype: &xfs_errortag_ktype, |
249 | parent_kobj: &mp->m_kobj, name: "errortag" ); |
250 | if (ret) |
251 | kmem_free(ptr: mp->m_errortag); |
252 | return ret; |
253 | } |
254 | |
255 | void |
256 | xfs_errortag_del( |
257 | struct xfs_mount *mp) |
258 | { |
259 | xfs_sysfs_del(kobj: &mp->m_errortag_kobj); |
260 | kmem_free(ptr: mp->m_errortag); |
261 | } |
262 | |
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 | |
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(error_tag: tag)) |
284 | return false; |
285 | |
286 | return mp->m_errortag[tag] != 0; |
287 | } |
288 | |
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; |
298 | |
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 | |
310 | if (!xfs_errortag_valid(error_tag)) |
311 | return false; |
312 | |
313 | randfactor = mp->m_errortag[error_tag]; |
314 | if (!randfactor || get_random_u32_below(ceil: randfactor)) |
315 | return false; |
316 | |
317 | xfs_warn_ratelimited(mp, |
318 | "Injecting error (%s) at file %s, line %d, on filesystem \"%s\"" , |
319 | expression, file, line, mp->m_super->s_id); |
320 | return true; |
321 | } |
322 | |
323 | int |
324 | xfs_errortag_get( |
325 | struct xfs_mount *mp, |
326 | unsigned int error_tag) |
327 | { |
328 | if (!xfs_errortag_valid(error_tag)) |
329 | return -EINVAL; |
330 | |
331 | return mp->m_errortag[error_tag]; |
332 | } |
333 | |
334 | int |
335 | xfs_errortag_set( |
336 | struct xfs_mount *mp, |
337 | unsigned int error_tag, |
338 | unsigned int tag_value) |
339 | { |
340 | if (!xfs_errortag_valid(error_tag)) |
341 | return -EINVAL; |
342 | |
343 | mp->m_errortag[error_tag] = tag_value; |
344 | return 0; |
345 | } |
346 | |
347 | int |
348 | xfs_errortag_add( |
349 | struct xfs_mount *mp, |
350 | unsigned int error_tag) |
351 | { |
352 | BUILD_BUG_ON(ARRAY_SIZE(xfs_errortag_random_default) != XFS_ERRTAG_MAX); |
353 | |
354 | if (!xfs_errortag_valid(error_tag)) |
355 | return -EINVAL; |
356 | |
357 | return xfs_errortag_set(mp, error_tag, |
358 | tag_value: xfs_errortag_random_default[error_tag]); |
359 | } |
360 | |
361 | int |
362 | xfs_errortag_clearall( |
363 | struct xfs_mount *mp) |
364 | { |
365 | memset(mp->m_errortag, 0, sizeof(unsigned int) * XFS_ERRTAG_MAX); |
366 | return 0; |
367 | } |
368 | #endif /* DEBUG */ |
369 | |
370 | void |
371 | xfs_error_report( |
372 | const char *tag, |
373 | int level, |
374 | struct xfs_mount *mp, |
375 | const char *filename, |
376 | int linenum, |
377 | xfs_failaddr_t failaddr) |
378 | { |
379 | if (level <= xfs_error_level) { |
380 | xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT, |
381 | "Internal error %s at line %d of file %s. Caller %pS" , |
382 | tag, linenum, filename, failaddr); |
383 | |
384 | xfs_stack_trace(); |
385 | } |
386 | } |
387 | |
388 | void |
389 | xfs_corruption_error( |
390 | const char *tag, |
391 | int level, |
392 | struct xfs_mount *mp, |
393 | const void *buf, |
394 | size_t bufsize, |
395 | const char *filename, |
396 | int linenum, |
397 | xfs_failaddr_t failaddr) |
398 | { |
399 | if (buf && level <= xfs_error_level) |
400 | xfs_hex_dump(p: buf, length: bufsize); |
401 | xfs_error_report(tag, level, mp, filename, linenum, failaddr: failaddr); |
402 | xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair" ); |
403 | } |
404 | |
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. |
409 | * |
410 | * Call xfs_buf_mark_corrupt, not this function. |
411 | */ |
412 | void |
413 | xfs_buf_corruption_error( |
414 | struct xfs_buf *bp, |
415 | xfs_failaddr_t fa) |
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" , |
421 | fa, bp->b_ops->name, xfs_buf_daddr(bp)); |
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 | |
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 |
434 | xfs_buf_verifier_error( |
435 | struct xfs_buf *bp, |
436 | int error, |
437 | const char *name, |
438 | const void *buf, |
439 | size_t bufsz, |
440 | xfs_failaddr_t failaddr) |
441 | { |
442 | struct xfs_mount *mp = bp->b_mount; |
443 | xfs_failaddr_t fa; |
444 | int sz; |
445 | |
446 | fa = failaddr ? failaddr : __return_address; |
447 | __xfs_buf_ioerror(bp, error, fa); |
448 | |
449 | xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR, |
450 | "Metadata %s detected at %pS, %s block 0x%llx %s" , |
451 | bp->b_error == -EFSBADCRC ? "CRC error" : "corruption" , |
452 | fa, bp->b_ops->name, xfs_buf_daddr(bp), name); |
453 | |
454 | xfs_alert(mp, "Unmount and run xfs_repair" ); |
455 | |
456 | if (xfs_error_level >= XFS_ERRLEVEL_LOW) { |
457 | sz = min_t(size_t, XFS_CORRUPTION_DUMP_LEN, bufsz); |
458 | xfs_alert(mp, "First %d bytes of corrupted metadata buffer:" , |
459 | sz); |
460 | xfs_hex_dump(p: buf, length: sz); |
461 | } |
462 | |
463 | if (xfs_error_level >= XFS_ERRLEVEL_HIGH) |
464 | xfs_stack_trace(); |
465 | } |
466 | |
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, name: "" , buf: xfs_buf_offset(bp, 0), |
478 | XFS_CORRUPTION_DUMP_LEN, failaddr: failaddr); |
479 | } |
480 | |
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, |
490 | const void *buf, |
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(p: buf, length: sz); |
511 | } |
512 | |
513 | if (xfs_error_level >= XFS_ERRLEVEL_HIGH) |
514 | xfs_stack_trace(); |
515 | } |
516 | |