Message ID | 151398985848.18741.1443595678961710395.stgit@magnolia (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
On Fri, Dec 22, 2017 at 04:44:18PM -0800, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@oracle.com> > > When we're scrubbing various btrees, cross-reference the records with > the bnobt to ensure that we don't also think the space is free. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- > fs/xfs/scrub/agheader.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++ > fs/xfs/scrub/alloc.c | 19 +++++++++++ > fs/xfs/scrub/bmap.c | 21 +++++++++++- > fs/xfs/scrub/btree.c | 12 +++++++ > fs/xfs/scrub/ialloc.c | 1 + > fs/xfs/scrub/inode.c | 15 ++++++++ > fs/xfs/scrub/refcount.c | 1 + > fs/xfs/scrub/rmap.c | 4 ++ > fs/xfs/scrub/scrub.h | 5 +++ > 9 files changed, 161 insertions(+), 1 deletion(-) > > > diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c > index 5be9059..3bb0f96 100644 > --- a/fs/xfs/scrub/agheader.c > +++ b/fs/xfs/scrub/agheader.c > @@ -107,6 +107,20 @@ xfs_scrub_superblock_xref( > struct xfs_scrub_context *sc, > struct xfs_buf *bp) > { > + struct xfs_mount *mp = sc->mp; > + xfs_agnumber_t agno = sc->sm->sm_agno; > + xfs_agblock_t bno; > + int error; > + > + bno = XFS_SB_BLOCK(mp); agbno > + > + error = xfs_scrub_ag_init(sc, agno, &sc->sa); > + if (!xfs_scrub_xref_process_error(sc, agno, bno, &error)) > + return; > + > + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); "xref_not_free". That doesn't tell me what it's actually checking is not free, or what it's checking against. Seeing as we're checking these all against the bnobt, wouldn't something like this be more obvious: xfs_scrub_is_used_space(sc, agbno, 1); > + /* scrub teardown will take care of sc->sa for us */ > } > > /* > @@ -407,11 +421,51 @@ xfs_scrub_superblock( > > /* AGF */ > > +/* Tally freespace record lengths. */ > +STATIC int > +xfs_scrub_agf_record_bno_lengths( > + struct xfs_btree_cur *cur, > + struct xfs_alloc_rec_incore *rec, > + void *priv) > +{ > + xfs_extlen_t *blocks = priv; > + > + (*blocks) += rec->ar_blockcount; > + return 0; > +} > + > /* Cross-reference with the other btrees. */ > STATIC void > xfs_scrub_agf_xref( > struct xfs_scrub_context *sc) > { > + struct xfs_mount *mp = sc->mp; > + struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp); > + struct xfs_btree_cur **pcur; > + xfs_agblock_t bno; > + xfs_extlen_t blocks; > + int error; > + > + bno = XFS_AGF_BLOCK(mp); agbno. (and for all the others) > + > + error = xfs_scrub_ag_btcur_init(sc, &sc->sa); > + if (error) > + return; > + > + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); > + > + /* Check agf_freeblks */ > + pcur = &sc->sa.bno_cur; > + if (*pcur) { > + blocks = 0; > + error = xfs_alloc_query_all(*pcur, > + xfs_scrub_agf_record_bno_lengths, &blocks); > + if (xfs_scrub_should_xref(sc, &error, pcur) && > + blocks != be32_to_cpu(agf->agf_freeblks)) > + xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp); > + } I have no idea what xfs_scrub_should_xref() means in this context. We're doing a xref scrub, so why are we asking if we should be running a xref? > diff --git a/fs/xfs/scrub/alloc.c b/fs/xfs/scrub/alloc.c > index 0d95b84..3d6f8cc 100644 > --- a/fs/xfs/scrub/alloc.c > +++ b/fs/xfs/scrub/alloc.c > @@ -114,3 +114,22 @@ xfs_scrub_cntbt( > { > return xfs_scrub_allocbt(sc, XFS_BTNUM_CNT); > } > + > +/* xref check that the extent is not free */ > +void > +xfs_scrub_xref_not_free( > + struct xfs_scrub_context *sc, > + struct xfs_btree_cur **pcur, > + xfs_agblock_t bno, > + xfs_extlen_t len) > +{ > + bool is_freesp; > + int error; > + > + if (!(*pcur)) > + return; > + > + error = xfs_alloc_has_record(*pcur, bno, len, &is_freesp); > + if (xfs_scrub_should_xref(sc, &error, pcur) && is_freesp) > + xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0); > +} Again, "should_xref" doesn't actually tell me anything about what this function is doing... > @@ -117,6 +117,25 @@ xfs_scrub_bmap_extent_xref( > struct xfs_btree_cur *cur, > struct xfs_bmbt_irec *irec) > { > + struct xfs_scrub_ag sa = { 0 }; > + struct xfs_mount *mp = info->sc->mp; > + xfs_agnumber_t agno; > + xfs_agblock_t agbno; > + xfs_extlen_t len; > + int error; > + > + agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock); > + agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); > + len = irec->br_blockcount; > + > + error = xfs_scrub_ag_init(info->sc, agno, &sa); > + if (!xfs_scrub_fblock_process_error(info->sc, info->whichfork, > + irec->br_startoff, &error)) > + return; > + > + xfs_scrub_xref_not_free(info->sc, &sa.bno_cur, agbno, len); > + > + xfs_scrub_ag_free(info->sc, &sa); Why do we use an on-stack struct xfs_scrub_ag here, and not the one embedded into the scrub context like all the other functions in this patch? > } > > /* Scrub a single extent record. */ > diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c > index 9151499..ae58fcc 100644 > --- a/fs/xfs/scrub/btree.c > +++ b/fs/xfs/scrub/btree.c > @@ -381,9 +381,12 @@ xfs_scrub_btree_check_block_owner( > struct xfs_scrub_ag sa = { 0 }; > struct xfs_scrub_ag *psa; > xfs_agnumber_t agno; > + xfs_agblock_t bno; > + bool is_freesp; > int error = 0; > > agno = xfs_daddr_to_agno(bs->cur->bc_mp, daddr); > + bno = xfs_daddr_to_agbno(bs->cur->bc_mp, daddr); agbno. > @@ -584,6 +584,21 @@ xfs_scrub_inode_xref( > xfs_ino_t ino, > struct xfs_dinode *dip) > { > + struct xfs_scrub_ag sa = { 0 }; > + xfs_agnumber_t agno; > + xfs_agblock_t agbno; > + int error; > + > + agno = XFS_INO_TO_AGNO(sc->mp, ino); > + agbno = XFS_INO_TO_AGBNO(sc->mp, ino); > + > + error = xfs_scrub_ag_init(sc, agno, &sa); > + if (!xfs_scrub_xref_process_error(sc, agno, agbno, &error)) > + return; > + > + xfs_scrub_xref_not_free(sc, &sa.bno_cur, agbno, 1); > + > + xfs_scrub_ag_free(sc, &sa); Same question here - on-stack vs embedded.... Cheers, Dave.
On Tue, Jan 09, 2018 at 10:51:25AM +1100, Dave Chinner wrote: > On Fri, Dec 22, 2017 at 04:44:18PM -0800, Darrick J. Wong wrote: > > From: Darrick J. Wong <darrick.wong@oracle.com> > > > > When we're scrubbing various btrees, cross-reference the records with > > the bnobt to ensure that we don't also think the space is free. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > --- > > fs/xfs/scrub/agheader.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++ > > fs/xfs/scrub/alloc.c | 19 +++++++++++ > > fs/xfs/scrub/bmap.c | 21 +++++++++++- > > fs/xfs/scrub/btree.c | 12 +++++++ > > fs/xfs/scrub/ialloc.c | 1 + > > fs/xfs/scrub/inode.c | 15 ++++++++ > > fs/xfs/scrub/refcount.c | 1 + > > fs/xfs/scrub/rmap.c | 4 ++ > > fs/xfs/scrub/scrub.h | 5 +++ > > 9 files changed, 161 insertions(+), 1 deletion(-) > > > > > > diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c > > index 5be9059..3bb0f96 100644 > > --- a/fs/xfs/scrub/agheader.c > > +++ b/fs/xfs/scrub/agheader.c > > @@ -107,6 +107,20 @@ xfs_scrub_superblock_xref( > > struct xfs_scrub_context *sc, > > struct xfs_buf *bp) > > { > > + struct xfs_mount *mp = sc->mp; > > + xfs_agnumber_t agno = sc->sm->sm_agno; > > + xfs_agblock_t bno; > > + int error; > > + > > + bno = XFS_SB_BLOCK(mp); > > agbno Fixed (and all the others). > > + > > + error = xfs_scrub_ag_init(sc, agno, &sc->sa); > > + if (!xfs_scrub_xref_process_error(sc, agno, bno, &error)) > > + return; > > + > > + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); > > "xref_not_free". That doesn't tell me what it's actually checking > is not free, or what it's checking against. Seeing as we're checking > these all against the bnobt, wouldn't something like this be more > obvious: > > xfs_scrub_is_used_space(sc, agbno, 1); I've been trying to keep "xref" in the name of the functions that help us do cross-referencing, but you're right that the **pcur parameter can drop out. I'll ... do that. :) > > + /* scrub teardown will take care of sc->sa for us */ > > } > > > > /* > > @@ -407,11 +421,51 @@ xfs_scrub_superblock( > > > > /* AGF */ > > > > +/* Tally freespace record lengths. */ > > +STATIC int > > +xfs_scrub_agf_record_bno_lengths( > > + struct xfs_btree_cur *cur, > > + struct xfs_alloc_rec_incore *rec, > > + void *priv) > > +{ > > + xfs_extlen_t *blocks = priv; > > + > > + (*blocks) += rec->ar_blockcount; > > + return 0; > > +} > > + > > /* Cross-reference with the other btrees. */ > > STATIC void > > xfs_scrub_agf_xref( > > struct xfs_scrub_context *sc) > > { > > + struct xfs_mount *mp = sc->mp; > > + struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp); > > + struct xfs_btree_cur **pcur; > > + xfs_agblock_t bno; > > + xfs_extlen_t blocks; > > + int error; > > + > > + bno = XFS_AGF_BLOCK(mp); > > agbno. (and for all the others) > > > + > > + error = xfs_scrub_ag_btcur_init(sc, &sc->sa); > > + if (error) > > + return; > > + > > + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); > > + > > + /* Check agf_freeblks */ > > + pcur = &sc->sa.bno_cur; > > + if (*pcur) { > > + blocks = 0; > > + error = xfs_alloc_query_all(*pcur, > > + xfs_scrub_agf_record_bno_lengths, &blocks); > > + if (xfs_scrub_should_xref(sc, &error, pcur) && > > + blocks != be32_to_cpu(agf->agf_freeblks)) > > + xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp); > > + } > > I have no idea what xfs_scrub_should_xref() means in this context. > We're doing a xref scrub, so why are we asking if we should be > running a xref? Given that we tried to retrieve some data from some other data structure, the function xfs_scrub_should_xref decides if we should actually bother with the comparison checks? In other words, if the xfs_alloc_query_all returned an error code then we need to delete *pcur and we can skip the "blocks != be32..." check since it makes no sense. How about xfs_scrub_should_check_xref? > > > > diff --git a/fs/xfs/scrub/alloc.c b/fs/xfs/scrub/alloc.c > > index 0d95b84..3d6f8cc 100644 > > --- a/fs/xfs/scrub/alloc.c > > +++ b/fs/xfs/scrub/alloc.c > > @@ -114,3 +114,22 @@ xfs_scrub_cntbt( > > { > > return xfs_scrub_allocbt(sc, XFS_BTNUM_CNT); > > } > > + > > +/* xref check that the extent is not free */ > > +void > > +xfs_scrub_xref_not_free( > > + struct xfs_scrub_context *sc, > > + struct xfs_btree_cur **pcur, > > + xfs_agblock_t bno, > > + xfs_extlen_t len) > > +{ > > + bool is_freesp; > > + int error; > > + > > + if (!(*pcur)) > > + return; > > + > > + error = xfs_alloc_has_record(*pcur, bno, len, &is_freesp); > > + if (xfs_scrub_should_xref(sc, &error, pcur) && is_freesp) > > + xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0); > > +} > > Again, "should_xref" doesn't actually tell me anything about what > this function is doing... > > > @@ -117,6 +117,25 @@ xfs_scrub_bmap_extent_xref( > > struct xfs_btree_cur *cur, > > struct xfs_bmbt_irec *irec) > > { > > + struct xfs_scrub_ag sa = { 0 }; > > + struct xfs_mount *mp = info->sc->mp; > > + xfs_agnumber_t agno; > > + xfs_agblock_t agbno; > > + xfs_extlen_t len; > > + int error; > > + > > + agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock); > > + agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); > > + len = irec->br_blockcount; > > + > > + error = xfs_scrub_ag_init(info->sc, agno, &sa); > > + if (!xfs_scrub_fblock_process_error(info->sc, info->whichfork, > > + irec->br_startoff, &error)) > > + return; > > + > > + xfs_scrub_xref_not_free(info->sc, &sa.bno_cur, agbno, len); > > + > > + xfs_scrub_ag_free(info->sc, &sa); > > Why do we use an on-stack struct xfs_scrub_ag here, and not the one > embedded into the scrub context like all the other functions in this > patch? I think this is an archaic side effect of a previous version of scrub when the xfs_scrub_ag wasn't embedded in the scrub context. :/ IOWs, there's no reason, I'll go fix it (and the others). --D > > } > > > > /* Scrub a single extent record. */ > > diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c > > index 9151499..ae58fcc 100644 > > --- a/fs/xfs/scrub/btree.c > > +++ b/fs/xfs/scrub/btree.c > > @@ -381,9 +381,12 @@ xfs_scrub_btree_check_block_owner( > > struct xfs_scrub_ag sa = { 0 }; > > struct xfs_scrub_ag *psa; > > xfs_agnumber_t agno; > > + xfs_agblock_t bno; > > + bool is_freesp; > > int error = 0; > > > > agno = xfs_daddr_to_agno(bs->cur->bc_mp, daddr); > > + bno = xfs_daddr_to_agbno(bs->cur->bc_mp, daddr); > > agbno. > > > @@ -584,6 +584,21 @@ xfs_scrub_inode_xref( > > xfs_ino_t ino, > > struct xfs_dinode *dip) > > { > > + struct xfs_scrub_ag sa = { 0 }; > > + xfs_agnumber_t agno; > > + xfs_agblock_t agbno; > > + int error; > > + > > + agno = XFS_INO_TO_AGNO(sc->mp, ino); > > + agbno = XFS_INO_TO_AGBNO(sc->mp, ino); > > + > > + error = xfs_scrub_ag_init(sc, agno, &sa); > > + if (!xfs_scrub_xref_process_error(sc, agno, agbno, &error)) > > + return; > > + > > + xfs_scrub_xref_not_free(sc, &sa.bno_cur, agbno, 1); > > + > > + xfs_scrub_ag_free(sc, &sa); > > Same question here - on-stack vs embedded.... > > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com > -- > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in > the body of a message to majordomo@vger.kernel.org > 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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Jan 08, 2018 at 04:34:41PM -0800, Darrick J. Wong wrote: > On Tue, Jan 09, 2018 at 10:51:25AM +1100, Dave Chinner wrote: > > On Fri, Dec 22, 2017 at 04:44:18PM -0800, Darrick J. Wong wrote: > > > + error = xfs_scrub_ag_btcur_init(sc, &sc->sa); > > > + if (error) > > > + return; > > > + > > > + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); > > > + > > > + /* Check agf_freeblks */ > > > + pcur = &sc->sa.bno_cur; > > > + if (*pcur) { > > > + blocks = 0; > > > + error = xfs_alloc_query_all(*pcur, > > > + xfs_scrub_agf_record_bno_lengths, &blocks); > > > + if (xfs_scrub_should_xref(sc, &error, pcur) && > > > + blocks != be32_to_cpu(agf->agf_freeblks)) > > > + xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp); > > > + } > > > > I have no idea what xfs_scrub_should_xref() means in this context. > > We're doing a xref scrub, so why are we asking if we should be > > running a xref? > > Given that we tried to retrieve some data from some other data > structure, the function xfs_scrub_should_xref decides if we should > actually bother with the comparison checks? In other words, if the > xfs_alloc_query_all returned an error code then we need to delete *pcur > and we can skip the "blocks != be32..." check since it makes no sense. > > How about xfs_scrub_should_check_xref? Yes, that makes more sense. Cheers, Dave.
diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c index 5be9059..3bb0f96 100644 --- a/fs/xfs/scrub/agheader.c +++ b/fs/xfs/scrub/agheader.c @@ -107,6 +107,20 @@ xfs_scrub_superblock_xref( struct xfs_scrub_context *sc, struct xfs_buf *bp) { + struct xfs_mount *mp = sc->mp; + xfs_agnumber_t agno = sc->sm->sm_agno; + xfs_agblock_t bno; + int error; + + bno = XFS_SB_BLOCK(mp); + + error = xfs_scrub_ag_init(sc, agno, &sc->sa); + if (!xfs_scrub_xref_process_error(sc, agno, bno, &error)) + return; + + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); + + /* scrub teardown will take care of sc->sa for us */ } /* @@ -407,11 +421,51 @@ xfs_scrub_superblock( /* AGF */ +/* Tally freespace record lengths. */ +STATIC int +xfs_scrub_agf_record_bno_lengths( + struct xfs_btree_cur *cur, + struct xfs_alloc_rec_incore *rec, + void *priv) +{ + xfs_extlen_t *blocks = priv; + + (*blocks) += rec->ar_blockcount; + return 0; +} + /* Cross-reference with the other btrees. */ STATIC void xfs_scrub_agf_xref( struct xfs_scrub_context *sc) { + struct xfs_mount *mp = sc->mp; + struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp); + struct xfs_btree_cur **pcur; + xfs_agblock_t bno; + xfs_extlen_t blocks; + int error; + + bno = XFS_AGF_BLOCK(mp); + + error = xfs_scrub_ag_btcur_init(sc, &sc->sa); + if (error) + return; + + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); + + /* Check agf_freeblks */ + pcur = &sc->sa.bno_cur; + if (*pcur) { + blocks = 0; + error = xfs_alloc_query_all(*pcur, + xfs_scrub_agf_record_bno_lengths, &blocks); + if (xfs_scrub_should_xref(sc, &error, pcur) && + blocks != be32_to_cpu(agf->agf_freeblks)) + xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp); + } + + /* scrub teardown will take care of sc->sa for us */ } /* Scrub the AGF. */ @@ -514,6 +568,7 @@ xfs_scrub_agfl_block_xref( struct xfs_scrub_context *sc, xfs_agblock_t bno) { + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); } /* Scrub an AGFL block. */ @@ -557,6 +612,22 @@ STATIC void xfs_scrub_agfl_xref( struct xfs_scrub_context *sc) { + struct xfs_mount *mp = sc->mp; + xfs_agblock_t bno; + int error; + + bno = XFS_AGFL_BLOCK(mp); + + error = xfs_scrub_ag_btcur_init(sc, &sc->sa); + if (error) + return; + + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); + + /* + * Scrub teardown will take care of sc->sa for us. Leave sc->sa + * active so that the agfl block xref can use it too. + */ } /* Scrub the AGFL. */ @@ -631,6 +702,19 @@ STATIC void xfs_scrub_agi_xref( struct xfs_scrub_context *sc) { + struct xfs_mount *mp = sc->mp; + xfs_agblock_t bno; + int error; + + bno = XFS_AGI_BLOCK(mp); + + error = xfs_scrub_ag_btcur_init(sc, &sc->sa); + if (error) + return; + + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, 1); + + /* scrub teardown will take care of sc->sa for us */ } /* Scrub the AGI. */ diff --git a/fs/xfs/scrub/alloc.c b/fs/xfs/scrub/alloc.c index 0d95b84..3d6f8cc 100644 --- a/fs/xfs/scrub/alloc.c +++ b/fs/xfs/scrub/alloc.c @@ -114,3 +114,22 @@ xfs_scrub_cntbt( { return xfs_scrub_allocbt(sc, XFS_BTNUM_CNT); } + +/* xref check that the extent is not free */ +void +xfs_scrub_xref_not_free( + struct xfs_scrub_context *sc, + struct xfs_btree_cur **pcur, + xfs_agblock_t bno, + xfs_extlen_t len) +{ + bool is_freesp; + int error; + + if (!(*pcur)) + return; + + error = xfs_alloc_has_record(*pcur, bno, len, &is_freesp); + if (xfs_scrub_should_xref(sc, &error, pcur) && is_freesp) + xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0); +} diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c index d960b7a..a74771c 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -31,12 +31,12 @@ #include "xfs_sb.h" #include "xfs_inode.h" #include "xfs_inode_fork.h" -#include "xfs_alloc.h" #include "xfs_rtalloc.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_bmap_btree.h" #include "xfs_rmap.h" +#include "xfs_alloc.h" #include "scrub/xfs_scrub.h" #include "scrub/scrub.h" #include "scrub/common.h" @@ -117,6 +117,25 @@ xfs_scrub_bmap_extent_xref( struct xfs_btree_cur *cur, struct xfs_bmbt_irec *irec) { + struct xfs_scrub_ag sa = { 0 }; + struct xfs_mount *mp = info->sc->mp; + xfs_agnumber_t agno; + xfs_agblock_t agbno; + xfs_extlen_t len; + int error; + + agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock); + agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); + len = irec->br_blockcount; + + error = xfs_scrub_ag_init(info->sc, agno, &sa); + if (!xfs_scrub_fblock_process_error(info->sc, info->whichfork, + irec->br_startoff, &error)) + return; + + xfs_scrub_xref_not_free(info->sc, &sa.bno_cur, agbno, len); + + xfs_scrub_ag_free(info->sc, &sa); } /* Scrub a single extent record. */ diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c index 9151499..ae58fcc 100644 --- a/fs/xfs/scrub/btree.c +++ b/fs/xfs/scrub/btree.c @@ -381,9 +381,12 @@ xfs_scrub_btree_check_block_owner( struct xfs_scrub_ag sa = { 0 }; struct xfs_scrub_ag *psa; xfs_agnumber_t agno; + xfs_agblock_t bno; + bool is_freesp; int error = 0; agno = xfs_daddr_to_agno(bs->cur->bc_mp, daddr); + bno = xfs_daddr_to_agbno(bs->cur->bc_mp, daddr); if (bs->cur->bc_flags & XFS_BTREE_LONG_PTRS) { error = xfs_scrub_ag_init(bs->sc, agno, &sa); @@ -395,6 +398,15 @@ xfs_scrub_btree_check_block_owner( psa = &bs->sc->sa; } + /* Cross-reference with the bnobt. */ + if (psa->bno_cur) { + error = xfs_alloc_has_record(psa->bno_cur, bno, 1, &is_freesp); + if (xfs_scrub_should_xref(bs->sc, &error, &psa->bno_cur) && + is_freesp) + xfs_scrub_btree_xref_set_corrupt(bs->sc, psa->bno_cur, + 0); + } + if (psa == &sa) xfs_scrub_ag_free(bs->sc, &sa); diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c index 599d62a..4c4ef17c 100644 --- a/fs/xfs/scrub/ialloc.c +++ b/fs/xfs/scrub/ialloc.c @@ -67,6 +67,7 @@ xfs_scrub_iallocbt_chunk_xref( xfs_agblock_t bno, xfs_extlen_t len) { + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, len); } /* Is this chunk worth checking? */ diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c index 6cd6b34..a00d179 100644 --- a/fs/xfs/scrub/inode.c +++ b/fs/xfs/scrub/inode.c @@ -584,6 +584,21 @@ xfs_scrub_inode_xref( xfs_ino_t ino, struct xfs_dinode *dip) { + struct xfs_scrub_ag sa = { 0 }; + xfs_agnumber_t agno; + xfs_agblock_t agbno; + int error; + + agno = XFS_INO_TO_AGNO(sc->mp, ino); + agbno = XFS_INO_TO_AGBNO(sc->mp, ino); + + error = xfs_scrub_ag_init(sc, agno, &sa); + if (!xfs_scrub_xref_process_error(sc, agno, agbno, &error)) + return; + + xfs_scrub_xref_not_free(sc, &sa.bno_cur, agbno, 1); + + xfs_scrub_ag_free(sc, &sa); } /* Scrub an inode. */ diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c index 5a3aa9b..19c303d 100644 --- a/fs/xfs/scrub/refcount.c +++ b/fs/xfs/scrub/refcount.c @@ -58,6 +58,7 @@ xfs_scrub_refcountbt_xref( xfs_extlen_t len, xfs_nlink_t refcount) { + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, len); } /* Scrub a refcountbt record. */ diff --git a/fs/xfs/scrub/rmap.c b/fs/xfs/scrub/rmap.c index 80edddb..5c9646b 100644 --- a/fs/xfs/scrub/rmap.c +++ b/fs/xfs/scrub/rmap.c @@ -57,6 +57,10 @@ xfs_scrub_rmapbt_xref( struct xfs_scrub_context *sc, struct xfs_rmap_irec *irec) { + xfs_agblock_t bno = irec->rm_startblock; + xfs_extlen_t len = irec->rm_blockcount; + + xfs_scrub_xref_not_free(sc, &sc->sa.bno_cur, bno, len); } /* Scrub an rmapbt record. */ diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h index 2a79614..e75ff0e 100644 --- a/fs/xfs/scrub/scrub.h +++ b/fs/xfs/scrub/scrub.h @@ -123,4 +123,9 @@ xfs_scrub_quota(struct xfs_scrub_context *sc) } #endif +/* cross-referencing helpers */ +void xfs_scrub_xref_not_free(struct xfs_scrub_context *sc, + struct xfs_btree_cur **pcur, xfs_agblock_t bno, + xfs_extlen_t len); + #endif /* __XFS_SCRUB_SCRUB_H__ */