Author: wuguanghao <wuguanghao3@huawei.com> Date: Mon Mar 14 20:12:17 2022 +0800 (cherry picked from commit feb7ea39582af46f13599e1678473c98965b05c7)
125 lines
3.9 KiB
Diff
125 lines
3.9 KiB
Diff
From be752639294c8a1eb0f06275e77744f32e5bd277 Mon Sep 17 00:00:00 2001
|
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
|
Date: Fri, 10 Jul 2020 15:34:36 -0400
|
|
Subject: [PATCH] xfs_repair: fix missing dir buffer corruption checks
|
|
|
|
The da_read_buf() function operates in "salvage" mode, which means that
|
|
if the verifiers fail, it will return a buffer with b_error set. The
|
|
callers of da_read_buf, however, do not adequately check for verifier
|
|
errors, which means that repair can fail to flag a corrupt filesystem.
|
|
|
|
Fix the callers to do this properly. The dabtree block walker and the
|
|
dabtree path checker functions to complain any time the da node / leafn
|
|
verifiers fail. Fix the directory block walking functions to complain
|
|
about EFSCORRUPTED, since they already dealt with EFSBADCRC.
|
|
|
|
Found by running xfs/496 against lhdr.stale = middlebit.
|
|
|
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
|
---
|
|
repair/da_util.c | 25 ++++++++++++++++---------
|
|
repair/dir2.c | 21 +++++++++++++++++++++
|
|
2 files changed, 37 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/repair/da_util.c b/repair/da_util.c
|
|
index 5061880f..7239c2e2 100644
|
|
--- a/repair/da_util.c
|
|
+++ b/repair/da_util.c
|
|
@@ -134,6 +134,15 @@ _("can't read %s block %u for inode %" PRIu64 "\n"),
|
|
goto error_out;
|
|
}
|
|
|
|
+ /* corrupt leafn/node; rebuild the dir. */
|
|
+ if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) {
|
|
+ do_warn(
|
|
+_("corrupt %s tree block %u for inode %" PRIu64 "\n"),
|
|
+ FORKNAME(whichfork), bno, da_cursor->ino);
|
|
+ libxfs_buf_relse(bp);
|
|
+ goto error_out;
|
|
+ }
|
|
+
|
|
node = bp->b_addr;
|
|
libxfs_da3_node_hdr_from_disk(mp, &nodehdr, node);
|
|
|
|
@@ -160,15 +169,6 @@ _("bad %s magic number 0x%x in inode %" PRIu64 " bno = %u\n"),
|
|
goto error_out;
|
|
}
|
|
|
|
- /* corrupt node; rebuild the dir. */
|
|
- if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) {
|
|
- libxfs_buf_relse(bp);
|
|
- do_warn(
|
|
-_("corrupt %s tree block %u for inode %" PRIu64 "\n"),
|
|
- FORKNAME(whichfork), bno, da_cursor->ino);
|
|
- goto error_out;
|
|
- }
|
|
-
|
|
if (nodehdr.count > geo->node_ents) {
|
|
do_warn(
|
|
_("bad %s record count in inode %" PRIu64 ", count = %d, max = %d\n"),
|
|
@@ -562,6 +562,13 @@ _("can't read %s block %u for inode %" PRIu64 "\n"),
|
|
FORKNAME(whichfork), dabno, cursor->ino);
|
|
return 1;
|
|
}
|
|
+ if (bp->b_error == -EFSCORRUPTED || bp->b_error == -EFSBADCRC) {
|
|
+ do_warn(
|
|
+_("corrupt %s tree block %u for inode %" PRIu64 "\n"),
|
|
+ FORKNAME(whichfork), dabno, cursor->ino);
|
|
+ libxfs_buf_relse(bp);
|
|
+ return 1;
|
|
+ }
|
|
|
|
newnode = bp->b_addr;
|
|
libxfs_da3_node_hdr_from_disk(mp, &nodehdr, newnode);
|
|
diff --git a/repair/dir2.c b/repair/dir2.c
|
|
index cbbce601..b374bc7b 100644
|
|
--- a/repair/dir2.c
|
|
+++ b/repair/dir2.c
|
|
@@ -983,6 +983,13 @@ _("can't read block %u for directory inode %" PRIu64 "\n"),
|
|
mp->m_dir_geo->datablk, ino);
|
|
return 1;
|
|
}
|
|
+ if (bp->b_error == -EFSCORRUPTED) {
|
|
+ do_warn(
|
|
+_("corrupt directory block %u for inode %" PRIu64 "\n"),
|
|
+ mp->m_dir_geo->datablk, ino);
|
|
+ libxfs_buf_relse(bp);
|
|
+ return 1;
|
|
+ }
|
|
/*
|
|
* Verify the block
|
|
*/
|
|
@@ -1122,6 +1129,13 @@ _("can't read file block %u for directory inode %" PRIu64 "\n"),
|
|
da_bno, ino);
|
|
goto error_out;
|
|
}
|
|
+ if (bp->b_error == -EFSCORRUPTED) {
|
|
+ do_warn(
|
|
+_("corrupt directory leafn block %u for inode %" PRIu64 "\n"),
|
|
+ da_bno, ino);
|
|
+ libxfs_buf_relse(bp);
|
|
+ goto error_out;
|
|
+ }
|
|
leaf = bp->b_addr;
|
|
libxfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf);
|
|
/*
|
|
@@ -1324,6 +1338,13 @@ _("can't read block %" PRIu64 " for directory inode %" PRIu64 "\n"),
|
|
dbno, ino);
|
|
continue;
|
|
}
|
|
+ if (bp->b_error == -EFSCORRUPTED) {
|
|
+ do_warn(
|
|
+_("corrupt directory data block %lu for inode %" PRIu64 "\n"),
|
|
+ dbno, ino);
|
|
+ libxfs_buf_relse(bp);
|
|
+ continue;
|
|
+ }
|
|
data = bp->b_addr;
|
|
if (!(be32_to_cpu(data->magic) == XFS_DIR2_DATA_MAGIC ||
|
|
be32_to_cpu(data->magic) == XFS_DIR3_DATA_MAGIC))
|
|
--
|
|
2.27.0
|
|
|