[PATCH 20/28] repair: validate ir_count field for sparse format records

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

 



Sparse format inobt records contain an additional count field that
records the number of physical inodes tracked by the record. Verify the
count is internally consistent according to the holemask, similar to how
freecount is validated against the free mask.

Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx>
---
 repair/scan.c | 43 ++++++++++++++++++++++++++++++++++---------
 1 file changed, 34 insertions(+), 9 deletions(-)

diff --git a/repair/scan.c b/repair/scan.c
index 52c05e2..9b16199 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -758,6 +758,7 @@ scan_single_ino_chunk(
 	xfs_agblock_t		agbno;
 	int			j;
 	int			nfree;
+	int			ninodes;
 	int			off;
 	int			state;
 	ino_tree_node_t		*ino_rec = NULL;
@@ -909,7 +910,7 @@ _("inode rec for ino %" PRIu64 " (%d/%d) overlaps existing rec (start %d/%d)\n")
 	 * Mark sparse inodes as such in the in-core tree. Verify that sparse
 	 * inodes are free and that freecount is consistent with the free mask.
 	 */
-	nfree = 0;
+	nfree = ninodes = 0;
 	for (j = 0; j < XFS_INODES_PER_CHUNK; j++) {
 		if (ino_issparse(rp, j)) {
 			if (!suspect && !XFS_INOBT_IS_FREE_DISK(rp, j)) {
@@ -922,9 +923,11 @@ _("ir_holemask/ir_free mismatch, inode chunk %d/%u, holemask 0x%x free 0x%llx\n"
 			}
 			if (!suspect && ino_rec)
 				set_inode_sparse(ino_rec, j);
-		} else if (XFS_INOBT_IS_FREE_DISK(rp, j)) {
-			/* freecount only tracks non-sparse inos */
-			nfree++;
+		} else {
+			/* count fields track non-sparse inos */
+			if (XFS_INOBT_IS_FREE_DISK(rp, j))
+				nfree++;
+			ninodes++;
 		}
 	}
 
@@ -934,6 +937,14 @@ _("ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n"),
 			agno, ino, freecount, nfree);
 	}
 
+	/* verify sparse record formats have a valid inode count */
+	if (xfs_sb_version_hassparseinodes(&mp->m_sb) &&
+	    ninodes != rp->ir_u.sp.ir_count) {
+		do_warn(
+_("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"),
+			agno, ino, rp->ir_u.sp.ir_count, ninodes);
+	}
+
 	return suspect;
 }
 
@@ -948,6 +959,7 @@ scan_single_finobt_chunk(
 	xfs_agblock_t		agbno;
 	int			j;
 	int			nfree;
+	int			ninodes;
 	int			off;
 	int			state;
 	ino_tree_node_t		*ino_rec = NULL;
@@ -1069,11 +1081,13 @@ _("finobt rec for ino %" PRIu64 " (%d/%u) does not match existing rec (%d/%d)\n"
 			return ++suspect;
 		}
 
-		nfree = 0;
+		nfree = ninodes = 0;
 		for (j = 0; j < XFS_INODES_PER_CHUNK; j++) {
 			int isfree = XFS_INOBT_IS_FREE_DISK(rp, j);
 			int issparse = ino_issparse(rp, j);
 
+			if (!issparse)
+				ninodes++;
 			if (isfree && !issparse)
 				nfree++;
 
@@ -1135,7 +1149,7 @@ _("finobt rec for ino %" PRIu64 " (%d/%u) does not match existing rec (%d/%d)\n"
 	 * Mark sparse inodes as such in the in-core tree. Verify that sparse
 	 * inodes are free and that freecount is consistent with the free mask.
 	 */
-	nfree = 0;
+	nfree = ninodes = 0;
 	for (j = 0; j < XFS_INODES_PER_CHUNK; j++) {
 		if (ino_issparse(rp, j)) {
 			if (!suspect && !XFS_INOBT_IS_FREE_DISK(rp, j)) {
@@ -1148,10 +1162,13 @@ _("finobt ir_holemask/ir_free mismatch, inode chunk %d/%u, holemask 0x%x free 0x
 			}
 			if (!suspect && ino_rec)
 				set_inode_sparse(ino_rec, j);
-		} else if (XFS_INOBT_IS_FREE_DISK(rp, j)) {
-			/* freecount only tracks non-sparse inos */
-			nfree++;
+		} else {
+			/* count fields track non-sparse inos */
+			if (XFS_INOBT_IS_FREE_DISK(rp, j))
+				nfree++;
+			ninodes++;
 		}
+
 	}
 
 check_freecount:
@@ -1178,6 +1195,14 @@ _("finobt ir_freecount/free mismatch, inode chunk %d/%u, freecount %d nfree %d\n
 _("finobt record with no free inodes, inode chunk %d/%u\n"), agno, ino);
 	}
 
+	/* verify sparse record formats have a valid inode count */
+	if (xfs_sb_version_hassparseinodes(&mp->m_sb) &&
+	    ninodes != rp->ir_u.sp.ir_count) {
+		do_warn(
+_("invalid inode count, inode chunk %d/%u, count %d ninodes %d\n"),
+			agno, ino, rp->ir_u.sp.ir_count, ninodes);
+	}
+
 	return suspect;
 }
 
-- 
1.9.3

_______________________________________________
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