summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:25:03 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-09-17 18:55:28 -0700
commitebae1392f0792652de4d178f15f106ed7904068f (patch)
tree1eabfa93889c13fb5ea79a29e084fc10c63945d9
parent217968612d00111137df0bfe4bf594ae1af001ae (diff)
xfs: whine to dmesg when we encounter errors
Forward everything scrub whines about to dmesg. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/scrub/btree.c70
-rw-r--r--fs/xfs/scrub/common.c90
-rw-r--r--fs/xfs/scrub/common.h1
-rw-r--r--fs/xfs/scrub/dabtree.c15
-rw-r--r--fs/xfs/scrub/scrub.c25
-rw-r--r--fs/xfs/xfs_error.c2
6 files changed, 203 insertions, 0 deletions
diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c
index 99a262e0a506..84116b6689da 100644
--- a/fs/xfs/scrub/btree.c
+++ b/fs/xfs/scrub/btree.c
@@ -11,6 +11,9 @@
#include "xfs_mount.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
+#include "xfs_log_format.h"
+#include "xfs_inode.h"
+#include "xfs_ag.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/btree.h"
@@ -18,6 +21,23 @@
/* btree scrubbing */
+/* Figure out which block the btree cursor was pointing to. */
+static inline xfs_fsblock_t
+xchk_btree_cur_fsbno(
+ struct xfs_btree_cur *cur,
+ int level)
+{
+ if (level < cur->bc_nlevels && cur->bc_levels[level].bp)
+ return XFS_DADDR_TO_FSB(cur->bc_mp,
+ xfs_buf_daddr(cur->bc_levels[level].bp));
+ else if (level == cur->bc_nlevels - 1 &&
+ (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE))
+ return XFS_INO_TO_FSB(cur->bc_mp, cur->bc_ino.ip->i_ino);
+ else if (!(cur->bc_flags & XFS_BTREE_LONG_PTRS))
+ return XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_ag.pag->pag_agno, 0);
+ return NULLFSBLOCK;
+}
+
/*
* Check for btree operation errors. See the section about handling
* operational errors in common.c.
@@ -47,11 +67,37 @@ __xchk_btree_process_error(
fallthrough;
default:
if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
+ {
+ xfs_fsblock_t fsbno = xchk_btree_cur_fsbno(cur, level);
+ xchk_whine(sc->mp, "ino 0x%llx fork %d type %d btnum %d level %d ptr %d agno 0x%x agbno 0x%x error %d ret_ip %pS",
+ cur->bc_ino.ip->i_ino,
+ cur->bc_ino.whichfork,
+ sc->sm->sm_type,
+ cur->bc_btnum,
+ level,
+ cur->bc_levels[level].ptr,
+ XFS_FSB_TO_AGNO(cur->bc_mp, fsbno),
+ XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno),
+ *error,
+ ret_ip);
trace_xchk_ifork_btree_op_error(sc, cur, level,
*error, ret_ip);
+ }
else
+ {
+ xfs_fsblock_t fsbno = xchk_btree_cur_fsbno(cur, level);
+ xchk_whine(sc->mp, "type %d btnum %d level %d ptr %d agno 0x%x agbno 0x%x error %d ret_ip %pS",
+ sc->sm->sm_type,
+ cur->bc_btnum,
+ level,
+ cur->bc_levels[level].ptr,
+ XFS_FSB_TO_AGNO(cur->bc_mp, fsbno),
+ XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno),
+ *error,
+ ret_ip);
trace_xchk_btree_op_error(sc, cur, level,
*error, ret_ip);
+ }
break;
}
return false;
@@ -91,11 +137,35 @@ __xchk_btree_set_corrupt(
sc->sm->sm_flags |= errflag;
if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
+ {
+ xfs_fsblock_t fsbno = xchk_btree_cur_fsbno(cur, level);
+ xchk_whine(sc->mp, "ino 0x%llx fork %d type %d btnum %d level %d ptr %d agno 0x%x agbno 0x%x ret_ip %pS",
+ cur->bc_ino.ip->i_ino,
+ cur->bc_ino.whichfork,
+ sc->sm->sm_type,
+ cur->bc_btnum,
+ level,
+ cur->bc_levels[level].ptr,
+ XFS_FSB_TO_AGNO(cur->bc_mp, fsbno),
+ XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno),
+ ret_ip);
trace_xchk_ifork_btree_error(sc, cur, level,
ret_ip);
+ }
else
+ {
+ xfs_fsblock_t fsbno = xchk_btree_cur_fsbno(cur, level);
+ xchk_whine(sc->mp, "type %d btnum %d level %d ptr %d agno 0x%x agbno 0x%x ret_ip %pS",
+ sc->sm->sm_type,
+ cur->bc_btnum,
+ level,
+ cur->bc_levels[level].ptr,
+ XFS_FSB_TO_AGNO(cur->bc_mp, fsbno),
+ XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno),
+ ret_ip);
trace_xchk_btree_error(sc, cur, level,
ret_ip);
+ }
}
void
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index a2bbebb99bc1..96864ec1d21f 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -31,6 +31,7 @@
#include "xfs_rtalloc.h"
#include "xfs_rtrmap_btree.h"
#include "xfs_rtrefcount_btree.h"
+#include "xfs_error.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/trace.h"
@@ -99,6 +100,12 @@ __xchk_process_error(
*error = 0;
fallthrough;
default:
+ xchk_whine(sc->mp, "type %d agno 0x%x agbno 0x%x error %d ret_ip %pS",
+ sc->sm->sm_type,
+ agno,
+ bno,
+ *error,
+ ret_ip);
trace_xchk_op_error(sc, agno, bno, *error, ret_ip);
break;
}
@@ -161,6 +168,13 @@ __xchk_fblock_process_error(
*error = 0;
fallthrough;
default:
+ xchk_whine(sc->mp, "ino 0x%llx fork %d type %d offset %llu error %d ret_ip %pS",
+ sc->ip->i_ino,
+ whichfork,
+ sc->sm->sm_type,
+ offset,
+ *error,
+ ret_ip);
trace_xchk_file_op_error(sc, whichfork, offset, *error,
ret_ip);
break;
@@ -232,6 +246,8 @@ xchk_set_corrupt(
struct xfs_scrub *sc)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
+ xchk_whine(sc->mp, "type %d ret_ip %pS", sc->sm->sm_type,
+ __return_address);
trace_xchk_fs_error(sc, 0, __return_address);
}
@@ -243,6 +259,11 @@ xchk_block_set_corrupt(
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
trace_xchk_block_error(sc, xfs_buf_daddr(bp), __return_address);
+ xchk_whine(sc->mp, "type %d agno 0x%x agbno 0x%x ret_ip %pS",
+ sc->sm->sm_type,
+ xfs_daddr_to_agno(sc->mp, xfs_buf_daddr(bp)),
+ xfs_daddr_to_agbno(sc->mp, xfs_buf_daddr(bp)),
+ __return_address);
}
/* Record a corrupt quota counter. */
@@ -253,6 +274,8 @@ xchk_qcheck_set_corrupt(
xfs_dqid_t id)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
+ xchk_whine(sc->mp, "type %d dqtype %u id %u ret_ip %pS",
+ sc->sm->sm_type, dqtype, id, __return_address);
trace_xchk_qcheck_error(sc, dqtype, id, __return_address);
}
@@ -264,6 +287,11 @@ xchk_block_xref_set_corrupt(
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XCORRUPT;
trace_xchk_block_error(sc, xfs_buf_daddr(bp), __return_address);
+ xchk_whine(sc->mp, "type %d agno 0x%x agbno 0x%x ret_ip %pS",
+ sc->sm->sm_type,
+ xfs_daddr_to_agno(sc->mp, xfs_buf_daddr(bp)),
+ xfs_daddr_to_agbno(sc->mp, xfs_buf_daddr(bp)),
+ __return_address);
}
/*
@@ -277,6 +305,8 @@ xchk_ino_set_corrupt(
xfs_ino_t ino)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
+ xchk_whine(sc->mp, "ino 0x%llx type %d ret_ip %pS",
+ ino, sc->sm->sm_type, __return_address);
trace_xchk_ino_error(sc, ino, __return_address);
}
@@ -287,6 +317,8 @@ xchk_ino_xref_set_corrupt(
xfs_ino_t ino)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XCORRUPT;
+ xchk_whine(sc->mp, "ino 0x%llx type %d ret_ip %pS",
+ ino, sc->sm->sm_type, __return_address);
trace_xchk_ino_error(sc, ino, __return_address);
}
@@ -298,6 +330,12 @@ xchk_fblock_set_corrupt(
xfs_fileoff_t offset)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
+ xchk_whine(sc->mp, "ino 0x%llx fork %d type %d offset %llu ret_ip %pS",
+ sc->ip->i_ino,
+ whichfork,
+ sc->sm->sm_type,
+ offset,
+ __return_address);
trace_xchk_fblock_error(sc, whichfork, offset, __return_address);
}
@@ -309,6 +347,12 @@ xchk_fblock_xref_set_corrupt(
xfs_fileoff_t offset)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XCORRUPT;
+ xchk_whine(sc->mp, "ino 0x%llx fork %d type %d offset %llu ret_ip %pS",
+ sc->ip->i_ino,
+ whichfork,
+ sc->sm->sm_type,
+ offset,
+ __return_address);
trace_xchk_fblock_error(sc, whichfork, offset, __return_address);
}
@@ -322,6 +366,8 @@ xchk_ino_set_warning(
xfs_ino_t ino)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_WARNING;
+ xchk_whine(sc->mp, "ino 0x%llx type %d agno 0x%x agbno 0x%x ret_ip %pS",
+ ino, sc->sm->sm_type, __return_address);
trace_xchk_ino_warning(sc, ino, __return_address);
}
@@ -333,6 +379,12 @@ xchk_fblock_set_warning(
xfs_fileoff_t offset)
{
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_WARNING;
+ xchk_whine(sc->mp, "ino 0x%llx fork %d type %d offset %llu ret_ip %pS",
+ sc->ip->i_ino,
+ whichfork,
+ sc->sm->sm_type,
+ offset,
+ __return_address);
trace_xchk_fblock_warning(sc, whichfork, offset, __return_address);
}
@@ -813,6 +865,12 @@ xchk_get_inode(
error = -EFSCORRUPTED;
fallthrough;
default:
+ xchk_whine(mp, "type %d agno 0x%x agbno 0x%x error %d ret_ip %pS",
+ sc->sm->sm_type,
+ XFS_INO_TO_AGNO(mp, sc->sm->sm_ino),
+ XFS_INO_TO_AGBNO(mp, sc->sm->sm_ino),
+ error,
+ __return_address);
trace_xchk_op_error(sc,
XFS_INO_TO_AGNO(mp, sc->sm->sm_ino),
XFS_INO_TO_AGBNO(mp, sc->sm->sm_ino),
@@ -889,6 +947,10 @@ xchk_should_check_xref(
}
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XFAIL;
+ xchk_whine(sc->mp, "type %d xref error %d ret_ip %pS",
+ sc->sm->sm_type,
+ *error,
+ __return_address);
trace_xchk_xref_error(sc, *error, __return_address);
/*
@@ -920,6 +982,11 @@ xchk_buffer_recheck(
return;
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
trace_xchk_block_error(sc, xfs_buf_daddr(bp), fa);
+ xchk_whine(sc->mp, "type %d agno 0x%x agbno 0x%x ret_ip %pS",
+ sc->sm->sm_type,
+ xfs_daddr_to_agno(sc->mp, xfs_buf_daddr(bp)),
+ xfs_daddr_to_agbno(sc->mp, xfs_buf_daddr(bp)),
+ fa);
}
/*
@@ -1118,3 +1185,26 @@ xchk_fs_thaw(
mutex_unlock(&sc->mp->m_scrub_freeze);
return error;
}
+
+/* Complain about failures... */
+void
+xchk_whine(
+ const struct xfs_mount *mp,
+ const char *fmt,
+ ...)
+{
+ struct va_format vaf;
+ va_list args;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_INFO "XFS (%s) %pS: %pV\n", mp->m_super->s_id,
+ __return_address, &vaf);
+ va_end(args);
+
+ if (xfs_error_level >= XFS_ERRLEVEL_HIGH)
+ xfs_stack_trace();
+}
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index 7353fd1f2305..6fa1fb21150d 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -166,6 +166,7 @@ int xchk_get_inode(struct xfs_scrub *sc);
int xchk_setup_inode_contents(struct xfs_scrub *sc, unsigned int resblks);
int xchk_install_inode(struct xfs_scrub *sc, struct xfs_inode *ip);
void xchk_buffer_recheck(struct xfs_scrub *sc, struct xfs_buf *bp);
+void xchk_whine(const struct xfs_mount *mp, const char *fmt, ...);
/*
* Don't bother cross-referencing if we already found corruption or cross
diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c
index ed47f8a14a79..47aaae8fd86a 100644
--- a/fs/xfs/scrub/dabtree.c
+++ b/fs/xfs/scrub/dabtree.c
@@ -49,6 +49,14 @@ xchk_da_process_error(
*error = 0;
fallthrough;
default:
+ xchk_whine(sc->mp, "ino 0x%llx fork %d type %d dablk 0x%llx error %d ret_ip %pS",
+ sc->ip->i_ino,
+ ds->dargs.whichfork,
+ sc->sm->sm_type,
+ xfs_dir2_da_to_db(ds->dargs.geo,
+ ds->state->path.blk[level].blkno),
+ *error,
+ __return_address);
trace_xchk_file_op_error(sc, ds->dargs.whichfork,
xfs_dir2_da_to_db(ds->dargs.geo,
ds->state->path.blk[level].blkno),
@@ -71,6 +79,13 @@ xchk_da_set_corrupt(
sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
+ xchk_whine(sc->mp, "ino 0x%llx fork %d type %d dablk 0x%llx ret_ip %pS",
+ sc->ip->i_ino,
+ ds->dargs.whichfork,
+ sc->sm->sm_type,
+ xfs_dir2_da_to_db(ds->dargs.geo,
+ ds->state->path.blk[level].blkno),
+ __return_address);
trace_xchk_fblock_error(sc, ds->dargs.whichfork,
xfs_dir2_da_to_db(ds->dargs.geo,
ds->state->path.blk[level].blkno),
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index c8a57a0017d1..3349b1ca998f 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -517,6 +517,30 @@ static inline void xchk_postmortem(struct xfs_scrub *sc)
}
#endif /* CONFIG_XFS_ONLINE_REPAIR */
+static inline void
+whine(struct xfs_scrub *sc, int error)
+{
+ struct xfs_scrub_metadata *sm = sc->sm;
+ const char *wut = NULL;
+
+ if (sc->flags & XREP_ALREADY_FIXED) {
+ wut = "*** REPAIR SUCCESS";
+ error = 0;
+ } else if (error == -EAGAIN)
+ wut = "??? REPAIR DEFERRED";
+ else if (error != -EOPNOTSUPP && error != -ENOENT)
+ wut = "!!! REPAIR FAILED";
+
+ if (!wut)
+ return;
+
+ xfs_info(sc->mp,
+"%s ino 0x%llx type %u agno 0x%x inum 0x%llx gen 0x%x flags 0x%x error %d",
+ wut, XFS_I(file_inode(sc->file))->i_ino, sm->sm_type,
+ sm->sm_agno, sm->sm_ino, sm->sm_gen, sm->sm_flags,
+ error);
+}
+
/* Dispatch metadata scrubbing. */
int
xfs_scrub_metadata(
@@ -618,6 +642,7 @@ retry_op:
* already tried to fix it, then attempt a repair.
*/
error = xrep_attempt(sc);
+ whine(sc, error);
if (error == -EAGAIN) {
/*
* Either the repair function succeeded or it couldn't
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 19b46636825e..f6af8e3b9912 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -273,9 +273,11 @@ xfs_errortag_test(
if (!randfactor || prandom_u32() % randfactor)
return false;
+#if 0
xfs_warn_ratelimited(mp,
"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
expression, file, line, mp->m_super->s_id);
+#endif
return true;
}