xfs: scrub big block inode btrees correctly

Teach scrub how to handle the case that there are one or more inobt
records covering a given inode cluster.  This fixes the operation on big
block filesystems (e.g. 64k blocks, 512 byte inodes).

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
This commit is contained in:
Darrick J. Wong 2019-02-01 09:08:52 -08:00
parent b9454fe056
commit 4539b8a780
1 changed files with 9 additions and 1 deletions

View File

@ -162,6 +162,7 @@ xchk_iallocbt_check_cluster_ifree(
xfs_ino_t fsino;
xfs_agino_t agino;
unsigned int offset;
unsigned int cluster_buf_base;
bool irec_free;
bool ino_inuse;
bool freemask_ok;
@ -174,10 +175,17 @@ xchk_iallocbt_check_cluster_ifree(
* Given an inobt record, an offset of a cluster within the record, and
* an offset of an inode within a cluster, compute which fs inode we're
* talking about and the offset of that inode within the buffer.
*
* Be careful about inobt records that don't align with the start of
* the inode buffer when block sizes are large enough to hold multiple
* inode chunks. When this happens, cluster_base will be zero but
* ir_startino can be large enough to make cluster_buf_base nonzero.
*/
agino = irec->ir_startino + cluster_base + cluster_index;
fsino = XFS_AGINO_TO_INO(mp, bs->cur->bc_private.a.agno, agino);
offset = cluster_index * mp->m_sb.sb_inodesize;
cluster_buf_base = XFS_INO_TO_OFFSET(mp, irec->ir_startino);
ASSERT(cluster_buf_base == 0 || cluster_base == 0);
offset = (cluster_buf_base + cluster_index) * mp->m_sb.sb_inodesize;
if (offset >= BBTOB(cluster_bp->b_length)) {
xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
goto out;