diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2018-01-22 21:09:48 -0500 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2018-01-29 10:27:22 -0500 |
commit | 22431bf3dfbf44d7356933776eb486a6a01dea6f (patch) | |
tree | 5d4aecebcd8cdb86a29e317d2ddeadaff9ed4e85 | |
parent | 67a3f6d01495bbf520186aa3ecd013ba02b81462 (diff) |
xfs: refactor inode verifier corruption error printing
Refactor inode verifier error reporting into a non-libxfs function so
that we aren't encoding the message format in libxfs. This also
changes the kernel dmesg output to resemble buffer verifier errors
more closely.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_buf.c | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_error.c | 37 | ||||
-rw-r--r-- | fs/xfs/xfs_error.h | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 14 |
4 files changed, 50 insertions, 10 deletions
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 4035b5d5f6fd..d7e7e58f0ee2 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c | |||
@@ -578,10 +578,8 @@ xfs_iread( | |||
578 | /* even unallocated inodes are verified */ | 578 | /* even unallocated inodes are verified */ |
579 | fa = xfs_dinode_verify(mp, ip->i_ino, dip); | 579 | fa = xfs_dinode_verify(mp, ip->i_ino, dip); |
580 | if (fa) { | 580 | if (fa) { |
581 | xfs_alert(mp, "%s: validation failed for inode %lld at %pS", | 581 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, "dinode", dip, |
582 | __func__, ip->i_ino, fa); | 582 | sizeof(*dip), fa); |
583 | |||
584 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, dip); | ||
585 | error = -EFSCORRUPTED; | 583 | error = -EFSCORRUPTED; |
586 | goto out_brelse; | 584 | goto out_brelse; |
587 | } | 585 | } |
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 980d5f0660b5..ccf520f0b00d 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "xfs_errortag.h" | 24 | #include "xfs_errortag.h" |
25 | #include "xfs_error.h" | 25 | #include "xfs_error.h" |
26 | #include "xfs_sysfs.h" | 26 | #include "xfs_sysfs.h" |
27 | #include "xfs_inode.h" | ||
27 | 28 | ||
28 | #ifdef DEBUG | 29 | #ifdef DEBUG |
29 | 30 | ||
@@ -372,3 +373,39 @@ xfs_verifier_error( | |||
372 | if (xfs_error_level >= XFS_ERRLEVEL_HIGH) | 373 | if (xfs_error_level >= XFS_ERRLEVEL_HIGH) |
373 | xfs_stack_trace(); | 374 | xfs_stack_trace(); |
374 | } | 375 | } |
376 | |||
377 | /* | ||
378 | * Warnings for inode corruption problems. Don't bother with the stack | ||
379 | * trace unless the error level is turned up high. | ||
380 | */ | ||
381 | void | ||
382 | xfs_inode_verifier_error( | ||
383 | struct xfs_inode *ip, | ||
384 | int error, | ||
385 | const char *name, | ||
386 | void *buf, | ||
387 | size_t bufsz, | ||
388 | xfs_failaddr_t failaddr) | ||
389 | { | ||
390 | struct xfs_mount *mp = ip->i_mount; | ||
391 | xfs_failaddr_t fa; | ||
392 | int sz; | ||
393 | |||
394 | fa = failaddr ? failaddr : __return_address; | ||
395 | |||
396 | xfs_alert(mp, "Metadata %s detected at %pS, inode 0x%llx %s", | ||
397 | error == -EFSBADCRC ? "CRC error" : "corruption", | ||
398 | fa, ip->i_ino, name); | ||
399 | |||
400 | xfs_alert(mp, "Unmount and run xfs_repair"); | ||
401 | |||
402 | if (buf && xfs_error_level >= XFS_ERRLEVEL_LOW) { | ||
403 | sz = min_t(size_t, XFS_CORRUPTION_DUMP_LEN, bufsz); | ||
404 | xfs_alert(mp, "First %d bytes of corrupted metadata buffer:", | ||
405 | sz); | ||
406 | xfs_hex_dump(buf, sz); | ||
407 | } | ||
408 | |||
409 | if (xfs_error_level >= XFS_ERRLEVEL_HIGH) | ||
410 | xfs_stack_trace(); | ||
411 | } | ||
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index a3ba05bd983d..7e728c5a46b8 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h | |||
@@ -28,6 +28,9 @@ extern void xfs_corruption_error(const char *tag, int level, | |||
28 | int linenum, xfs_failaddr_t failaddr); | 28 | int linenum, xfs_failaddr_t failaddr); |
29 | extern void xfs_verifier_error(struct xfs_buf *bp, int error, | 29 | extern void xfs_verifier_error(struct xfs_buf *bp, int error, |
30 | xfs_failaddr_t failaddr); | 30 | xfs_failaddr_t failaddr); |
31 | extern void xfs_inode_verifier_error(struct xfs_inode *ip, int error, | ||
32 | const char *name, void *buf, size_t bufsz, | ||
33 | xfs_failaddr_t failaddr); | ||
31 | 34 | ||
32 | #define XFS_ERROR_REPORT(e, lvl, mp) \ | 35 | #define XFS_ERROR_REPORT(e, lvl, mp) \ |
33 | xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address) | 36 | xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address) |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 4ea6476bcbd7..5366fb619db6 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -3486,21 +3486,23 @@ bool | |||
3486 | xfs_inode_verify_forks( | 3486 | xfs_inode_verify_forks( |
3487 | struct xfs_inode *ip) | 3487 | struct xfs_inode *ip) |
3488 | { | 3488 | { |
3489 | struct xfs_ifork *ifp; | ||
3489 | xfs_failaddr_t fa; | 3490 | xfs_failaddr_t fa; |
3490 | 3491 | ||
3491 | fa = xfs_ifork_verify_data(ip, &xfs_default_ifork_ops); | 3492 | fa = xfs_ifork_verify_data(ip, &xfs_default_ifork_ops); |
3492 | if (fa) { | 3493 | if (fa) { |
3493 | xfs_alert(ip->i_mount, | 3494 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); |
3494 | "%s: bad inode %llu inline data fork at %pS", | 3495 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, "data fork", |
3495 | __func__, ip->i_ino, fa); | 3496 | ifp->if_u1.if_data, ifp->if_bytes, fa); |
3496 | return false; | 3497 | return false; |
3497 | } | 3498 | } |
3498 | 3499 | ||
3499 | fa = xfs_ifork_verify_attr(ip, &xfs_default_ifork_ops); | 3500 | fa = xfs_ifork_verify_attr(ip, &xfs_default_ifork_ops); |
3500 | if (fa) { | 3501 | if (fa) { |
3501 | xfs_alert(ip->i_mount, | 3502 | ifp = XFS_IFORK_PTR(ip, XFS_ATTR_FORK); |
3502 | "%s: bad inode %llu inline attr fork at %pS", | 3503 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, "attr fork", |
3503 | __func__, ip->i_ino, fa); | 3504 | ifp ? ifp->if_u1.if_data : NULL, |
3505 | ifp ? ifp->if_bytes : 0, fa); | ||
3504 | return false; | 3506 | return false; |
3505 | } | 3507 | } |
3506 | return true; | 3508 | return true; |