Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cce77bcf authored by Dave Chinner's avatar Dave Chinner Committed by Darrick J. Wong
Browse files

xfs: factor out AG header initialisation from growfs core



The intialisation of new AG headers is mostly common with the
userspace mkfs code and growfs in the kernel, so start factoring it
out so we can move it to libxfs and use it in both places.

Signed-Off-By: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 879de98e
Loading
Loading
Loading
Loading
+331 −306
Original line number Diff line number Diff line
@@ -71,77 +71,27 @@ xfs_growfs_get_hdr_buf(
	return bp;
}

static int
xfs_growfs_data_private(
	xfs_mount_t		*mp,		/* mount point for filesystem */
	xfs_growfs_data_t	*in)		/* growfs data input struct */
{
	xfs_agf_t		*agf;
	struct xfs_agfl		*agfl;
	xfs_agi_t		*agi;
	xfs_agnumber_t		agno;
	xfs_extlen_t		agsize;
	xfs_extlen_t		tmpsize;
	xfs_alloc_rec_t		*arec;
	xfs_buf_t		*bp;
	int			bucket;
	int			dpct;
	int			error, saved_error = 0;
	xfs_agnumber_t		nagcount;
	xfs_agnumber_t		nagimax = 0;
	xfs_rfsblock_t		nb, nb_mod;
	xfs_rfsblock_t		new;
	xfs_rfsblock_t		nfree;
	xfs_agnumber_t		oagcount;
	int			pct;
	xfs_trans_t		*tp;

	nb = in->newblocks;
	pct = in->imaxpct;
	if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100)
		return -EINVAL;
	if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
		return error;
	dpct = pct - mp->m_sb.sb_imax_pct;
	error = xfs_buf_read_uncached(mp->m_ddev_targp,
				XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
				XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
	if (error)
		return error;
	xfs_buf_relse(bp);

	new = nb;	/* use new as a temporary here */
	nb_mod = do_div(new, mp->m_sb.sb_agblocks);
	nagcount = new + (nb_mod != 0);
	if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) {
		nagcount--;
		nb = (xfs_rfsblock_t)nagcount * mp->m_sb.sb_agblocks;
		if (nb < mp->m_sb.sb_dblocks)
			return -EINVAL;
	}
	new = nb - mp->m_sb.sb_dblocks;
	oagcount = mp->m_sb.sb_agcount;

	/* allocate the new per-ag structures */
	if (nagcount > oagcount) {
		error = xfs_initialize_perag(mp, nagcount, &nagimax);
		if (error)
			return error;
	}

	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata,
			XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp);
	if (error)
		return error;

/*
 * Write new AG headers to disk. Non-transactional, but written
 * synchronously so they are completed prior to the growfs transaction
 * being logged.
 */
	nfree = 0;
	for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {
static int
xfs_grow_ag_headers(
	struct xfs_mount	*mp,
	xfs_agnumber_t		agno,
	xfs_extlen_t		agsize,
	xfs_rfsblock_t		*nfree)
{
	struct xfs_agf		*agf;
	struct xfs_agi		*agi;
	struct xfs_agfl		*agfl;
	__be32			*agfl_bno;
	xfs_alloc_rec_t		*arec;
	struct xfs_buf		*bp;
	int			bucket;
	xfs_extlen_t		tmpsize;
	int			error = 0;

	/*
	 * AG freespace header block
@@ -152,19 +102,13 @@ xfs_growfs_data_private(
			&xfs_agf_buf_ops);
	if (!bp) {
		error = -ENOMEM;
			goto error0;
		goto out_error;
	}

	agf = XFS_BUF_TO_AGF(bp);
	agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);
	agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);
	agf->agf_seqno = cpu_to_be32(agno);
		if (agno == nagcount - 1)
			agsize =
				nb -
				(agno * (xfs_rfsblock_t)mp->m_sb.sb_agblocks);
		else
			agsize = mp->m_sb.sb_agblocks;
	agf->agf_length = cpu_to_be32(agsize);
	agf->agf_roots[XFS_BTNUM_BNOi] = cpu_to_be32(XFS_BNO_BLOCK(mp));
	agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
@@ -195,7 +139,7 @@ xfs_growfs_data_private(
	error = xfs_bwrite(bp);
	xfs_buf_relse(bp);
	if (error)
			goto error0;
		goto out_error;

	/*
	 * AG freelist header block
@@ -206,7 +150,7 @@ xfs_growfs_data_private(
			&xfs_agfl_buf_ops);
	if (!bp) {
		error = -ENOMEM;
			goto error0;
		goto out_error;
	}

	agfl = XFS_BUF_TO_AGFL(bp);
@@ -223,7 +167,7 @@ xfs_growfs_data_private(
	error = xfs_bwrite(bp);
	xfs_buf_relse(bp);
	if (error)
			goto error0;
		goto out_error;

	/*
	 * AG inode header block
@@ -234,7 +178,7 @@ xfs_growfs_data_private(
			&xfs_agi_buf_ops);
	if (!bp) {
		error = -ENOMEM;
			goto error0;
		goto out_error;
	}

	agi = XFS_BUF_TO_AGI(bp);
@@ -260,7 +204,7 @@ xfs_growfs_data_private(
	error = xfs_bwrite(bp);
	xfs_buf_relse(bp);
	if (error)
			goto error0;
		goto out_error;

	/*
	 * BNO btree root block
@@ -272,7 +216,7 @@ xfs_growfs_data_private(

	if (!bp) {
		error = -ENOMEM;
			goto error0;
		goto out_error;
	}

	xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 1, agno, 0);
@@ -285,7 +229,7 @@ xfs_growfs_data_private(
	error = xfs_bwrite(bp);
	xfs_buf_relse(bp);
	if (error)
			goto error0;
		goto out_error;

	/*
	 * CNT btree root block
@@ -296,7 +240,7 @@ xfs_growfs_data_private(
			&xfs_allocbt_buf_ops);
	if (!bp) {
		error = -ENOMEM;
			goto error0;
		goto out_error;
	}

	xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 1, agno, 0);
@@ -305,12 +249,12 @@ xfs_growfs_data_private(
	arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);
	arec->ar_blockcount = cpu_to_be32(
		agsize - be32_to_cpu(arec->ar_startblock));
		nfree += be32_to_cpu(arec->ar_blockcount);
	*nfree += be32_to_cpu(arec->ar_blockcount);

	error = xfs_bwrite(bp);
	xfs_buf_relse(bp);
	if (error)
			goto error0;
		goto out_error;

	/* RMAP btree root block */
	if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
@@ -323,7 +267,7 @@ xfs_growfs_data_private(
			&xfs_rmapbt_buf_ops);
		if (!bp) {
			error = -ENOMEM;
				goto error0;
			goto out_error;
		}

		xfs_btree_init_block(mp, bp, XFS_BTNUM_RMAP, 0, 0,
@@ -375,8 +319,7 @@ xfs_growfs_data_private(
		/* account for refc btree root */
		if (xfs_sb_version_hasreflink(&mp->m_sb)) {
			rrec = XFS_RMAP_REC_ADDR(block, 5);
				rrec->rm_startblock = cpu_to_be32(
						xfs_refc_block(mp));
			rrec->rm_startblock = cpu_to_be32(xfs_refc_block(mp));
			rrec->rm_blockcount = cpu_to_be32(1);
			rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC);
			rrec->rm_offset = 0;
@@ -386,7 +329,7 @@ xfs_growfs_data_private(
		error = xfs_bwrite(bp);
		xfs_buf_relse(bp);
		if (error)
				goto error0;
			goto out_error;
	}

	/*
@@ -398,7 +341,7 @@ xfs_growfs_data_private(
			&xfs_inobt_buf_ops);
	if (!bp) {
		error = -ENOMEM;
			goto error0;
		goto out_error;
	}

	xfs_btree_init_block(mp, bp, XFS_BTNUM_INO , 0, 0, agno, 0);
@@ -406,7 +349,7 @@ xfs_growfs_data_private(
	error = xfs_bwrite(bp);
	xfs_buf_relse(bp);
	if (error)
			goto error0;
		goto out_error;

	/*
	 * FINO btree root block
@@ -418,7 +361,7 @@ xfs_growfs_data_private(
			&xfs_inobt_buf_ops);
		if (!bp) {
			error = -ENOMEM;
				goto error0;
			goto out_error;
		}

		xfs_btree_init_block(mp, bp, XFS_BTNUM_FINO,
@@ -427,7 +370,7 @@ xfs_growfs_data_private(
		error = xfs_bwrite(bp);
		xfs_buf_relse(bp);
		if (error)
				goto error0;
			goto out_error;
	}

	/*
@@ -440,7 +383,7 @@ xfs_growfs_data_private(
			&xfs_refcountbt_buf_ops);
		if (!bp) {
			error = -ENOMEM;
				goto error0;
			goto out_error;
		}

		xfs_btree_init_block(mp, bp, XFS_BTNUM_REFC,
@@ -449,10 +392,92 @@ xfs_growfs_data_private(
		error = xfs_bwrite(bp);
		xfs_buf_relse(bp);
		if (error)
				goto error0;
			goto out_error;
	}

out_error:
	return error;
}

static int
xfs_growfs_data_private(
	xfs_mount_t		*mp,		/* mount point for filesystem */
	xfs_growfs_data_t	*in)		/* growfs data input struct */
{
	xfs_agf_t		*agf;
	xfs_agi_t		*agi;
	xfs_agnumber_t		agno;
	xfs_extlen_t		agsize;
	xfs_buf_t		*bp;
	int			dpct;
	int			error, saved_error = 0;
	xfs_agnumber_t		nagcount;
	xfs_agnumber_t		nagimax = 0;
	xfs_rfsblock_t		nb, nb_mod;
	xfs_rfsblock_t		new;
	xfs_rfsblock_t		nfree;
	xfs_agnumber_t		oagcount;
	int			pct;
	xfs_trans_t		*tp;

	nb = in->newblocks;
	pct = in->imaxpct;
	if (nb < mp->m_sb.sb_dblocks || pct < 0 || pct > 100)
		return -EINVAL;
	if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
		return error;
	dpct = pct - mp->m_sb.sb_imax_pct;
	error = xfs_buf_read_uncached(mp->m_ddev_targp,
				XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
				XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
	if (error)
		return error;
	xfs_buf_relse(bp);

	new = nb;	/* use new as a temporary here */
	nb_mod = do_div(new, mp->m_sb.sb_agblocks);
	nagcount = new + (nb_mod != 0);
	if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) {
		nagcount--;
		nb = (xfs_rfsblock_t)nagcount * mp->m_sb.sb_agblocks;
		if (nb < mp->m_sb.sb_dblocks)
			return -EINVAL;
	}
	new = nb - mp->m_sb.sb_dblocks;
	oagcount = mp->m_sb.sb_agcount;

	/* allocate the new per-ag structures */
	if (nagcount > oagcount) {
		error = xfs_initialize_perag(mp, nagcount, &nagimax);
		if (error)
			return error;
	}

	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata,
			XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp);
	if (error)
		return error;

	/*
	 * Write new AG headers to disk. Non-transactional, but written
	 * synchronously so they are completed prior to the growfs transaction
	 * being logged.
	 */
	nfree = 0;
	for (agno = nagcount - 1; agno >= oagcount; agno--, new -= agsize) {

		if (agno == nagcount - 1)
			agsize = nb -
				(agno * (xfs_rfsblock_t)mp->m_sb.sb_agblocks);
		else
			agsize = mp->m_sb.sb_agblocks;

		error = xfs_grow_ag_headers(mp, agno, agsize, &nfree);
		if (error)
			goto error0;
	}
	xfs_trans_agblocks_delta(tp, nfree);

	/*
	 * There are new blocks in the old last a.g.
	 */