Commit c0d5a92f authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: split xchk_bmap_xref_rmap into two functions

There's more special-cased functionality than not in this function.
Split it into two so that each can be far more cohesive.
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
parent 634d4a79
...@@ -165,7 +165,7 @@ xchk_bmap_get_rmap( ...@@ -165,7 +165,7 @@ xchk_bmap_get_rmap(
return has_rmap; return has_rmap;
} }
/* Make sure that we have rmapbt records for this extent. */ /* Make sure that we have rmapbt records for this data/attr fork extent. */
STATIC void STATIC void
xchk_bmap_xref_rmap( xchk_bmap_xref_rmap(
struct xchk_bmap_info *info, struct xchk_bmap_info *info,
...@@ -174,41 +174,39 @@ xchk_bmap_xref_rmap( ...@@ -174,41 +174,39 @@ xchk_bmap_xref_rmap(
{ {
struct xfs_rmap_irec rmap; struct xfs_rmap_irec rmap;
unsigned long long rmap_end; unsigned long long rmap_end;
uint64_t owner; uint64_t owner = info->sc->ip->i_ino;
if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm)) if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm))
return; return;
if (info->whichfork == XFS_COW_FORK)
owner = XFS_RMAP_OWN_COW;
else
owner = info->sc->ip->i_ino;
/* Find the rmap record for this irec. */ /* Find the rmap record for this irec. */
if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap)) if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap))
return; return;
/* Check the rmap. */ /*
* The rmap must be an exact match for this incore file mapping record,
* which may have arisen from multiple ondisk records.
*/
if (rmap.rm_startblock != agbno)
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount; rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
if (rmap.rm_startblock > agbno || if (rmap_end != agbno + irec->br_blockcount)
agbno + irec->br_blockcount > rmap_end)
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff); irec->br_startoff);
/* /* Check the logical offsets. */
* Check the logical offsets if applicable. CoW staging extents if (rmap.rm_offset != irec->br_startoff)
* don't track logical offsets since the mappings only exist in xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
* memory. irec->br_startoff);
*/
if (info->whichfork != XFS_COW_FORK) { rmap_end = (unsigned long long)rmap.rm_offset + rmap.rm_blockcount;
rmap_end = (unsigned long long)rmap.rm_offset + if (rmap_end != irec->br_startoff + irec->br_blockcount)
rmap.rm_blockcount; xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
if (rmap.rm_offset > irec->br_startoff || irec->br_startoff);
irec->br_startoff + irec->br_blockcount > rmap_end)
xchk_fblock_xref_set_corrupt(info->sc,
info->whichfork, irec->br_startoff);
}
/* Check the owner */
if (rmap.rm_owner != owner) if (rmap.rm_owner != owner)
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff); irec->br_startoff);
...@@ -220,8 +218,7 @@ xchk_bmap_xref_rmap( ...@@ -220,8 +218,7 @@ xchk_bmap_xref_rmap(
* records because the blocks are owned (on-disk) by the refcountbt, * records because the blocks are owned (on-disk) by the refcountbt,
* which doesn't track unwritten state. * which doesn't track unwritten state.
*/ */
if (owner != XFS_RMAP_OWN_COW && if (!!(irec->br_state == XFS_EXT_UNWRITTEN) !=
!!(irec->br_state == XFS_EXT_UNWRITTEN) !=
!!(rmap.rm_flags & XFS_RMAP_UNWRITTEN)) !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN))
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff); irec->br_startoff);
...@@ -233,23 +230,60 @@ xchk_bmap_xref_rmap( ...@@ -233,23 +230,60 @@ xchk_bmap_xref_rmap(
if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK) if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff); irec->br_startoff);
}
/* Make sure that we have rmapbt records for this COW fork extent. */
STATIC void
xchk_bmap_xref_rmap_cow(
struct xchk_bmap_info *info,
struct xfs_bmbt_irec *irec,
xfs_agblock_t agbno)
{
struct xfs_rmap_irec rmap;
unsigned long long rmap_end;
uint64_t owner = XFS_RMAP_OWN_COW;
if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm))
return;
/* Find the rmap record for this irec. */
if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap))
return;
/* /*
* The rmap must correspond exactly with this bmbt record. Skip this * CoW staging extents are owned by the refcount btree, so the rmap
* for CoW fork extents because the refcount btree (and not the inode) * can start before and end after the physical space allocated to this
* is the ondisk owner for those extents. * mapping. There are no offsets to check.
*/ */
if (info->whichfork != XFS_COW_FORK) { if (rmap.rm_startblock > agbno)
if (rmap.rm_startblock != agbno) xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, irec->br_startoff);
irec->br_startoff);
rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
rmap_end = (unsigned long long)rmap.rm_startblock + if (rmap_end < agbno + irec->br_blockcount)
rmap.rm_blockcount; xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
if (rmap_end != agbno + irec->br_blockcount) irec->br_startoff);
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff); /* Check the owner */
} if (rmap.rm_owner != owner)
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
/*
* No flags allowed. Note that the (in-memory) CoW fork distinguishes
* between unwritten and written extents, but we don't track that in
* the rmap records because the blocks are owned (on-disk) by the
* refcountbt, which doesn't track unwritten state.
*/
if (rmap.rm_flags & XFS_RMAP_ATTR_FORK)
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
if (rmap.rm_flags & XFS_RMAP_UNWRITTEN)
xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
irec->br_startoff);
} }
/* Cross-reference a single rtdev extent record. */ /* Cross-reference a single rtdev extent record. */
...@@ -288,9 +322,9 @@ xchk_bmap_iextent_xref( ...@@ -288,9 +322,9 @@ xchk_bmap_iextent_xref(
xchk_xref_is_used_space(info->sc, agbno, len); xchk_xref_is_used_space(info->sc, agbno, len);
xchk_xref_is_not_inode_chunk(info->sc, agbno, len); xchk_xref_is_not_inode_chunk(info->sc, agbno, len);
xchk_bmap_xref_rmap(info, irec, agbno);
switch (info->whichfork) { switch (info->whichfork) {
case XFS_DATA_FORK: case XFS_DATA_FORK:
xchk_bmap_xref_rmap(info, irec, agbno);
if (!xfs_is_reflink_inode(info->sc->ip)) { if (!xfs_is_reflink_inode(info->sc->ip)) {
xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino, xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
info->whichfork, irec->br_startoff); info->whichfork, irec->br_startoff);
...@@ -303,6 +337,7 @@ xchk_bmap_iextent_xref( ...@@ -303,6 +337,7 @@ xchk_bmap_iextent_xref(
irec->br_blockcount); irec->br_blockcount);
break; break;
case XFS_ATTR_FORK: case XFS_ATTR_FORK:
xchk_bmap_xref_rmap(info, irec, agbno);
xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino, xfs_rmap_ino_owner(&oinfo, info->sc->ip->i_ino,
info->whichfork, irec->br_startoff); info->whichfork, irec->br_startoff);
xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount, xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
...@@ -313,6 +348,7 @@ xchk_bmap_iextent_xref( ...@@ -313,6 +348,7 @@ xchk_bmap_iextent_xref(
irec->br_blockcount); irec->br_blockcount);
break; break;
case XFS_COW_FORK: case XFS_COW_FORK:
xchk_bmap_xref_rmap_cow(info, irec, agbno);
xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount, xchk_xref_is_only_owned_by(info->sc, agbno, irec->br_blockcount,
&XFS_RMAP_OINFO_COW); &XFS_RMAP_OINFO_COW);
xchk_xref_is_cow_staging(info->sc, agbno, xchk_xref_is_cow_staging(info->sc, agbno,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment