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

xfs: don't track the AGFL buffer in the scrub AG context

While scrubbing an allocation group, we don't need to hold the AGFL
buffer as part of the scrub context.  All that is necessary to lock an
AG is to hold the AGI and AGF buffers, so fix all the existing users of
the AGFL buffer to grab them only when necessary.
Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
parent 9a48b4a6
...@@ -609,9 +609,16 @@ xchk_agf( ...@@ -609,9 +609,16 @@ xchk_agf(
/* AGFL */ /* AGFL */
struct xchk_agfl_info { struct xchk_agfl_info {
unsigned int sz_entries; /* Number of AGFL entries that the AGF claims are in use. */
unsigned int agflcount;
/* Number of AGFL entries that we found. */
unsigned int nr_entries; unsigned int nr_entries;
/* Buffer to hold AGFL entries for extent checking. */
xfs_agblock_t *entries; xfs_agblock_t *entries;
struct xfs_buf *agfl_bp;
struct xfs_scrub *sc; struct xfs_scrub *sc;
}; };
...@@ -641,10 +648,10 @@ xchk_agfl_block( ...@@ -641,10 +648,10 @@ xchk_agfl_block(
struct xfs_scrub *sc = sai->sc; struct xfs_scrub *sc = sai->sc;
if (xfs_verify_agbno(sc->sa.pag, agbno) && if (xfs_verify_agbno(sc->sa.pag, agbno) &&
sai->nr_entries < sai->sz_entries) sai->nr_entries < sai->agflcount)
sai->entries[sai->nr_entries++] = agbno; sai->entries[sai->nr_entries++] = agbno;
else else
xchk_block_set_corrupt(sc, sc->sa.agfl_bp); xchk_block_set_corrupt(sc, sai->agfl_bp);
xchk_agfl_block_xref(sc, agbno); xchk_agfl_block_xref(sc, agbno);
...@@ -696,19 +703,26 @@ int ...@@ -696,19 +703,26 @@ int
xchk_agfl( xchk_agfl(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xchk_agfl_info sai; struct xchk_agfl_info sai = {
.sc = sc,
};
struct xfs_agf *agf; struct xfs_agf *agf;
xfs_agnumber_t agno = sc->sm->sm_agno; xfs_agnumber_t agno = sc->sm->sm_agno;
unsigned int agflcount;
unsigned int i; unsigned int i;
int error; int error;
/* Lock the AGF and AGI so that nobody can touch this AG. */
error = xchk_ag_read_headers(sc, agno, &sc->sa); error = xchk_ag_read_headers(sc, agno, &sc->sa);
if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error)) if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
goto out; return error;
if (!sc->sa.agf_bp) if (!sc->sa.agf_bp)
return -EFSCORRUPTED; return -EFSCORRUPTED;
xchk_buffer_recheck(sc, sc->sa.agfl_bp);
/* Try to read the AGFL, and verify its structure if we get it. */
error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &sai.agfl_bp);
if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
return error;
xchk_buffer_recheck(sc, sai.agfl_bp);
xchk_agfl_xref(sc); xchk_agfl_xref(sc);
...@@ -717,24 +731,21 @@ xchk_agfl( ...@@ -717,24 +731,21 @@ xchk_agfl(
/* Allocate buffer to ensure uniqueness of AGFL entries. */ /* Allocate buffer to ensure uniqueness of AGFL entries. */
agf = sc->sa.agf_bp->b_addr; agf = sc->sa.agf_bp->b_addr;
agflcount = be32_to_cpu(agf->agf_flcount); sai.agflcount = be32_to_cpu(agf->agf_flcount);
if (agflcount > xfs_agfl_size(sc->mp)) { if (sai.agflcount > xfs_agfl_size(sc->mp)) {
xchk_block_set_corrupt(sc, sc->sa.agf_bp); xchk_block_set_corrupt(sc, sc->sa.agf_bp);
goto out; goto out;
} }
memset(&sai, 0, sizeof(sai)); sai.entries = kvcalloc(sai.agflcount, sizeof(xfs_agblock_t),
sai.sc = sc; GFP_KERNEL | __GFP_RETRY_MAYFAIL);
sai.sz_entries = agflcount;
sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount,
KM_MAYFAIL);
if (!sai.entries) { if (!sai.entries) {
error = -ENOMEM; error = -ENOMEM;
goto out; goto out;
} }
/* Check the blocks in the AGFL. */ /* Check the blocks in the AGFL. */
error = xfs_agfl_walk(sc->mp, sc->sa.agf_bp->b_addr, error = xfs_agfl_walk(sc->mp, sc->sa.agf_bp->b_addr, sai.agfl_bp,
sc->sa.agfl_bp, xchk_agfl_block, &sai); xchk_agfl_block, &sai);
if (error == -ECANCELED) { if (error == -ECANCELED) {
error = 0; error = 0;
goto out_free; goto out_free;
...@@ -742,7 +753,7 @@ xchk_agfl( ...@@ -742,7 +753,7 @@ xchk_agfl(
if (error) if (error)
goto out_free; goto out_free;
if (agflcount != sai.nr_entries) { if (sai.agflcount != sai.nr_entries) {
xchk_block_set_corrupt(sc, sc->sa.agf_bp); xchk_block_set_corrupt(sc, sc->sa.agf_bp);
goto out_free; goto out_free;
} }
...@@ -758,7 +769,7 @@ xchk_agfl( ...@@ -758,7 +769,7 @@ xchk_agfl(
} }
out_free: out_free:
kmem_free(sai.entries); kvfree(sai.entries);
out: out:
return error; return error;
} }
......
...@@ -697,7 +697,6 @@ xrep_agfl( ...@@ -697,7 +697,6 @@ xrep_agfl(
* freespace overflow to the freespace btrees. * freespace overflow to the freespace btrees.
*/ */
sc->sa.agf_bp = agf_bp; sc->sa.agf_bp = agf_bp;
sc->sa.agfl_bp = agfl_bp;
error = xrep_roll_ag_trans(sc); error = xrep_roll_ag_trans(sc);
if (error) if (error)
goto err; goto err;
......
...@@ -424,10 +424,6 @@ xchk_ag_read_headers( ...@@ -424,10 +424,6 @@ xchk_ag_read_headers(
if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGF)) if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGF))
return error; return error;
error = xfs_alloc_read_agfl(sa->pag, sc->tp, &sa->agfl_bp);
if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGFL))
return error;
return 0; return 0;
} }
...@@ -515,10 +511,6 @@ xchk_ag_free( ...@@ -515,10 +511,6 @@ xchk_ag_free(
struct xchk_ag *sa) struct xchk_ag *sa)
{ {
xchk_ag_btcur_free(sa); xchk_ag_btcur_free(sa);
if (sa->agfl_bp) {
xfs_trans_brelse(sc->tp, sa->agfl_bp);
sa->agfl_bp = NULL;
}
if (sa->agf_bp) { if (sa->agf_bp) {
xfs_trans_brelse(sc->tp, sa->agf_bp); xfs_trans_brelse(sc->tp, sa->agf_bp);
sa->agf_bp = NULL; sa->agf_bp = NULL;
......
...@@ -126,8 +126,6 @@ xrep_roll_ag_trans( ...@@ -126,8 +126,6 @@ xrep_roll_ag_trans(
xfs_trans_bhold(sc->tp, sc->sa.agi_bp); xfs_trans_bhold(sc->tp, sc->sa.agi_bp);
if (sc->sa.agf_bp) if (sc->sa.agf_bp)
xfs_trans_bhold(sc->tp, sc->sa.agf_bp); xfs_trans_bhold(sc->tp, sc->sa.agf_bp);
if (sc->sa.agfl_bp)
xfs_trans_bhold(sc->tp, sc->sa.agfl_bp);
/* /*
* Roll the transaction. We still own the buffer and the buffer lock * Roll the transaction. We still own the buffer and the buffer lock
...@@ -145,8 +143,6 @@ xrep_roll_ag_trans( ...@@ -145,8 +143,6 @@ xrep_roll_ag_trans(
xfs_trans_bjoin(sc->tp, sc->sa.agi_bp); xfs_trans_bjoin(sc->tp, sc->sa.agi_bp);
if (sc->sa.agf_bp) if (sc->sa.agf_bp)
xfs_trans_bjoin(sc->tp, sc->sa.agf_bp); xfs_trans_bjoin(sc->tp, sc->sa.agf_bp);
if (sc->sa.agfl_bp)
xfs_trans_bjoin(sc->tp, sc->sa.agfl_bp);
return 0; return 0;
} }
...@@ -498,6 +494,7 @@ xrep_put_freelist( ...@@ -498,6 +494,7 @@ xrep_put_freelist(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_agblock_t agbno) xfs_agblock_t agbno)
{ {
struct xfs_buf *agfl_bp;
int error; int error;
/* Make sure there's space on the freelist. */ /* Make sure there's space on the freelist. */
...@@ -516,8 +513,12 @@ xrep_put_freelist( ...@@ -516,8 +513,12 @@ xrep_put_freelist(
return error; return error;
/* Put the block on the AGFL. */ /* Put the block on the AGFL. */
error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
if (error)
return error;
error = xfs_alloc_put_freelist(sc->sa.pag, sc->tp, sc->sa.agf_bp, error = xfs_alloc_put_freelist(sc->sa.pag, sc->tp, sc->sa.agf_bp,
sc->sa.agfl_bp, agbno, 0); agfl_bp, agbno, 0);
if (error) if (error)
return error; return error;
xfs_extent_busy_insert(sc->tp, sc->sa.pag, agbno, 1, xfs_extent_busy_insert(sc->tp, sc->sa.pag, agbno, 1,
......
...@@ -39,7 +39,6 @@ struct xchk_ag { ...@@ -39,7 +39,6 @@ struct xchk_ag {
/* AG btree roots */ /* AG btree roots */
struct xfs_buf *agf_bp; struct xfs_buf *agf_bp;
struct xfs_buf *agfl_bp;
struct xfs_buf *agi_bp; struct xfs_buf *agi_bp;
/* AG btrees */ /* AG btrees */
......
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