Commit 82742f8c authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Carlos Maiolino
Browse files

xfs: pass the exact range to initialize to xfs_initialize_perag



Currently only the new agcount is passed to xfs_initialize_perag, which
requires lookups of existing AGs to skip them and complicates error
handling.  Also pass the previous agcount so that the range that
xfs_initialize_perag operates on is exactly defined.  That way the
extra lookups can be avoided, and error handling can clean up the
exact range from the old count to the last added perag structure.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Signed-off-by: default avatarCarlos Maiolino <cem@kernel.org>
parent af8512c5
Loading
Loading
Loading
Loading
+6 −22
Original line number Diff line number Diff line
@@ -296,27 +296,16 @@ xfs_free_unused_perag_range(
int
xfs_initialize_perag(
	struct xfs_mount	*mp,
	xfs_agnumber_t		agcount,
	xfs_agnumber_t		old_agcount,
	xfs_agnumber_t		new_agcount,
	xfs_rfsblock_t		dblocks,
	xfs_agnumber_t		*maxagi)
{
	struct xfs_perag	*pag;
	xfs_agnumber_t		index;
	xfs_agnumber_t		first_initialised = NULLAGNUMBER;
	int			error;

	/*
	 * Walk the current per-ag tree so we don't try to initialise AGs
	 * that already exist (growfs case). Allocate and insert all the
	 * AGs we don't find ready for initialisation.
	 */
	for (index = 0; index < agcount; index++) {
		pag = xfs_perag_get(mp, index);
		if (pag) {
			xfs_perag_put(pag);
			continue;
		}

	for (index = old_agcount; index < new_agcount; index++) {
		pag = kzalloc(sizeof(*pag), GFP_KERNEL | __GFP_RETRY_MAYFAIL);
		if (!pag) {
			error = -ENOMEM;
@@ -353,21 +342,17 @@ xfs_initialize_perag(
		/* Active ref owned by mount indicates AG is online. */
		atomic_set(&pag->pag_active_ref, 1);

		/* first new pag is fully initialized */
		if (first_initialised == NULLAGNUMBER)
			first_initialised = index;

		/*
		 * Pre-calculated geometry
		 */
		pag->block_count = __xfs_ag_block_count(mp, index, agcount,
		pag->block_count = __xfs_ag_block_count(mp, index, new_agcount,
				dblocks);
		pag->min_block = XFS_AGFL_BLOCK(mp);
		__xfs_agino_range(mp, pag->block_count, &pag->agino_min,
				&pag->agino_max);
	}

	index = xfs_set_inode_alloc(mp, agcount);
	index = xfs_set_inode_alloc(mp, new_agcount);

	if (maxagi)
		*maxagi = index;
@@ -381,8 +366,7 @@ xfs_initialize_perag(
out_free_pag:
	kfree(pag);
out_unwind_new_pags:
	/* unwind any prior newly initialized pags */
	xfs_free_unused_perag_range(mp, first_initialised, agcount);
	xfs_free_unused_perag_range(mp, old_agcount, index);
	return error;
}

+3 −2
Original line number Diff line number Diff line
@@ -146,8 +146,9 @@ __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)

void xfs_free_unused_perag_range(struct xfs_mount *mp, xfs_agnumber_t agstart,
			xfs_agnumber_t agend);
int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
			xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t old_agcount,
		xfs_agnumber_t agcount, xfs_rfsblock_t dcount,
		xfs_agnumber_t *maxagi);
int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
void xfs_free_perag(struct xfs_mount *mp);

+8 −10
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ xfs_growfs_data_private(
	struct xfs_mount	*mp,		/* mount point for filesystem */
	struct xfs_growfs_data	*in)		/* growfs data input struct */
{
	xfs_agnumber_t		oagcount = mp->m_sb.sb_agcount;
	struct xfs_buf		*bp;
	int			error;
	xfs_agnumber_t		nagcount;
@@ -94,7 +95,6 @@ xfs_growfs_data_private(
	xfs_rfsblock_t		nb, nb_div, nb_mod;
	int64_t			delta;
	bool			lastag_extended = false;
	xfs_agnumber_t		oagcount;
	struct xfs_trans	*tp;
	struct aghdr_init_data	id = {};
	struct xfs_perag	*last_pag;
@@ -138,16 +138,14 @@ xfs_growfs_data_private(
	if (delta == 0)
		return 0;

	oagcount = mp->m_sb.sb_agcount;
	/* TODO: shrinking the entire AGs hasn't yet completed */
	if (nagcount < oagcount)
		return -EINVAL;

	/* allocate the new per-ag structures */
	if (nagcount > oagcount) {
		error = xfs_initialize_perag(mp, nagcount, nb, &nagimax);
	error = xfs_initialize_perag(mp, oagcount, nagcount, nb, &nagimax);
	if (error)
		return error;
	} else if (nagcount < oagcount) {
		/* TODO: shrinking the entire AGs hasn't yet completed */
		return -EINVAL;
	}

	if (delta > 0)
		error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata,
+3 −2
Original line number Diff line number Diff line
@@ -3346,6 +3346,7 @@ xlog_do_recover(
	struct xfs_mount	*mp = log->l_mp;
	struct xfs_buf		*bp = mp->m_sb_bp;
	struct xfs_sb		*sbp = &mp->m_sb;
	xfs_agnumber_t		orig_agcount = sbp->sb_agcount;
	int			error;

	trace_xfs_log_recover(log, head_blk, tail_blk);
@@ -3393,8 +3394,8 @@ xlog_do_recover(
	/* re-initialise in-core superblock and geometry structures */
	mp->m_features |= xfs_sb_version_to_features(sbp);
	xfs_reinit_percpu_counters(mp);
	error = xfs_initialize_perag(mp, sbp->sb_agcount, sbp->sb_dblocks,
			&mp->m_maxagi);
	error = xfs_initialize_perag(mp, orig_agcount, sbp->sb_agcount,
			sbp->sb_dblocks, &mp->m_maxagi);
	if (error) {
		xfs_warn(mp, "Failed post-recovery per-ag init: %d", error);
		return error;
+2 −2
Original line number Diff line number Diff line
@@ -810,8 +810,8 @@ xfs_mountfs(
	/*
	 * Allocate and initialize the per-ag data.
	 */
	error = xfs_initialize_perag(mp, sbp->sb_agcount, mp->m_sb.sb_dblocks,
			&mp->m_maxagi);
	error = xfs_initialize_perag(mp, 0, sbp->sb_agcount,
			mp->m_sb.sb_dblocks, &mp->m_maxagi);
	if (error) {
		xfs_warn(mp, "Failed per-ag init: %d", error);
		goto out_free_dir;