[PATCH 01/16] xfs_repair: fix missing dir buffer corruption checks

Darrick J. Wong
2020-05-09T16:30:03Z

From: Darrick J. Wong <darrick.wong@oracle.com>

Both callers of da_read_buf do not adequately check for verifier
failures in the (salvage mode) buffer that gets returned. This leads to
repair sometimes failing to complain about corrupt directories when run
with -n, which leads to an incorrect return value of 0 (all clean).

Found by running xfs/496 against lhdr.stale = middlebit.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
repair/da_util.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/repair/da_util.c b/repair/da_util.c
index 5061880f..92c04337 100644
--- a/repair/da_util.c
+++ b/repair/da_util.c
@@ -140,11 +140,24 @@ _("can't read %s block %u for inode %" PRIu64 "\n"),
if (whichfork == XFS_DATA_FORK &&
(nodehdr.magic == XFS_DIR2_LEAFN_MAGIC ||
nodehdr.magic == XFS_DIR3_LEAFN_MAGIC)) {
+ int bad = 0;
+
if (i != -1) {
do_warn(
_("found non-root LEAFN node in inode %" PRIu64 " bno = %u\n"),
da_cursor->ino, bno);
+ bad++;
}
+
+ /* corrupt leafn node; rebuild the dir. */
+ if (!bad &&
+ (bp->b_error == -EFSBADCRC ||
+ bp->b_error == -EFSCORRUPTED)) {
+ do_warn(
+_("corrupt %s LEAFN block %u for inode %" PRIu64 "\n"),
+ FORKNAME(whichfork), bno, da_cursor->ino);
+ }
+
*rbno = 0;
libxfs_buf_relse(bp);
return 1;
@@ -599,6 +612,14 @@ _("bad level %d in %s block %u for inode %" PRIu64 "\n"),
dabno, cursor->ino);
bad++;
}
+ if (!bad &&
+ (bp->b_error == -EFSCORRUPTED ||
+ bp->b_error == -EFSBADCRC)) {
+ do_warn(
+_("corruption error reading %s block %u for inode %" PRIu64 "\n"),
+ FORKNAME(whichfork), dabno, cursor->ino);
+ bad++;
+ }
if (bad) {
#ifdef XR_DIR_TRACE
fprintf(stderr, "verify_da_path returns 1 (bad) #4\n");