On Tue, Jan 16, 2018 at 01:44:47PM +1100, Dave Chinner wrote: > On Tue, Jan 09, 2018 at 01:25:47PM -0800, Darrick J. Wong wrote: > > From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > > > During metadata btree scrub, we should cross-reference with the > > reference counts. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > --- > > v2: streamline scrubber arguments, remove stack allocated objects > > --- > > .... > > > +/* Make sure the refcount records match this data fork extent. */ > > +STATIC void > > +xfs_scrub_bmap_xref_refcount_data( > > + struct xfs_scrub_bmap_info *info, > > + struct xfs_bmbt_irec *irec, > > + xfs_fsblock_t bno) > > What's in the irec if it's not the block number of the extent we > are looking up? > > Actually, I may have just answered that myself: bno is actually > an agbno, not an fsbno. So that should be: > > xfs_agblock_t agbno) Er... Yes. Oops, will fix (all of the agbno). > > > +{ > > + xfs_agblock_t fbno; > > + xfs_extlen_t flen; > > + int error; > > + > > + if (!info->sc->sa.refc_cur) > > + return; > > + > > + /* If this is shared, the inode flag must be set. */ > > + error = xfs_refcount_find_shared(info->sc->sa.refc_cur, bno, > > + irec->br_blockcount, &fbno, &flen, false); > > + if (!xfs_scrub_should_check_xref(info->sc, &error, > > + &info->sc->sa.refc_cur)) > > + return; > > + > > + if (flen != 0 && !xfs_is_reflink_inode(info->sc->ip)) > > + xfs_scrub_fblock_xref_set_corrupt(info->sc, info->whichfork, > > + irec->br_startoff); > > So is the block corrupt or is the inode flags corrupt? What > determines the object we mark as corrupt/needing fixing here? Hmm. The reflink iflag is broken here, because the iflag is only supposed to represent a shortcut for "might any of the data fork blocks shared?" Will change to the ino_xref_set_corrupt helper. --D > > +/* Make sure the refcount records match this attr fork extent. */ > > +STATIC void > > +xfs_scrub_bmap_xref_refcount_attr( > > + struct xfs_scrub_bmap_info *info, > > + struct xfs_bmbt_irec *irec, > > + xfs_fsblock_t bno) > > agbno > > > +{ > > + xfs_agblock_t fbno; > > + xfs_extlen_t flen; > > + int error; > > + > > + if (!info->sc->sa.refc_cur) > > + return; > > + > > + /* No shared attr fork extents */ > > + error = xfs_refcount_find_shared(info->sc->sa.refc_cur, bno, > > + irec->br_blockcount, &fbno, &flen, false); > > + if (!xfs_scrub_should_check_xref(info->sc, &error, > > + &info->sc->sa.refc_cur)) > > + return; > > + > > + if (flen != 0) > > + xfs_scrub_fblock_xref_set_corrupt(info->sc, info->whichfork, > > + irec->br_startoff); > > +} > > + > > +/* Make sure the refcount records match this CoW fork extent. */ > > +STATIC void > > +xfs_scrub_bmap_xref_refcount_cow( > > + struct xfs_scrub_bmap_info *info, > > + struct xfs_bmbt_irec *irec, > > + xfs_fsblock_t bno) > > agbno > > > +{ > > + if (!info->sc->sa.refc_cur) > > + return; > > + > > + xfs_scrub_xref_has_cow_staging(info->sc, bno, irec->br_blockcount); > > +} > > + > > /* Cross-reference a single rtdev extent record. */ > > STATIC void > > xfs_scrub_bmap_rt_extent_xref( > > @@ -243,6 +309,17 @@ xfs_scrub_bmap_extent_xref( > > xfs_scrub_xref_is_used_space(info->sc, agbno, len); > > xfs_scrub_xref_not_inodes(info->sc, agbno, len); > > xfs_scrub_bmap_xref_rmap(info, irec, agbno); > > + switch (info->whichfork) { > > + case XFS_DATA_FORK: > > + xfs_scrub_bmap_xref_refcount_data(info, irec, agbno); > > + break; > > + case XFS_ATTR_FORK: > > + xfs_scrub_bmap_xref_refcount_attr(info, irec, agbno); > > + break; > > + case XFS_COW_FORK: > > + xfs_scrub_bmap_xref_refcount_cow(info, irec, agbno); > > + break; > > This is where the agbno comes from :P > > > + } > > > > xfs_scrub_ag_free(info->sc, &info->sc->sa); > > } > > diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c > > index 30603b4..fb16314 100644 > > --- a/fs/xfs/scrub/ialloc.c > > +++ b/fs/xfs/scrub/ialloc.c > > @@ -97,6 +97,7 @@ xfs_scrub_iallocbt_chunk_xref( > > > > xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); > > xfs_scrub_xref_owned_by(sc, agbno, len, &oinfo); > > + xfs_scrub_xref_not_shared(sc, agbno, len); > > } > > > > /* Is this chunk worth checking? */ > > diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c > > index fc546f2..f12586c 100644 > > --- a/fs/xfs/scrub/inode.c > > +++ b/fs/xfs/scrub/inode.c > > @@ -652,6 +652,7 @@ xfs_scrub_inode_xref( > > xfs_scrub_inode_xref_finobt(sc, ino); > > xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); > > xfs_scrub_xref_owned_by(sc, agbno, 1, &oinfo); > > + xfs_scrub_xref_not_shared(sc, agbno, 1); > > > > xfs_scrub_ag_free(sc, &sc->sa); > > } > > diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c > > index df18e47..6e5b12a 100644 > > --- a/fs/xfs/scrub/refcount.c > > +++ b/fs/xfs/scrub/refcount.c > > @@ -31,6 +31,7 @@ > > #include "xfs_sb.h" > > #include "xfs_alloc.h" > > #include "xfs_rmap.h" > > +#include "xfs_refcount.h" > > #include "scrub/xfs_scrub.h" > > #include "scrub/scrub.h" > > #include "scrub/common.h" > > @@ -428,3 +429,67 @@ xfs_scrub_refcountbt( > > > > return error; > > } > > + > > +/* xref check that a cow staging extent is marked in the refcountbt. */ > > +void > > +xfs_scrub_xref_has_cow_staging( > > + struct xfs_scrub_context *sc, > > + xfs_agblock_t bno, > > agbno > > > + xfs_extlen_t len) > > +{ > > + struct xfs_refcount_irec rc; > > + bool has_cowflag; > > + int has_refcount; > > + int error; > ..... > > +/* > > + * xref check that the extent is not shared. Only file data blocks > > + * can have multiple owners. > > + */ > > +void > > +xfs_scrub_xref_not_shared( > > + struct xfs_scrub_context *sc, > > + xfs_agblock_t bno, > > agbno > > Cheers, > > Dave. > -- > Dave Chinner > david@xxxxxxxxxxxxx > -- > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html