diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-09-01 11:25:03 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-12-15 17:29:28 -0800 |
commit | 6820eb4d84a13b0de1cce1afae8bec6baa9ac9f0 (patch) | |
tree | 0171d79f3a1f451fa1f7c270f41e3212ab52130d /fs/xfs/scrub | |
parent | f003db0ecaec5aad70a880986d0292a0c37573bb (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>
Diffstat (limited to 'fs/xfs/scrub')
-rw-r--r-- | fs/xfs/scrub/btree.c | 70 | ||||
-rw-r--r-- | fs/xfs/scrub/common.c | 90 | ||||
-rw-r--r-- | fs/xfs/scrub/common.h | 1 | ||||
-rw-r--r-- | fs/xfs/scrub/dabtree.c | 15 | ||||
-rw-r--r-- | fs/xfs/scrub/scrub.c | 31 |
5 files changed, 207 insertions, 0 deletions
diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c index 08a70f410887..9ad369aed1d3 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 c231dead630b..c81ee424553e 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); } @@ -834,6 +886,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), @@ -938,6 +996,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); /* @@ -969,6 +1031,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); } /* @@ -1145,3 +1212,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 fae1d1ae9c13..6da0ab14d315 100644 --- a/fs/xfs/scrub/common.h +++ b/fs/xfs/scrub/common.h @@ -175,6 +175,7 @@ bool xchk_ilock_nowait(struct xfs_scrub *sc, unsigned int ilock_flags); void xchk_iunlock(struct xfs_scrub *sc, unsigned int ilock_flags); 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 0c5f8b0995b6..a12612dd5df2 100644 --- a/fs/xfs/scrub/scrub.c +++ b/fs/xfs/scrub/scrub.c @@ -505,6 +505,36 @@ static inline void xchk_postmortem(struct xfs_scrub *sc) } #endif /* CONFIG_XFS_ONLINE_REPAIR */ +static inline void +repair_outcomes(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"; + 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); + return; + } else { + return; + } + + xfs_info_ratelimited(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( @@ -603,6 +633,7 @@ retry_op: * already tried to fix it, then attempt a repair. */ error = xrep_attempt(sc); + repair_outcomes(sc, error); if (error == -EAGAIN) { /* * Either the repair function succeeded or it couldn't |