aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-02-26 22:43:19 -0600
committerEric Sandeen <sandeen@redhat.com>2018-02-26 22:43:19 -0600
commit1d3bac1f3b6b4aa8b4de1ed6a95b0440b1bcd953 (patch)
tree160670996cba555bbf1c47f66dc1b66f1060f318
parent885ba5ce1dd446a82f2ecf1f03ad834d253b05d7 (diff)
downloadxfsprogs-dev-1d3bac1f3b6b4aa8b4de1ed6a95b0440b1bcd953.tar.gz
xfs: refactor inode verifier corruption error printing
Source kernel commit: 22431bf3dfbf44d7356933776eb486a6a01dea6f 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> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--libxfs/libxfs_priv.h6
-rw-r--r--libxfs/rdwr.c14
-rw-r--r--libxfs/util.c19
-rw-r--r--libxfs/xfs_inode_buf.c6
4 files changed, 34 insertions, 11 deletions
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index 82627668fb..d35676e9c7 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h
@@ -527,7 +527,11 @@ int libxfs_mod_incore_sb(struct xfs_mount *, int, int64_t, int);
#define xfs_reinit_percpu_counters(mp)
void xfs_trans_mod_sb(struct xfs_trans *, uint, long);
-void xfs_verifier_error(struct xfs_buf *bp, int error, xfs_failaddr_t failaddr);
+void xfs_verifier_error(struct xfs_buf *bp, int error,
+ xfs_failaddr_t failaddr);
+void xfs_inode_verifier_error(struct xfs_inode *ip, int error,
+ const char *name, void *buf, size_t bufsz,
+ xfs_failaddr_t failaddr);
/* XXX: this is clearly a bug - a shared header needs to export this */
/* xfs_rtalloc.c */
diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c
index 7b75648c22..3c5def2950 100644
--- a/libxfs/rdwr.c
+++ b/libxfs/rdwr.c
@@ -1344,21 +1344,23 @@ bool
libxfs_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 %Lu inline data fork at %pF",
- __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 %Lu inline attr fork at %pF",
- __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;
diff --git a/libxfs/util.c b/libxfs/util.c
index 2d3b721777..aac558cf0c 100644
--- a/libxfs/util.c
+++ b/libxfs/util.c
@@ -744,6 +744,25 @@ xfs_verifier_error(
}
/*
+ * 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)
+{
+ xfs_alert(NULL, "Metadata %s detected at %p, inode 0x%llx %s",
+ error == -EFSBADCRC ? "CRC error" : "corruption",
+ failaddr ? failaddr : __return_address,
+ ip->i_ino, name);
+}
+
+/*
* This is called from I/O verifiers on v5 superblock filesystems. In the
* kernel, it validates the metadata LSN parameter against the current LSN of
* the active log. We don't have an active log in userspace so this kind of
diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c
index ecbd517854..2c805b342e 100644
--- a/libxfs/xfs_inode_buf.c
+++ b/libxfs/xfs_inode_buf.c
@@ -577,10 +577,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;
}