[PATCH 2/5] xfs_repair: better checking of v5 metadata fields

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Check the UUID, owner, and block number fields during repair, looking for
blocks that fail either the checksum or the data structure verifiers.  For
directories we can simply rebuild corrupt/broken index data, though for
anything else we have to toss out the broken object.

Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
---
 repair/dir2.c   |    7 ++
 repair/phase6.c |  159 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 repair/scan.c   |   17 ++++++
 3 files changed, 177 insertions(+), 6 deletions(-)


diff --git a/repair/dir2.c b/repair/dir2.c
index c6d618d..644c214 100644
--- a/repair/dir2.c
+++ b/repair/dir2.c
@@ -198,6 +198,13 @@ _("bad dir magic number 0x%x in inode %" PRIu64 " bno = %u\n"),
 					da_cursor->ino, bno);
 			goto error_out;
 		}
+		/* corrupt node; rebuild the dir. */
+		if (bp->b_error == EFSBADCRC || bp->b_error == EFSCORRUPTED) {
+			do_warn(
+_("corrupt tree block %u for directory inode %" PRIu64 "\n"),
+				bno, da_cursor->ino);
+			goto error_out;
+		}
 		btree = xfs_da3_node_tree_p(node);
 		if (nodehdr.count > mp->m_dir_node_ents)  {
 			libxfs_putbuf(bp);
diff --git a/repair/phase6.c b/repair/phase6.c
index c09b394..efefb2b 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -1981,6 +1981,41 @@ longform_dir2_check_leaf(
 		libxfs_putbuf(bp);
 		return 1;
 	}
+
+	/* check v5 metadata */
+	if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) {
+		struct xfs_dir3_leaf_hdr *block3 = bp->b_addr;
+
+		/* verify owner */
+		if (be64_to_cpu(block3->info.owner) != ip->i_ino) {
+			do_warn(
+	_("expected owner inode %" PRIu64 ", got %llu, directory block %" PRIu64 "\n"),
+				ip->i_ino, be64_to_cpu(block3->info.owner),
+				bp->b_bn);
+			libxfs_putbuf(bp);
+			return 1;
+		}
+		/* verify block number */
+		if (be64_to_cpu(block3->info.blkno) != bp->b_bn) {
+			do_warn(
+	_("expected block %" PRIu64 ", got %llu, directory inode %" PRIu64 "\n"),
+				bp->b_bn,
+				be64_to_cpu(block3->info.blkno),
+				ip->i_ino);
+			libxfs_putbuf(bp);
+			return 1;
+		}
+		/* verify uuid */
+		if (platform_uuid_compare(&block3->info.uuid,
+					  &mp->m_sb.sb_uuid) != 0) {
+			do_warn(
+	_("wrong FS UUID, directory inode %" PRIu64 " block %" PRIu64 "\n"),
+				ip->i_ino, bp->b_bn);
+			libxfs_putbuf(bp);
+			return 1;
+		}
+	}
+
 	seeval = dir_hash_see_all(hashtab, ents, leafhdr.count, leafhdr.stale);
 	if (dir_hash_check(hashtab, ip, seeval)) {
 		libxfs_putbuf(bp);
@@ -2055,12 +2090,9 @@ longform_dir2_check_node(
 		xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
 		ents = xfs_dir3_leaf_ents_p(leaf);
 		if (!(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC ||
-		      leafhdr.magic == XFS_DIR3_LEAFN_MAGIC)) {
-			if (leafhdr.magic == XFS_DA_NODE_MAGIC ||
-			    leafhdr.magic == XFS_DA3_NODE_MAGIC) {
-				libxfs_putbuf(bp);
-				continue;
-			}
+		      leafhdr.magic == XFS_DIR3_LEAFN_MAGIC ||
+		      leafhdr.magic == XFS_DA_NODE_MAGIC ||
+		      leafhdr.magic == XFS_DA3_NODE_MAGIC)) {
 			do_warn(
 	_("unknown magic number %#x for block %u in directory inode %" PRIu64 "\n"),
 				leafhdr.magic, da_bno, ip->i_ino);
@@ -2068,6 +2100,48 @@ longform_dir2_check_node(
 			return 1;
 		}
 
+		/* check v5 metadata */
+		if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC ||
+		    leafhdr.magic == XFS_DA3_NODE_MAGIC) {
+			struct xfs_da3_blkinfo	*info = bp->b_addr;
+
+			/* verify owner */
+			if (be64_to_cpu(info->owner) != ip->i_ino) {
+				do_warn(
+	_("expected owner inode %" PRIu64 ", got %llu, directory block %" PRIu64 "\n"),
+					ip->i_ino, be64_to_cpu(info->owner),
+					bp->b_bn);
+				libxfs_putbuf(bp);
+				return 1;
+			}
+			/* verify block number */
+			if (be64_to_cpu(info->blkno) != bp->b_bn) {
+				do_warn(
+	_("expected block %" PRIu64 ", got %llu, directory inode %" PRIu64 "\n"),
+					bp->b_bn,
+					be64_to_cpu(info->blkno),
+					ip->i_ino);
+				libxfs_putbuf(bp);
+				return 1;
+			}
+			/* verify uuid */
+			if (platform_uuid_compare(&info->uuid,
+						  &mp->m_sb.sb_uuid) != 0) {
+				do_warn(
+	_("wrong FS UUID, directory inode %" PRIu64 " block %" PRIu64 "\n"),
+					ip->i_ino, bp->b_bn);
+				libxfs_putbuf(bp);
+				return 1;
+			}
+		}
+
+		/* ignore nodes */
+		if (leafhdr.magic == XFS_DA_NODE_MAGIC ||
+		    leafhdr.magic == XFS_DA3_NODE_MAGIC) {
+			libxfs_putbuf(bp);
+			continue;
+		}
+
 		/*
 		 * If there's a validator error, we need to ensure that we got
 		 * the right ops on the buffer for when we write it back out.
@@ -2121,6 +2195,40 @@ longform_dir2_check_node(
 			libxfs_putbuf(bp);
 			return 1;
 		}
+
+		/* check v5 metadata */
+		if (freehdr.magic == XFS_DIR3_FREE_MAGIC) {
+			struct xfs_dir3_free_hdr *h = bp->b_addr;
+
+			/* verify owner */
+			if (be64_to_cpu(h->hdr.owner) != ip->i_ino) {
+				do_warn(
+	_("expected owner inode %" PRIu64 ", got %llu, directory block %" PRIu64 "\n"),
+					ip->i_ino, be64_to_cpu(h->hdr.owner),
+					bp->b_bn);
+				libxfs_putbuf(bp);
+				return 1;
+			}
+			/* verify block number */
+			if (be64_to_cpu(h->hdr.blkno) != bp->b_bn) {
+				do_warn(
+	_("expected block %" PRIu64 ", got %llu, directory inode %" PRIu64 "\n"),
+					bp->b_bn,
+					be64_to_cpu(h->hdr.blkno),
+					ip->i_ino);
+				libxfs_putbuf(bp);
+				return 1;
+			}
+			/* verify uuid */
+			if (platform_uuid_compare(&h->hdr.uuid,
+						  &mp->m_sb.sb_uuid) != 0) {
+				do_warn(
+	_("wrong FS UUID, directory inode %" PRIu64 " block %" PRIu64 "\n"),
+					ip->i_ino, bp->b_bn);
+				libxfs_putbuf(bp);
+				return 1;
+			}
+		}
 		for (i = used = 0; i < freehdr.nvalid; i++) {
 			if (i + freehdr.firstdb >= freetab->nents ||
 					freetab->ents[i + freehdr.firstdb].v !=
@@ -2212,6 +2320,7 @@ longform_dir2_entry_check(xfs_mount_t	*mp,
 	     da_bno = (xfs_dablk_t)next_da_bno) {
 		const struct xfs_buf_ops *ops;
 		int			 error;
+		struct xfs_dir2_data_hdr *d;
 
 		next_da_bno = da_bno + mp->m_dirblkfsbs - 1;
 		if (bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) {
@@ -2260,6 +2369,44 @@ longform_dir2_entry_check(xfs_mount_t	*mp,
 			}
 			continue;
 		}
+
+		/* check v5 metadata */
+		d = bplist[db]->b_addr;
+		if (be32_to_cpu(d->magic) == XFS_DIR3_BLOCK_MAGIC ||
+		    be32_to_cpu(d->magic) == XFS_DIR3_DATA_MAGIC) {
+			struct xfs_buf		 *bp = bplist[db];
+			struct xfs_dir3_data_hdr *block3 = bp->b_addr;
+
+			/* verify owner */
+			if (be64_to_cpu(block3->hdr.owner) != ino) {
+				do_warn(
+	_("expected owner inode %" PRIu64 ", got %llu, directory block %" PRIu64 "\n"),
+					ino, be64_to_cpu(block3->hdr.owner),
+					bp->b_bn);
+				fixit++;
+				continue;
+			}
+			/* verify block number */
+			if (be64_to_cpu(block3->hdr.blkno) != bp->b_bn) {
+				do_warn(
+	_("expected block %" PRIu64 ", got %llu, directory inode %" PRIu64 "\n"),
+					bp->b_bn,
+					be64_to_cpu(block3->hdr.blkno),
+					ino);
+				fixit++;
+				continue;
+			}
+			/* verify uuid */
+			if (platform_uuid_compare(&block3->hdr.uuid,
+						  &mp->m_sb.sb_uuid) != 0) {
+				do_warn(
+	_("wrong FS UUID, directory inode %" PRIu64 " block %" PRIu64 "\n"),
+					ino, bp->b_bn);
+				fixit++;
+				continue;
+			}
+		}
+
 		longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot,
 				irec, ino_offset, &bplist[db], hashtab,
 				&freetab, da_bno, isblock);
diff --git a/repair/scan.c b/repair/scan.c
index 12aa782..79fbf83 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -227,6 +227,23 @@ _("expected owner inode %" PRIu64 ", got %llu, bmbt block %" PRIu64 "\n"),
 				ino, be64_to_cpu(block->bb_u.l.bb_owner), bno);
 			return(1);
 		}
+		/* verify block number */
+		if (be64_to_cpu(block->bb_u.l.bb_blkno) !=
+		    XFS_FSB_TO_DADDR(mp, bno)) {
+			do_warn(
+_("expected block %" PRIu64 ", got %llu, bmbt block %" PRIu64 "\n"),
+				XFS_FSB_TO_DADDR(mp, bno),
+				be64_to_cpu(block->bb_u.l.bb_blkno), bno);
+			return(1);
+		}
+		/* verify uuid */
+		if (platform_uuid_compare(&block->bb_u.l.bb_uuid,
+					  &mp->m_sb.sb_uuid) != 0) {
+			do_warn(
+_("wrong FS UUID, bmbt block %" PRIu64 "\n"),
+				bno);
+			return(1);
+		}
 	}
 
 	if (check_dups == 0)  {

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs




[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux