[PATCH] xfs_db: make check work for sparse inodes
Darrick J. Wong
darrick.wong at oracle.com
Fri Dec 4 14:26:06 CST 2015
Teach the inobt/finobt scanning functions how to deal with sparse
inode chunks well enough that we can pass the spot-check. Should
fix the xfs/076 failures.
Signed-off-by: Darrick J. Wong <darrick.wong at oracle.com>
---
db/check.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 75 insertions(+), 15 deletions(-)
diff --git a/db/check.c b/db/check.c
index 9c1541d..14c7de5 100644
--- a/db/check.c
+++ b/db/check.c
@@ -4319,6 +4319,30 @@ 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_first_zero_bit(
+ unsigned long mask)
+{
+ int n;
+ int b = 0;
+
+ for (n = 0; n < sizeof(mask) * NBBY && (mask & 1); n++, mask >>= 1)
+ b++;
+
+ return b;
+}
+
static void
scanfunc_ino(
struct xfs_btree_block *block,
@@ -4336,6 +4360,10 @@ scanfunc_ino(
int off;
xfs_inobt_ptr_t *pp;
xfs_inobt_rec_t *rp;
+ bool sparse;
+ int inodes_per_chunk;
+ int freecount;
+ int startidx;
if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC &&
be32_to_cpu(block->bb_magic) != XFS_IBT_CRC_MAGIC) {
@@ -4364,29 +4392,44 @@ scanfunc_ino(
}
rp = XFS_INOBT_REC_ADDR(mp, block, 1);
for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) {
- agino = be32_to_cpu(rp[i].ir_startino);
+ sparse = xfs_sb_version_hassparseinodes(&mp->m_sb);
+ if (sparse) {
+ unsigned long holemask;
+
+ 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_first_zero_bit(holemask) * XFS_INODES_PER_HOLEMASK_BIT;
+ } else {
+ inodes_per_chunk = XFS_INODES_PER_CHUNK;
+ freecount = be32_to_cpu(rp[i].ir_u.f.ir_freecount);
+ startidx = 0;
+ }
+ agino = be32_to_cpu(rp[i].ir_startino) + startidx;
off = XFS_INO_TO_OFFSET(mp, agino);
if (off == 0) {
- if ((sbversion & XFS_SB_VERSION_ALIGNBIT) &&
+ if (!sparse &&
+ (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 >>
+ inodes_per_chunk >>
mp->m_sb.sb_inopblog),
DBM_INODE, seqno, bno);
}
- 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);
+ icount += inodes_per_chunk;
+ agicount += inodes_per_chunk;
+ ifree += freecount;
+ agifreecount += 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),
+ (int)XFS_FSB_TO_BB(mp, inodes_per_chunk >>
+ mp->m_sb.sb_inopblog),
DB_RING_IGN, NULL);
if (iocur_top->data == NULL) {
if (!sflag)
@@ -4399,20 +4442,22 @@ scanfunc_ino(
continue;
}
for (j = 0, nfree = 0; j < XFS_INODES_PER_CHUNK; 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 + ((off + j) << mp->m_sb.sb_inodelog)),
+ process_inode(agf, agino - startidx + j,
+ (xfs_dinode_t *)((char *)iocur_top->data + ((off - startidx + j) << mp->m_sb.sb_inodelog)),
isfree);
}
- if (nfree != be32_to_cpu(rp[i].ir_u.f.ir_freecount)) {
+ if (nfree != freecount) {
if (!sflag)
dbprintf(_("ir_freecount/free mismatch, "
"inode chunk %u/%u, freecount "
"%d nfree %d\n"),
seqno, agino,
- be32_to_cpu(rp[i].ir_u.f.ir_freecount), nfree);
+ freecount, nfree);
error++;
}
pop_cur();
@@ -4447,6 +4492,9 @@ scanfunc_fino(
int off;
xfs_inobt_ptr_t *pp;
struct xfs_inobt_rec *rp;
+ bool sparse;
+ int inodes_per_chunk;
+ int startidx;
if (be32_to_cpu(block->bb_magic) != XFS_FIBT_MAGIC &&
be32_to_cpu(block->bb_magic) != XFS_FIBT_CRC_MAGIC) {
@@ -4475,17 +4523,29 @@ scanfunc_fino(
}
rp = XFS_INOBT_REC_ADDR(mp, block, 1);
for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) {
- agino = be32_to_cpu(rp[i].ir_startino);
+ sparse = xfs_sb_version_hassparseinodes(&mp->m_sb);
+ if (sparse) {
+ unsigned long holemask;
+
+ inodes_per_chunk = rp[i].ir_u.sp.ir_count;
+ holemask = be16_to_cpu(rp[i].ir_u.sp.ir_holemask);
+ startidx = find_first_zero_bit(holemask) * XFS_INODES_PER_HOLEMASK_BIT;
+ } else {
+ inodes_per_chunk = XFS_INODES_PER_CHUNK;
+ startidx = 0;
+ }
+ agino = be32_to_cpu(rp[i].ir_startino) + startidx;
off = XFS_INO_TO_OFFSET(mp, agino);
if (off == 0) {
- if ((sbversion & XFS_SB_VERSION_ALIGNBIT) &&
+ if (!sparse &&
+ (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 >>
+ inodes_per_chunk >>
mp->m_sb.sb_inopblog),
DBM_INODE, DBM_INODE, seqno, bno);
}
More information about the xfs
mailing list