]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_db: Revert "xfs_db: make check work for sparse inodes"
authorBrian Foster <bfoster@redhat.com>
Tue, 21 Jun 2016 02:58:57 +0000 (12:58 +1000)
committerDave Chinner <david@fromorbit.com>
Tue, 21 Jun 2016 02:58:57 +0000 (12:58 +1000)
This reverts commit bb2f98b78f20f4abbfbbd442162d9f535c84888a which
introduced support for multi-record inode chunks in
xfs_db/xfs_check. However, it doesn't currently handle filesystems
with multi-record inode chunks correctly. For example, do the
following on a 64k page size arch such as ppc64:

# mkfs.xfs -f -b size=64k <dev>
# xfs_db -c check <dev>
bad magic number 0 for inode 1152
bad magic number 0 for inode 1153
bad magic number 0 for inode 1154
bad magic number 0 for inode 1155
bad magic number 0 for inode 1156
bad magic number 0 for inode 1157
...

This boils down to a regression in the inode record processing code
(scanfunc_ino()) in db/check.c. Specifically, the cblocks value can
end up being zero after it is shifted by mp->m_sb.sb_inopblog (i.e.,
64 >> 7 == 0 for an -isize=512 -bsize=64k fs).

Fixing this problem is easier to do from scratch, so revert the
oringial commit first.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
db/check.c

index 0871ed792e06fb7a4b7b82bfc7097b32213ea89e..750ecc1e44d7f615bcb51b8e33e58a6bfedeb209 100644 (file)
@@ -4311,51 +4311,6 @@ scanfunc_cnt(
                scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_cnt, TYP_CNTBT);
 }
 
-static bool
-ino_issparse(
-       struct xfs_inobt_rec    *rp,
-       int                     offset)
-{
-       if (!xfs_sb_version_hassparseinodes(&mp->m_sb))
-               return false;
-
-       return xfs_inobt_is_sparse_disk(rp, offset);
-}
-
-static int
-find_one_ino_bit(
-       __u16           mask,
-       int             startino)
-{
-       int             n;
-       int             b;
-
-       startino /= XFS_INODES_PER_HOLEMASK_BIT;
-       b = startino;
-       mask >>= startino;
-       for (n = startino; n < sizeof(mask) * NBBY && !(mask & 1); n++, mask >>= 1)
-               b++;
-
-       return b * XFS_INODES_PER_HOLEMASK_BIT;
-}
-
-static int
-find_zero_ino_bit(
-       __u16           mask,
-       int             startino)
-{
-       int             n;
-       int             b;
-
-       startino /= XFS_INODES_PER_HOLEMASK_BIT;
-       b = startino;
-       mask >>= startino;
-       for (n = startino; n < sizeof(mask) * NBBY && (mask & 1); n++, mask >>= 1)
-               b++;
-
-       return b * XFS_INODES_PER_HOLEMASK_BIT;
-}
-
 static void
 scanfunc_ino(
        struct xfs_btree_block  *block,
@@ -4373,13 +4328,6 @@ scanfunc_ino(
        int                     off;
        xfs_inobt_ptr_t         *pp;
        xfs_inobt_rec_t         *rp;
-       bool                    sparse, crc;
-       int                     inodes_per_chunk;
-       int                     freecount;
-       int                     startidx, endidx;
-       __u16                   holemask;
-       xfs_agino_t             rino;
-       xfs_extlen_t            cblocks;
 
        if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC &&
            be32_to_cpu(block->bb_magic) != XFS_IBT_CRC_MAGIC) {
@@ -4407,111 +4355,59 @@ scanfunc_ino(
                        return;
                }
                rp = XFS_INOBT_REC_ADDR(mp, block, 1);
-               sparse = xfs_sb_version_hassparseinodes(&mp->m_sb);
-               crc = xfs_sb_version_hascrc(&mp->m_sb);
                for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) {
-                       nfree = 0;
-
-                       /* First let's look at the inode chunk alignment */
                        agino = be32_to_cpu(rp[i].ir_startino);
                        off = XFS_INO_TO_OFFSET(mp, agino);
-                       if (off == 0 &&
-                           (sbversion & XFS_SB_VERSION_ALIGNBIT) &&
-                           mp->m_sb.sb_inoalignmt &&
-                           (XFS_INO_TO_AGBNO(mp, agino) %
-                            mp->m_sb.sb_inoalignmt)) {
-                               if (sparse || crc) {
-                                       dbprintf(_("incorrect record %u/%u "
-                                                "alignment in inobt block "
-                                                "%u/%u\n"),
-                                                seqno, agino, seqno, bno);
-                                       error++;
-                               } else
+                       if (off == 0) {
+                               if ((sbversion & XFS_SB_VERSION_ALIGNBIT) &&
+                                   mp->m_sb.sb_inoalignmt &&
+                                   (XFS_INO_TO_AGBNO(mp, agino) %
+                                    mp->m_sb.sb_inoalignmt))
                                        sbversion &= ~XFS_SB_VERSION_ALIGNBIT;
+                               set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino),
+                                       (xfs_extlen_t)MAX(1,
+                                               XFS_INODES_PER_CHUNK >>
+                                               mp->m_sb.sb_inopblog),
+                                       DBM_INODE, seqno, bno);
                        }
-
-                       /* Move on to examining the inode chunks */
-                       if (sparse) {
-                               inodes_per_chunk = rp[i].ir_u.sp.ir_count;
-                               freecount = rp[i].ir_u.sp.ir_freecount;
-                               holemask = be16_to_cpu(rp[i].ir_u.sp.ir_holemask);
-                               startidx = find_zero_ino_bit(holemask, 0);
-                       } else {
-                               inodes_per_chunk = XFS_INODES_PER_CHUNK;
-                               freecount = be32_to_cpu(rp[i].ir_u.f.ir_freecount);
-                               holemask = 0;
-                               startidx = 0;
-                       }
-
-                       /* For each allocated chunk, look at each inode. */
-                       endidx = find_one_ino_bit(holemask, startidx);
-                       do {
-                               rino = agino + startidx;
-                               cblocks = (endidx - startidx) >>
-                                               mp->m_sb.sb_inopblog;
-
-                               /* Check the sparse chunk alignment */
-                               if (sparse &&
-                                   (XFS_INO_TO_AGBNO(mp, rino) %
-                                    mp->m_sb.sb_spino_align)) {
-                                       dbprintf(_("incorrect chunk %u/%u "
-                                                "alignment in inobt block "
+                       icount += XFS_INODES_PER_CHUNK;
+                       agicount += XFS_INODES_PER_CHUNK;
+                       ifree += be32_to_cpu(rp[i].ir_u.f.ir_freecount);
+                       agifreecount += be32_to_cpu(rp[i].ir_u.f.ir_freecount);
+                       push_cur();
+                       set_cur(&typtab[TYP_INODE],
+                               XFS_AGB_TO_DADDR(mp, seqno,
+                                                XFS_AGINO_TO_AGBNO(mp, agino)),
+                               (int)XFS_FSB_TO_BB(mp, mp->m_ialloc_blks),
+                               DB_RING_IGN, NULL);
+                       if (iocur_top->data == NULL) {
+                               if (!sflag)
+                                       dbprintf(_("can't read inode block "
                                                 "%u/%u\n"),
-                                                seqno, rino, seqno, bno);
-                                       error++;
-                               }
-
-                               /* Check the block map */
-                               set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, rino),
-                                       cblocks, DBM_INODE, seqno, bno);
-
-                               push_cur();
-                               set_cur(&typtab[TYP_INODE],
-                                       XFS_AGB_TO_DADDR(mp, seqno,
-                                                        XFS_AGINO_TO_AGBNO(mp, rino)),
-                                       (int)XFS_FSB_TO_BB(mp, cblocks),
-                                       DB_RING_IGN, NULL);
-                               if (iocur_top->data == NULL) {
-                                       if (!sflag)
-                                               dbprintf(_("can't read inode block "
-                                                        "%u/%u\n"),
-                                                       seqno,
-                                                       XFS_AGINO_TO_AGBNO(mp, agino));
-                                       error++;
-                                       pop_cur();
-                                       continue;
-                               }
-
-                               /* Examine each inode in this chunk */
-                               for (j = startidx; j < endidx; j++) {
-                                       if (ino_issparse(&rp[i], j))
-                                               continue;
-                                       isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j);
-                                       if (isfree)
-                                               nfree++;
-                                       process_inode(agf, agino + j,
-                                               (xfs_dinode_t *)((char *)iocur_top->data + ((j - startidx) << mp->m_sb.sb_inodelog)),
-                                                       isfree);
-                               }
+                                               seqno,
+                                               XFS_AGINO_TO_AGBNO(mp, agino));
+                               error++;
                                pop_cur();
-
-                               startidx = find_zero_ino_bit(holemask, endidx);
-                               endidx = find_one_ino_bit(holemask, startidx);
-                       } while (endidx < XFS_INODES_PER_CHUNK);
-                       icount += inodes_per_chunk;
-                       agicount += inodes_per_chunk;
-                       ifree += freecount;
-                       agifreecount += freecount;
-
-                       if (nfree != freecount) {
+                               continue;
+                       }
+                       for (j = 0, nfree = 0; j < XFS_INODES_PER_CHUNK; j++) {
+                               isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j);
+                               if (isfree)
+                                       nfree++;
+                               process_inode(agf, agino + j,
+                                       (xfs_dinode_t *)((char *)iocur_top->data + ((off + j) << mp->m_sb.sb_inodelog)),
+                                               isfree);
+                       }
+                       if (nfree != be32_to_cpu(rp[i].ir_u.f.ir_freecount)) {
                                if (!sflag)
                                        dbprintf(_("ir_freecount/free mismatch, "
                                                 "inode chunk %u/%u, freecount "
                                                 "%d nfree %d\n"),
                                                seqno, agino,
-                                               freecount, nfree);
+                                               be32_to_cpu(rp[i].ir_u.f.ir_freecount), nfree);
                                error++;
                        }
+                       pop_cur();
                }
                return;
        }
@@ -4543,11 +4439,6 @@ scanfunc_fino(
        int                     off;
        xfs_inobt_ptr_t         *pp;
        struct xfs_inobt_rec    *rp;
-       bool                    sparse, crc;
-       int                     startidx, endidx;
-       __u16                   holemask;
-       xfs_agino_t             rino;
-       xfs_extlen_t            cblocks;
 
        if (be32_to_cpu(block->bb_magic) != XFS_FIBT_MAGIC &&
            be32_to_cpu(block->bb_magic) != XFS_FIBT_CRC_MAGIC) {
@@ -4575,63 +4466,21 @@ scanfunc_fino(
                        return;
                }
                rp = XFS_INOBT_REC_ADDR(mp, block, 1);
-               sparse = xfs_sb_version_hassparseinodes(&mp->m_sb);
-               crc = xfs_sb_version_hascrc(&mp->m_sb);
                for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) {
-                       /* First let's look at the inode chunk alignment */
                        agino = be32_to_cpu(rp[i].ir_startino);
                        off = XFS_INO_TO_OFFSET(mp, agino);
-                       if (off == 0 &&
-                           (sbversion & XFS_SB_VERSION_ALIGNBIT) &&
-                           mp->m_sb.sb_inoalignmt &&
-                           (XFS_INO_TO_AGBNO(mp, agino) %
-                            mp->m_sb.sb_inoalignmt)) {
-                               if (sparse || crc) {
-                                       dbprintf(_("incorrect record %u/%u "
-                                                "alignment in finobt block "
-                                                "%u/%u\n"),
-                                                seqno, agino, seqno, bno);
-                                       error++;
-                               } else
+                       if (off == 0) {
+                               if ((sbversion & XFS_SB_VERSION_ALIGNBIT) &&
+                                   mp->m_sb.sb_inoalignmt &&
+                                   (XFS_INO_TO_AGBNO(mp, agino) %
+                                    mp->m_sb.sb_inoalignmt))
                                        sbversion &= ~XFS_SB_VERSION_ALIGNBIT;
+                               check_set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino),
+                                       (xfs_extlen_t)MAX(1,
+                                               XFS_INODES_PER_CHUNK >>
+                                               mp->m_sb.sb_inopblog),
+                                       DBM_INODE, DBM_INODE, seqno, bno);
                        }
-
-                       /* Move on to examining the inode chunks */
-                       if (sparse) {
-                               holemask = be16_to_cpu(rp[i].ir_u.sp.ir_holemask);
-                               startidx = find_zero_ino_bit(holemask, 0);
-                       } else {
-                               holemask = 0;
-                               startidx = 0;
-                       }
-
-                       /* For each allocated chunk... */
-                       endidx = find_one_ino_bit(holemask, startidx);
-                       do {
-                               rino = agino + startidx;
-                               cblocks = (endidx - startidx) >>
-                                               mp->m_sb.sb_inopblog;
-
-                               /* Check the sparse chunk alignment */
-                               if (sparse &&
-                                   (XFS_INO_TO_AGBNO(mp, rino) %
-                                    mp->m_sb.sb_spino_align)) {
-                                       dbprintf(_("incorrect chunk %u/%u "
-                                                "alignment in finobt block "
-                                                "%u/%u\n"),
-                                                seqno, rino, seqno, bno);
-                                       error++;
-                               }
-
-                               /* Check the block map */
-                               check_set_dbmap(seqno,
-                                       XFS_AGINO_TO_AGBNO(mp, rino),
-                                       cblocks, DBM_INODE, DBM_INODE,
-                                       seqno, bno);
-
-                               startidx = find_zero_ino_bit(holemask, endidx);
-                               endidx = find_one_ino_bit(holemask, startidx);
-                       } while (endidx < XFS_INODES_PER_CHUNK);
                }
                return;
        }