Blame SOURCES/xfsprogs-4.5.0-revert-xfs_db-sparse-inodes.patch

4a5a34
commit 09c93e56b5296a30507cde9c00433eb4ed2d395d
4a5a34
Author: Brian Foster <bfoster@redhat.com>
4a5a34
Date:   Tue Jun 21 12:58:57 2016 +1000
4a5a34
4a5a34
    xfs_db: Revert "xfs_db: make check work for sparse inodes"
4a5a34
    
4a5a34
    This reverts commit bb2f98b78f20f4abbfbbd442162d9f535c84888a which
4a5a34
    introduced support for multi-record inode chunks in
4a5a34
    xfs_db/xfs_check. However, it doesn't currently handle filesystems
4a5a34
    with multi-record inode chunks correctly. For example, do the
4a5a34
    following on a 64k page size arch such as ppc64:
4a5a34
    
4a5a34
    # mkfs.xfs -f -b size=64k <dev>
4a5a34
    # xfs_db -c check <dev>
4a5a34
    bad magic number 0 for inode 1152
4a5a34
    bad magic number 0 for inode 1153
4a5a34
    bad magic number 0 for inode 1154
4a5a34
    bad magic number 0 for inode 1155
4a5a34
    bad magic number 0 for inode 1156
4a5a34
    bad magic number 0 for inode 1157
4a5a34
    ...
4a5a34
    
4a5a34
    This boils down to a regression in the inode record processing code
4a5a34
    (scanfunc_ino()) in db/check.c. Specifically, the cblocks value can
4a5a34
    end up being zero after it is shifted by mp->m_sb.sb_inopblog (i.e.,
4a5a34
    64 >> 7 == 0 for an -isize=512 -bsize=64k fs).
4a5a34
    
4a5a34
    Fixing this problem is easier to do from scratch, so revert the
4a5a34
    oringial commit first.
4a5a34
    
4a5a34
    Signed-off-by: Brian Foster <bfoster@redhat.com>
4a5a34
    Reviewed-by: Dave Chinner <dchinner@redhat.com>
4a5a34
    Signed-off-by: Dave Chinner <david@fromorbit.com>
4a5a34
4a5a34
diff --git a/db/check.c b/db/check.c
4a5a34
index 0871ed7..750ecc1 100644
4a5a34
--- a/db/check.c
4a5a34
+++ b/db/check.c
4a5a34
@@ -4311,51 +4311,6 @@ scanfunc_cnt(
4a5a34
 		scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_cnt, TYP_CNTBT);
4a5a34
 }
4a5a34
 
4a5a34
-static bool
4a5a34
-ino_issparse(
4a5a34
-	struct xfs_inobt_rec	*rp,
4a5a34
-	int			offset)
4a5a34
-{
4a5a34
-	if (!xfs_sb_version_hassparseinodes(&mp->m_sb))
4a5a34
-		return false;
4a5a34
-
4a5a34
-	return xfs_inobt_is_sparse_disk(rp, offset);
4a5a34
-}
4a5a34
-
4a5a34
-static int
4a5a34
-find_one_ino_bit(
4a5a34
-	__u16		mask,
4a5a34
-	int		startino)
4a5a34
-{
4a5a34
-	int		n;
4a5a34
-	int		b;
4a5a34
-
4a5a34
-	startino /= XFS_INODES_PER_HOLEMASK_BIT;
4a5a34
-	b = startino;
4a5a34
-	mask >>= startino;
4a5a34
-	for (n = startino; n < sizeof(mask) * NBBY && !(mask & 1); n++, mask >>= 1)
4a5a34
-		b++;
4a5a34
-
4a5a34
-	return b * XFS_INODES_PER_HOLEMASK_BIT;
4a5a34
-}
4a5a34
-
4a5a34
-static int
4a5a34
-find_zero_ino_bit(
4a5a34
-	__u16		mask,
4a5a34
-	int		startino)
4a5a34
-{
4a5a34
-	int		n;
4a5a34
-	int		b;
4a5a34
-
4a5a34
-	startino /= XFS_INODES_PER_HOLEMASK_BIT;
4a5a34
-	b = startino;
4a5a34
-	mask >>= startino;
4a5a34
-	for (n = startino; n < sizeof(mask) * NBBY && (mask & 1); n++, mask >>= 1)
4a5a34
-		b++;
4a5a34
-
4a5a34
-	return b * XFS_INODES_PER_HOLEMASK_BIT;
4a5a34
-}
4a5a34
-
4a5a34
 static void
4a5a34
 scanfunc_ino(
4a5a34
 	struct xfs_btree_block	*block,
4a5a34
@@ -4373,13 +4328,6 @@ scanfunc_ino(
4a5a34
 	int			off;
4a5a34
 	xfs_inobt_ptr_t		*pp;
4a5a34
 	xfs_inobt_rec_t		*rp;
4a5a34
-	bool			sparse, crc;
4a5a34
-	int			inodes_per_chunk;
4a5a34
-	int			freecount;
4a5a34
-	int			startidx, endidx;
4a5a34
-	__u16			holemask;
4a5a34
-	xfs_agino_t		rino;
4a5a34
-	xfs_extlen_t		cblocks;
4a5a34
 
4a5a34
 	if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC &&
4a5a34
 	    be32_to_cpu(block->bb_magic) != XFS_IBT_CRC_MAGIC) {
4a5a34
@@ -4407,111 +4355,59 @@ scanfunc_ino(
4a5a34
 			return;
4a5a34
 		}
4a5a34
 		rp = XFS_INOBT_REC_ADDR(mp, block, 1);
4a5a34
-		sparse = xfs_sb_version_hassparseinodes(&mp->m_sb);
4a5a34
-		crc = xfs_sb_version_hascrc(&mp->m_sb);
4a5a34
 		for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) {
4a5a34
-			nfree = 0;
4a5a34
-
4a5a34
-			/* First let's look at the inode chunk alignment */
4a5a34
 			agino = be32_to_cpu(rp[i].ir_startino);
4a5a34
 			off = XFS_INO_TO_OFFSET(mp, agino);
4a5a34
-			if (off == 0 &&
4a5a34
-			    (sbversion & XFS_SB_VERSION_ALIGNBIT) &&
4a5a34
-			    mp->m_sb.sb_inoalignmt &&
4a5a34
-			    (XFS_INO_TO_AGBNO(mp, agino) %
4a5a34
-			     mp->m_sb.sb_inoalignmt)) {
4a5a34
-				if (sparse || crc) {
4a5a34
-					dbprintf(_("incorrect record %u/%u "
4a5a34
-						 "alignment in inobt block "
4a5a34
-						 "%u/%u\n"),
4a5a34
-						 seqno, agino, seqno, bno);
4a5a34
-					error++;
4a5a34
-				} else
4a5a34
+			if (off == 0) {
4a5a34
+				if ((sbversion & XFS_SB_VERSION_ALIGNBIT) &&
4a5a34
+				    mp->m_sb.sb_inoalignmt &&
4a5a34
+				    (XFS_INO_TO_AGBNO(mp, agino) %
4a5a34
+				     mp->m_sb.sb_inoalignmt))
4a5a34
 					sbversion &= ~XFS_SB_VERSION_ALIGNBIT;
4a5a34
+				set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino),
4a5a34
+					(xfs_extlen_t)MAX(1,
4a5a34
+						XFS_INODES_PER_CHUNK >>
4a5a34
+						mp->m_sb.sb_inopblog),
4a5a34
+					DBM_INODE, seqno, bno);
4a5a34
 			}
4a5a34
-
4a5a34
-			/* Move on to examining the inode chunks */
4a5a34
-			if (sparse) {
4a5a34
-				inodes_per_chunk = rp[i].ir_u.sp.ir_count;
4a5a34
-				freecount = rp[i].ir_u.sp.ir_freecount;
4a5a34
-				holemask = be16_to_cpu(rp[i].ir_u.sp.ir_holemask);
4a5a34
-				startidx = find_zero_ino_bit(holemask, 0);
4a5a34
-			} else {
4a5a34
-				inodes_per_chunk = XFS_INODES_PER_CHUNK;
4a5a34
-				freecount = be32_to_cpu(rp[i].ir_u.f.ir_freecount);
4a5a34
-				holemask = 0;
4a5a34
-				startidx = 0;
4a5a34
-			}
4a5a34
-
4a5a34
-			/* For each allocated chunk, look at each inode. */
4a5a34
-			endidx = find_one_ino_bit(holemask, startidx);
4a5a34
-			do {
4a5a34
-				rino = agino + startidx;
4a5a34
-				cblocks = (endidx - startidx) >>
4a5a34
-						mp->m_sb.sb_inopblog;
4a5a34
-
4a5a34
-				/* Check the sparse chunk alignment */
4a5a34
-				if (sparse &&
4a5a34
-				    (XFS_INO_TO_AGBNO(mp, rino) %
4a5a34
-				     mp->m_sb.sb_spino_align)) {
4a5a34
-					dbprintf(_("incorrect chunk %u/%u "
4a5a34
-						 "alignment in inobt block "
4a5a34
+			icount += XFS_INODES_PER_CHUNK;
4a5a34
+			agicount += XFS_INODES_PER_CHUNK;
4a5a34
+			ifree += be32_to_cpu(rp[i].ir_u.f.ir_freecount);
4a5a34
+			agifreecount += be32_to_cpu(rp[i].ir_u.f.ir_freecount);
4a5a34
+			push_cur();
4a5a34
+			set_cur(&typtab[TYP_INODE],
4a5a34
+				XFS_AGB_TO_DADDR(mp, seqno,
4a5a34
+						 XFS_AGINO_TO_AGBNO(mp, agino)),
4a5a34
+				(int)XFS_FSB_TO_BB(mp, mp->m_ialloc_blks),
4a5a34
+				DB_RING_IGN, NULL);
4a5a34
+			if (iocur_top->data == NULL) {
4a5a34
+				if (!sflag)
4a5a34
+					dbprintf(_("can't read inode block "
4a5a34
 						 "%u/%u\n"),
4a5a34
-						 seqno, rino, seqno, bno);
4a5a34
-					error++;
4a5a34
-				}
4a5a34
-
4a5a34
-				/* Check the block map */
4a5a34
-				set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, rino),
4a5a34
-					cblocks, DBM_INODE, seqno, bno);
4a5a34
-
4a5a34
-				push_cur();
4a5a34
-				set_cur(&typtab[TYP_INODE],
4a5a34
-					XFS_AGB_TO_DADDR(mp, seqno,
4a5a34
-							 XFS_AGINO_TO_AGBNO(mp, rino)),
4a5a34
-					(int)XFS_FSB_TO_BB(mp, cblocks),
4a5a34
-					DB_RING_IGN, NULL);
4a5a34
-				if (iocur_top->data == NULL) {
4a5a34
-					if (!sflag)
4a5a34
-						dbprintf(_("can't read inode block "
4a5a34
-							 "%u/%u\n"),
4a5a34
-							seqno,
4a5a34
-							XFS_AGINO_TO_AGBNO(mp, agino));
4a5a34
-					error++;
4a5a34
-					pop_cur();
4a5a34
-					continue;
4a5a34
-				}
4a5a34
-
4a5a34
-				/* Examine each inode in this chunk */
4a5a34
-				for (j = startidx; j < endidx; j++) {
4a5a34
-					if (ino_issparse(&rp[i], j))
4a5a34
-						continue;
4a5a34
-					isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j);
4a5a34
-					if (isfree)
4a5a34
-						nfree++;
4a5a34
-					process_inode(agf, agino + j,
4a5a34
-						(xfs_dinode_t *)((char *)iocur_top->data + ((j - startidx) << mp->m_sb.sb_inodelog)),
4a5a34
-							isfree);
4a5a34
-				}
4a5a34
+						seqno,
4a5a34
+						XFS_AGINO_TO_AGBNO(mp, agino));
4a5a34
+				error++;
4a5a34
 				pop_cur();
4a5a34
-
4a5a34
-				startidx = find_zero_ino_bit(holemask, endidx);
4a5a34
-				endidx = find_one_ino_bit(holemask, startidx);
4a5a34
-			} while (endidx < XFS_INODES_PER_CHUNK);
4a5a34
-			icount += inodes_per_chunk;
4a5a34
-			agicount += inodes_per_chunk;
4a5a34
-			ifree += freecount;
4a5a34
-			agifreecount += freecount;
4a5a34
-
4a5a34
-			if (nfree != freecount) {
4a5a34
+				continue;
4a5a34
+			}
4a5a34
+			for (j = 0, nfree = 0; j < XFS_INODES_PER_CHUNK; j++) {
4a5a34
+				isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j);
4a5a34
+				if (isfree)
4a5a34
+					nfree++;
4a5a34
+				process_inode(agf, agino + j,
4a5a34
+					(xfs_dinode_t *)((char *)iocur_top->data + ((off + j) << mp->m_sb.sb_inodelog)),
4a5a34
+						isfree);
4a5a34
+			}
4a5a34
+			if (nfree != be32_to_cpu(rp[i].ir_u.f.ir_freecount)) {
4a5a34
 				if (!sflag)
4a5a34
 					dbprintf(_("ir_freecount/free mismatch, "
4a5a34
 						 "inode chunk %u/%u, freecount "
4a5a34
 						 "%d nfree %d\n"),
4a5a34
 						seqno, agino,
4a5a34
-						freecount, nfree);
4a5a34
+						be32_to_cpu(rp[i].ir_u.f.ir_freecount), nfree);
4a5a34
 				error++;
4a5a34
 			}
4a5a34
+			pop_cur();
4a5a34
 		}
4a5a34
 		return;
4a5a34
 	}
4a5a34
@@ -4543,11 +4439,6 @@ scanfunc_fino(
4a5a34
 	int			off;
4a5a34
 	xfs_inobt_ptr_t		*pp;
4a5a34
 	struct xfs_inobt_rec	*rp;
4a5a34
-	bool			sparse, crc;
4a5a34
-	int			startidx, endidx;
4a5a34
-	__u16			holemask;
4a5a34
-	xfs_agino_t		rino;
4a5a34
-	xfs_extlen_t		cblocks;
4a5a34
 
4a5a34
 	if (be32_to_cpu(block->bb_magic) != XFS_FIBT_MAGIC &&
4a5a34
 	    be32_to_cpu(block->bb_magic) != XFS_FIBT_CRC_MAGIC) {
4a5a34
@@ -4575,63 +4466,21 @@ scanfunc_fino(
4a5a34
 			return;
4a5a34
 		}
4a5a34
 		rp = XFS_INOBT_REC_ADDR(mp, block, 1);
4a5a34
-		sparse = xfs_sb_version_hassparseinodes(&mp->m_sb);
4a5a34
-		crc = xfs_sb_version_hascrc(&mp->m_sb);
4a5a34
 		for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) {
4a5a34
-			/* First let's look at the inode chunk alignment */
4a5a34
 			agino = be32_to_cpu(rp[i].ir_startino);
4a5a34
 			off = XFS_INO_TO_OFFSET(mp, agino);
4a5a34
-			if (off == 0 &&
4a5a34
-			    (sbversion & XFS_SB_VERSION_ALIGNBIT) &&
4a5a34
-			    mp->m_sb.sb_inoalignmt &&
4a5a34
-			    (XFS_INO_TO_AGBNO(mp, agino) %
4a5a34
-			     mp->m_sb.sb_inoalignmt)) {
4a5a34
-				if (sparse || crc) {
4a5a34
-					dbprintf(_("incorrect record %u/%u "
4a5a34
-						 "alignment in finobt block "
4a5a34
-						 "%u/%u\n"),
4a5a34
-						 seqno, agino, seqno, bno);
4a5a34
-					error++;
4a5a34
-				} else
4a5a34
+			if (off == 0) {
4a5a34
+				if ((sbversion & XFS_SB_VERSION_ALIGNBIT) &&
4a5a34
+				    mp->m_sb.sb_inoalignmt &&
4a5a34
+				    (XFS_INO_TO_AGBNO(mp, agino) %
4a5a34
+				     mp->m_sb.sb_inoalignmt))
4a5a34
 					sbversion &= ~XFS_SB_VERSION_ALIGNBIT;
4a5a34
+				check_set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino),
4a5a34
+					(xfs_extlen_t)MAX(1,
4a5a34
+						XFS_INODES_PER_CHUNK >>
4a5a34
+						mp->m_sb.sb_inopblog),
4a5a34
+					DBM_INODE, DBM_INODE, seqno, bno);
4a5a34
 			}
4a5a34
-
4a5a34
-			/* Move on to examining the inode chunks */
4a5a34
-			if (sparse) {
4a5a34
-				holemask = be16_to_cpu(rp[i].ir_u.sp.ir_holemask);
4a5a34
-				startidx = find_zero_ino_bit(holemask, 0);
4a5a34
-			} else {
4a5a34
-				holemask = 0;
4a5a34
-				startidx = 0;
4a5a34
-			}
4a5a34
-
4a5a34
-			/* For each allocated chunk... */
4a5a34
-			endidx = find_one_ino_bit(holemask, startidx);
4a5a34
-			do {
4a5a34
-				rino = agino + startidx;
4a5a34
-				cblocks = (endidx - startidx) >>
4a5a34
-						mp->m_sb.sb_inopblog;
4a5a34
-
4a5a34
-				/* Check the sparse chunk alignment */
4a5a34
-				if (sparse &&
4a5a34
-				    (XFS_INO_TO_AGBNO(mp, rino) %
4a5a34
-				     mp->m_sb.sb_spino_align)) {
4a5a34
-					dbprintf(_("incorrect chunk %u/%u "
4a5a34
-						 "alignment in finobt block "
4a5a34
-						 "%u/%u\n"),
4a5a34
-						 seqno, rino, seqno, bno);
4a5a34
-					error++;
4a5a34
-				}
4a5a34
-
4a5a34
-				/* Check the block map */
4a5a34
-				check_set_dbmap(seqno,
4a5a34
-					XFS_AGINO_TO_AGBNO(mp, rino),
4a5a34
-					cblocks, DBM_INODE, DBM_INODE,
4a5a34
-					seqno, bno);
4a5a34
-
4a5a34
-				startidx = find_zero_ino_bit(holemask, endidx);
4a5a34
-				endidx = find_one_ino_bit(holemask, startidx);
4a5a34
-			} while (endidx < XFS_INODES_PER_CHUNK);
4a5a34
 		}
4a5a34
 		return;
4a5a34
 	}