xfs: refactor inode verifier corruption error printing
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 23 Jan 2018 02:09:48 +0000 (18:09 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 29 Jan 2018 15:27:22 +0000 (07:27 -0800)
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>
fs/xfs/libxfs/xfs_inode_buf.c
fs/xfs/xfs_error.c
fs/xfs/xfs_error.h
fs/xfs/xfs_inode.c

index 4035b5d5f6fd1de98b29ff49fbf825f8c560d2ec..d7e7e58f0ee24868b509b14ba25bbc0d878bd859 100644 (file)
@@ -578,10 +578,8 @@ xfs_iread(
        /* even unallocated inodes are verified */
        fa = xfs_dinode_verify(mp, ip->i_ino, dip);
        if (fa) {
-               xfs_alert(mp, "%s: validation failed for inode %lld at %pS",
-                               __func__, ip->i_ino, fa);
-
-               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, dip);
+               xfs_inode_verifier_error(ip, -EFSCORRUPTED, "dinode", dip,
+                               sizeof(*dip), fa);
                error = -EFSCORRUPTED;
                goto out_brelse;
        }
index 980d5f0660b58f8a95585aa9047928397da5cb81..ccf520f0b00dc62782e220adbeb738fc6f5c27c5 100644 (file)
@@ -24,6 +24,7 @@
 #include "xfs_errortag.h"
 #include "xfs_error.h"
 #include "xfs_sysfs.h"
+#include "xfs_inode.h"
 
 #ifdef DEBUG
 
@@ -372,3 +373,39 @@ xfs_verifier_error(
        if (xfs_error_level >= XFS_ERRLEVEL_HIGH)
                xfs_stack_trace();
 }
+
+/*
+ * Warnings for inode corruption problems.  Don't bother with the stack
+ * trace unless the error level is turned up high.
+ */
+void
+xfs_inode_verifier_error(
+       struct xfs_inode        *ip,
+       int                     error,
+       const char              *name,
+       void                    *buf,
+       size_t                  bufsz,
+       xfs_failaddr_t          failaddr)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       xfs_failaddr_t          fa;
+       int                     sz;
+
+       fa = failaddr ? failaddr : __return_address;
+
+       xfs_alert(mp, "Metadata %s detected at %pS, inode 0x%llx %s",
+                 error == -EFSBADCRC ? "CRC error" : "corruption",
+                 fa, ip->i_ino, name);
+
+       xfs_alert(mp, "Unmount and run xfs_repair");
+
+       if (buf && xfs_error_level >= XFS_ERRLEVEL_LOW) {
+               sz = min_t(size_t, XFS_CORRUPTION_DUMP_LEN, bufsz);
+               xfs_alert(mp, "First %d bytes of corrupted metadata buffer:",
+                               sz);
+               xfs_hex_dump(buf, sz);
+       }
+
+       if (xfs_error_level >= XFS_ERRLEVEL_HIGH)
+               xfs_stack_trace();
+}
index a3ba05bd983db5fbbc54dd5935a564cef3a92956..7e728c5a46b896634c4578414e2aaba8a0f4a23c 100644 (file)
@@ -28,6 +28,9 @@ extern void xfs_corruption_error(const char *tag, int level,
                        int linenum, xfs_failaddr_t failaddr);
 extern void xfs_verifier_error(struct xfs_buf *bp, int error,
                        xfs_failaddr_t failaddr);
+extern void xfs_inode_verifier_error(struct xfs_inode *ip, int error,
+                       const char *name, void *buf, size_t bufsz,
+                       xfs_failaddr_t failaddr);
 
 #define        XFS_ERROR_REPORT(e, lvl, mp)    \
        xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)
index 4ea6476bcbd785b12e1233632c871e2231482192..5366fb619db6da4df7e97369d04e4d82d1fa2b22 100644 (file)
@@ -3486,21 +3486,23 @@ bool
 xfs_inode_verify_forks(
        struct xfs_inode        *ip)
 {
+       struct xfs_ifork        *ifp;
        xfs_failaddr_t          fa;
 
        fa = xfs_ifork_verify_data(ip, &xfs_default_ifork_ops);
        if (fa) {
-               xfs_alert(ip->i_mount,
-                               "%s: bad inode %llu inline data fork at %pS",
-                               __func__, ip->i_ino, fa);
+               ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
+               xfs_inode_verifier_error(ip, -EFSCORRUPTED, "data fork",
+                               ifp->if_u1.if_data, ifp->if_bytes, fa);
                return false;
        }
 
        fa = xfs_ifork_verify_attr(ip, &xfs_default_ifork_ops);
        if (fa) {
-               xfs_alert(ip->i_mount,
-                               "%s: bad inode %llu inline attr fork at %pS",
-                               __func__, ip->i_ino, fa);
+               ifp = XFS_IFORK_PTR(ip, XFS_ATTR_FORK);
+               xfs_inode_verifier_error(ip, -EFSCORRUPTED, "attr fork",
+                               ifp ? ifp->if_u1.if_data : NULL,
+                               ifp ? ifp->if_bytes : 0, fa);
                return false;
        }
        return true;