|
|
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 |
}
|