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

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
Loading
Loading
Loading
Loading
+29 −18
Original line number Diff line number Diff line
@@ -609,9 +609,16 @@ xchk_agf(
/* AGFL */

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;

	/* Buffer to hold AGFL entries for extent checking. */
	xfs_agblock_t		*entries;

	struct xfs_buf		*agfl_bp;
	struct xfs_scrub	*sc;
};

@@ -641,10 +648,10 @@ xchk_agfl_block(
	struct xfs_scrub	*sc = sai->sc;

	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;
	else
		xchk_block_set_corrupt(sc, sc->sa.agfl_bp);
		xchk_block_set_corrupt(sc, sai->agfl_bp);

	xchk_agfl_block_xref(sc, agbno);

@@ -696,19 +703,26 @@ int
xchk_agfl(
	struct xfs_scrub	*sc)
{
	struct xchk_agfl_info	sai;
	struct xchk_agfl_info	sai = {
		.sc		= sc,
	};
	struct xfs_agf		*agf;
	xfs_agnumber_t		agno = sc->sm->sm_agno;
	unsigned int		agflcount;
	unsigned int		i;
	int			error;

	/* Lock the AGF and AGI so that nobody can touch this AG. */
	error = xchk_ag_read_headers(sc, agno, &sc->sa);
	if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
		goto out;
		return error;
	if (!sc->sa.agf_bp)
		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);

@@ -717,24 +731,21 @@ xchk_agfl(

	/* Allocate buffer to ensure uniqueness of AGFL entries. */
	agf = sc->sa.agf_bp->b_addr;
	agflcount = be32_to_cpu(agf->agf_flcount);
	if (agflcount > xfs_agfl_size(sc->mp)) {
	sai.agflcount = be32_to_cpu(agf->agf_flcount);
	if (sai.agflcount > xfs_agfl_size(sc->mp)) {
		xchk_block_set_corrupt(sc, sc->sa.agf_bp);
		goto out;
	}
	memset(&sai, 0, sizeof(sai));
	sai.sc = sc;
	sai.sz_entries = agflcount;
	sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount,
			KM_MAYFAIL);
	sai.entries = kvcalloc(sai.agflcount, sizeof(xfs_agblock_t),
			GFP_KERNEL | __GFP_RETRY_MAYFAIL);
	if (!sai.entries) {
		error = -ENOMEM;
		goto out;
	}

	/* Check the blocks in the AGFL. */
	error = xfs_agfl_walk(sc->mp, sc->sa.agf_bp->b_addr,
			sc->sa.agfl_bp, xchk_agfl_block, &sai);
	error = xfs_agfl_walk(sc->mp, sc->sa.agf_bp->b_addr, sai.agfl_bp,
			xchk_agfl_block, &sai);
	if (error == -ECANCELED) {
		error = 0;
		goto out_free;
@@ -742,7 +753,7 @@ xchk_agfl(
	if (error)
		goto out_free;

	if (agflcount != sai.nr_entries) {
	if (sai.agflcount != sai.nr_entries) {
		xchk_block_set_corrupt(sc, sc->sa.agf_bp);
		goto out_free;
	}
@@ -758,7 +769,7 @@ xchk_agfl(
	}

out_free:
	kmem_free(sai.entries);
	kvfree(sai.entries);
out:
	return error;
}
+0 −1
Original line number Diff line number Diff line
@@ -697,7 +697,6 @@ xrep_agfl(
	 * freespace overflow to the freespace btrees.
	 */
	sc->sa.agf_bp = agf_bp;
	sc->sa.agfl_bp = agfl_bp;
	error = xrep_roll_ag_trans(sc);
	if (error)
		goto err;
+0 −8
Original line number Diff line number Diff line
@@ -424,10 +424,6 @@ xchk_ag_read_headers(
	if (error && want_ag_read_header_failure(sc, XFS_SCRUB_TYPE_AGF))
		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;
}

@@ -515,10 +511,6 @@ xchk_ag_free(
	struct xchk_ag		*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) {
		xfs_trans_brelse(sc->tp, sa->agf_bp);
		sa->agf_bp = NULL;
+6 −5
Original line number Diff line number Diff line
@@ -126,8 +126,6 @@ xrep_roll_ag_trans(
		xfs_trans_bhold(sc->tp, sc->sa.agi_bp);
	if (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
@@ -145,8 +143,6 @@ xrep_roll_ag_trans(
		xfs_trans_bjoin(sc->tp, sc->sa.agi_bp);
	if (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;
}
@@ -498,6 +494,7 @@ xrep_put_freelist(
	struct xfs_scrub	*sc,
	xfs_agblock_t		agbno)
{
	struct xfs_buf		*agfl_bp;
	int			error;

	/* Make sure there's space on the freelist. */
@@ -516,8 +513,12 @@ xrep_put_freelist(
		return error;

	/* 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,
			sc->sa.agfl_bp, agbno, 0);
			agfl_bp, agbno, 0);
	if (error)
		return error;
	xfs_extent_busy_insert(sc->tp, sc->sa.pag, agbno, 1,
+0 −1
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@ struct xchk_ag {

	/* AG btree roots */
	struct xfs_buf		*agf_bp;
	struct xfs_buf		*agfl_bp;
	struct xfs_buf		*agi_bp;

	/* AG btrees */