You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
341 lines
9.6 KiB
341 lines
9.6 KiB
commit 09c93e56b5296a30507cde9c00433eb4ed2d395d |
|
Author: Brian Foster <bfoster@redhat.com> |
|
Date: Tue Jun 21 12:58:57 2016 +1000 |
|
|
|
xfs_db: Revert "xfs_db: make check work for sparse inodes" |
|
|
|
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> |
|
|
|
diff --git a/db/check.c b/db/check.c |
|
index 0871ed7..750ecc1 100644 |
|
--- a/db/check.c |
|
+++ b/db/check.c |
|
@@ -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; |
|
}
|
|
|