xfs: whine to dmesg when we encounter errors

Forward everything scrub whines about to dmesg.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c
index 117910d..b061d22 100644
--- a/fs/xfs/scrub/btree.c
+++ b/fs/xfs/scrub/btree.c
@@ -24,6 +24,22 @@
 
 /* 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_bufs[level])
+		return XFS_DADDR_TO_FSB(cur->bc_mp, cur->bc_bufs[level]->b_bn);
+	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_private.b.ip->i_ino);
+	else if (!(cur->bc_flags & XFS_BTREE_LONG_PTRS))
+		return XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, 0);
+	return NULLFSBLOCK;
+}
+
 /*
  * Check for btree operation errors.  See the section about handling
  * operational errors in common.c.
@@ -53,11 +69,37 @@
 		/* fall through */
 	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 %llu fork %d type %d btnum %d level %d ptr %d agno %u agbno %u error %d ret_ip %pS",
+					cur->bc_private.b.ip->i_ino,
+					cur->bc_private.b.whichfork,
+					sc->sm->sm_type,
+					cur->bc_btnum,
+					level,
+					cur->bc_ptrs[level],
+					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 %u agbno %u error %d ret_ip %pS",
+					sc->sm->sm_type,
+					cur->bc_btnum,
+					level,
+					cur->bc_ptrs[level],
+					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;
@@ -97,11 +139,35 @@
 	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 %llu fork %d type %d btnum %d level %d ptr %d agno %u agbno %u ret_ip %pS",
+				cur->bc_private.b.ip->i_ino,
+				cur->bc_private.b.whichfork,
+				sc->sm->sm_type,
+				cur->bc_btnum,
+				level,
+				cur->bc_ptrs[level],
+				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 %u agbno %u ret_ip %pS",
+				sc->sm->sm_type,
+				cur->bc_btnum,
+				level,
+				cur->bc_ptrs[level],
+				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 4d45bd2..773a03d 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -33,6 +33,7 @@
 #include "xfs_attr.h"
 #include "xfs_reflink.h"
 #include "xfs_rtrmap_btree.h"
+#include "xfs_error.h"
 #include "scrub/xfs_scrub.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
@@ -92,6 +93,12 @@
 		*error = 0;
 		/* fall through */
 	default:
+		xchk_whine(sc->mp, "type %d agno %u agbno %u 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;
@@ -145,6 +152,13 @@
 		*error = 0;
 		/* fall through */
 	default:
+		xchk_whine(sc->mp, "ino %llu 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;
@@ -216,6 +230,8 @@
 	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);
 }
 
@@ -226,6 +242,11 @@
 	struct xfs_buf		*bp)
 {
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
+	xchk_whine(sc->mp, "type %d agno %u agbno %u ret_ip %pS",
+			sc->sm->sm_type,
+			XFS_FSB_TO_AGNO(sc->mp, XFS_DADDR_TO_FSB(sc->mp, bp->b_bn)),
+			XFS_FSB_TO_AGBNO(sc->mp, XFS_DADDR_TO_FSB(sc->mp, bp->b_bn)),
+			__return_address);
 	trace_xchk_block_error(sc, bp->b_bn, __return_address);
 }
 
@@ -236,6 +257,11 @@
 	struct xfs_buf		*bp)
 {
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XCORRUPT;
+	xchk_whine(sc->mp, "type %d agno %u agbno %u ret_ip %pS",
+			sc->sm->sm_type,
+			XFS_FSB_TO_AGNO(sc->mp, XFS_DADDR_TO_FSB(sc->mp, bp->b_bn)),
+			XFS_FSB_TO_AGBNO(sc->mp, XFS_DADDR_TO_FSB(sc->mp, bp->b_bn)),
+			__return_address);
 	trace_xchk_block_error(sc, bp->b_bn, __return_address);
 }
 
@@ -250,6 +276,8 @@
 	xfs_ino_t		ino)
 {
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
+	xchk_whine(sc->mp, "ino %llu type %d ret_ip %pS",
+			ino, sc->sm->sm_type, __return_address);
 	trace_xchk_ino_error(sc, ino, __return_address);
 }
 
@@ -260,6 +288,8 @@
 	xfs_ino_t		ino)
 {
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XCORRUPT;
+	xchk_whine(sc->mp, "ino %llu type %d ret_ip %pS",
+			ino, sc->sm->sm_type, __return_address);
 	trace_xchk_ino_error(sc, ino, __return_address);
 }
 
@@ -271,6 +301,12 @@
 	xfs_fileoff_t		offset)
 {
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
+	xchk_whine(sc->mp, "ino %llu 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);
 }
 
@@ -282,6 +318,12 @@
 	xfs_fileoff_t		offset)
 {
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_XCORRUPT;
+	xchk_whine(sc->mp, "ino %llu 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);
 }
 
@@ -295,6 +337,8 @@
 	xfs_ino_t		ino)
 {
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_WARNING;
+	xchk_whine(sc->mp, "ino %llu type %d agno %u agbno %u ret_ip %pS",
+			ino, sc->sm->sm_type, __return_address);
 	trace_xchk_ino_warning(sc, ino, __return_address);
 }
 
@@ -306,6 +350,12 @@
 	xfs_fileoff_t		offset)
 {
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_WARNING;
+	xchk_whine(sc->mp, "ino %llu 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);
 }
 
@@ -756,6 +806,12 @@
 		error = -EFSCORRUPTED;
 		/* fall through */
 	default:
+		xchk_whine(mp, "type %d agno %u agbno %u 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),
@@ -828,6 +884,10 @@
 	}
 
 	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);
 
 	/*
@@ -858,6 +918,11 @@
 	if (!fa)
 		return;
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
+	xchk_whine(sc->mp, "type %d agno %u agbno %u ret_ip %pS",
+			sc->sm->sm_type,
+			XFS_FSB_TO_AGNO(sc->mp, XFS_DADDR_TO_FSB(sc->mp, bp->b_bn)),
+			XFS_FSB_TO_AGBNO(sc->mp, XFS_DADDR_TO_FSB(sc->mp, bp->b_bn)),
+			fa);
 	trace_xchk_block_error(sc, bp->b_bn, fa);
 }
 
@@ -1040,3 +1105,29 @@
 	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;
+	int			level;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	printk(KERN_INFO "XFS (%s) %pf: %pV\n", mp->m_fsname, __return_address,
+			&vaf);
+	va_end(args);
+
+	if (!kstrtoint(KERN_INFO, 0, &level) &&
+	    level <= LOGLEVEL_ERR &&
+	    xfs_error_level >= XFS_ERRLEVEL_HIGH)
+		xfs_stack_trace();
+}
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index fa08ca3..d429908 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -133,6 +133,7 @@
 int xchk_setup_inode_contents(struct xfs_scrub *sc, struct xfs_inode *ip,
 		unsigned int resblks);
 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 e7891e0..41a625b 100644
--- a/fs/xfs/scrub/dabtree.c
+++ b/fs/xfs/scrub/dabtree.c
@@ -57,6 +57,14 @@
 		*error = 0;
 		/* fall through */
 	default:
+		xchk_whine(sc->mp, "ino %llu fork %d type %d offset %llu 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),
@@ -79,6 +87,13 @@
 
 	sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
 
+	xchk_whine(sc->mp, "ino %llu fork %d type %d offset %llu 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 2355444..39cfe30 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -584,6 +584,11 @@
 		 * already tried to fix it, then attempt a repair.
 		 */
 		error = xrep_attempt(ip, &sc);
+		if (error != -EOPNOTSUPP && error != -ENOENT)
+			xchk_whine(mp, "REPAIRED? ino 0x%llx type %u agno %u inum %llu gen %u flags 0x%x error %d",
+					ip->i_ino, sm->sm_type, sm->sm_agno,
+					sm->sm_ino, sm->sm_gen, sm->sm_flags,
+					(sc.flags & XREP_ALREADY_FIXED) ? 0 : 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 a1e177f..9f34dd3 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -253,10 +253,6 @@
 	randfactor = mp->m_errortag[error_tag];
 	if (!randfactor || prandom_u32() % randfactor)
 		return false;
-
-	xfs_warn_ratelimited(mp,
-"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
-			expression, file, line, mp->m_fsname);
 	return true;
 }