Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: count inode blocks correctly in inobt scrub

A big block filesystem might require more than one inobt record to cover
all the inodes in the block. In these cases it is not correct to round
the irec count up to the nearest block because this causes us to
overestimate the number of inode blocks we expect to find.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>

+15 -7
+15 -7
fs/xfs/scrub/ialloc.c
··· 44 44 45 45 /* Inode btree scrubber. */ 46 46 47 + struct xchk_iallocbt { 48 + /* Number of inodes we see while scanning inobt. */ 49 + unsigned long long inodes; 50 + }; 51 + 47 52 /* 48 53 * If we're checking the finobt, cross-reference with the inobt. 49 54 * Otherwise we're checking the inobt; if there is an finobt, make sure ··· 271 266 union xfs_btree_rec *rec) 272 267 { 273 268 struct xfs_mount *mp = bs->cur->bc_mp; 274 - xfs_filblks_t *inode_blocks = bs->private; 269 + struct xchk_iallocbt *iabt = bs->private; 275 270 struct xfs_inobt_rec_incore irec; 276 271 uint64_t holes; 277 272 xfs_agnumber_t agno = bs->cur->bc_private.a.agno; ··· 309 304 (agbno & (mp->m_blocks_per_cluster - 1))) 310 305 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 311 306 312 - *inode_blocks += XFS_B_TO_FSB(mp, 313 - irec.ir_count * mp->m_sb.sb_inodesize); 307 + iabt->inodes += irec.ir_count; 314 308 315 309 /* Handle non-sparse inodes */ 316 310 if (!xfs_inobt_issparse(irec.ir_holemask)) { ··· 401 397 xchk_iallocbt_xref_rmap_inodes( 402 398 struct xfs_scrub *sc, 403 399 int which, 404 - xfs_filblks_t inode_blocks) 400 + unsigned long long inodes) 405 401 { 406 402 xfs_filblks_t blocks; 403 + xfs_filblks_t inode_blocks; 407 404 int error; 408 405 409 406 if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm)) ··· 415 410 &XFS_RMAP_OINFO_INODES, &blocks); 416 411 if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) 417 412 return; 413 + inode_blocks = XFS_B_TO_FSB(sc->mp, inodes * sc->mp->m_sb.sb_inodesize); 418 414 if (blocks != inode_blocks) 419 415 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); 420 416 } ··· 427 421 xfs_btnum_t which) 428 422 { 429 423 struct xfs_btree_cur *cur; 430 - xfs_filblks_t inode_blocks = 0; 424 + struct xchk_iallocbt iabt = { 425 + .inodes = 0, 426 + }; 431 427 int error; 432 428 433 429 cur = which == XFS_BTNUM_INO ? sc->sa.ino_cur : sc->sa.fino_cur; 434 430 error = xchk_btree(sc, cur, xchk_iallocbt_rec, &XFS_RMAP_OINFO_INOBT, 435 - &inode_blocks); 431 + &iabt); 436 432 if (error) 437 433 return error; 438 434 ··· 448 440 * to inode chunks with free inodes. 449 441 */ 450 442 if (which == XFS_BTNUM_INO) 451 - xchk_iallocbt_xref_rmap_inodes(sc, which, inode_blocks); 443 + xchk_iallocbt_xref_rmap_inodes(sc, which, iabt.inodes); 452 444 453 445 return error; 454 446 }