Linux XFS filesystem development
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: Brian Foster <bfoster@redhat.com>
Cc: linux-xfs@vger.kernel.org, Carlos Maiolino <cem@kernel.org>
Subject: Re: [PATCH v4 3/4] xfs: calculate AGFL max to support multiple-alloc transactions
Date: Wed, 23 Sep 2026 17:38:02 -0700	[thread overview]
Message-ID: <20260924003802.GG2705364@frogsfrogsfrogs> (raw)
In-Reply-To: <20260923161524.416059-4-bfoster@redhat.com>

On Wed, Sep 23, 2026 at 12:15:23PM -0400, Brian Foster wrote:
> Rework xfs_alloc_min_freelist() to return an (optional) max value
> along with the historical min freelist value. The max value
> includes an extra level in the btree based calculation to account
> for btree splits in the first allocation of a multi-alloc sequence.
> 
> This value reflects the worst case AGFL requirement that can be
> expected across multiple allocations within a single AG and single
> transaction. For example, consider the case of allocating an inode
> chunk and then an inobt block on inode record insertion.
> 
> While here, rename the need variable in xfs_alloc_fix_freelist() for
> clarity with upcoming changes.
> 
> Note that no callers calculate the max AGFL value as of yet. No
> functional changes in this patch.
> 
> Assisted-by: LLM
> Signed-off-by: Brian Foster <bfoster@redhat.com>
> Reviewed-by: Mark Tinguely <mark.tinguely@oracle.com>

Looks fine to me
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>

--D

> ---
>  fs/xfs/libxfs/xfs_alloc.c  | 35 ++++++++++++++++++++++-------------
>  fs/xfs/libxfs/xfs_alloc.h  |  4 ++--
>  fs/xfs/libxfs/xfs_bmap.c   |  5 +++--
>  fs/xfs/libxfs/xfs_ialloc.c |  4 +++-
>  4 files changed, 30 insertions(+), 18 deletions(-)
> 
> diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
> index b2525c58051b..af63926cc9ee 100644
> --- a/fs/xfs/libxfs/xfs_alloc.c
> +++ b/fs/xfs/libxfs/xfs_alloc.c
> @@ -2445,7 +2445,7 @@ xfs_alloc_longest_free_extent(
>   * multi-allocation transactions.
>   */
>  static unsigned int
> -__xfs_alloc_min_freelist(
> +__xfs_alloc_freelist(
>  	struct xfs_mount	*mp,
>  	struct xfs_perag	*pag,
>  	unsigned int		extra_levels)
> @@ -2492,12 +2492,21 @@ __xfs_alloc_min_freelist(
>  	return min_free;
>  }
>  
> -unsigned int
> -xfs_alloc_min_freelist(
> +/*
> + * Compute the minimum and maximum length of the AGFL in the given AG. The max
> + * value in this context refers to the max requirement the AG might see in a
> + * multi-alloc transaction. If @pag is NULL, return the largest possible values.
> + */
> +void
> +xfs_alloc_freelist(
>  	struct xfs_mount	*mp,
> -	struct xfs_perag	*pag)
> +	struct xfs_perag	*pag,
> +	unsigned int		*min_free,
> +	unsigned int		*max_free)
>  {
> -	return __xfs_alloc_min_freelist(mp, pag, 0);
> +	*min_free = __xfs_alloc_freelist(mp, pag, 0);
> +	if (max_free)
> +		*max_free = __xfs_alloc_freelist(mp, pag, 1);
>  }
>  
>  /*
> @@ -2849,7 +2858,7 @@ xfs_alloc_fix_freelist(
>  	struct xfs_buf		*agflbp = NULL;
>  	struct xfs_alloc_arg	targs;	/* local allocation arguments */
>  	xfs_agblock_t		bno;	/* freelist block */
> -	xfs_extlen_t		need;	/* total blocks needed in freelist */
> +	xfs_extlen_t		min_free;/* total blocks needed in freelist */
>  	int			error = 0;
>  
>  	/* deferred ops (AGFL block frees) require permanent transactions */
> @@ -2877,8 +2886,8 @@ xfs_alloc_fix_freelist(
>  		goto out_agbp_relse;
>  	}
>  
> -	need = xfs_alloc_min_freelist(mp, pag);
> -	if (!xfs_alloc_space_available(args, need, alloc_flags |
> +	xfs_alloc_freelist(mp, pag, &min_free, NULL);
> +	if (!xfs_alloc_space_available(args, min_free, alloc_flags |
>  			XFS_ALLOC_FLAG_CHECK))
>  		goto out_agbp_relse;
>  
> @@ -2901,8 +2910,8 @@ xfs_alloc_fix_freelist(
>  		xfs_agfl_reset(tp, agbp, pag);
>  
>  	/* If there isn't enough total space or single-extent, reject it. */
> -	need = xfs_alloc_min_freelist(mp, pag);
> -	if (!xfs_alloc_space_available(args, need, alloc_flags))
> +	xfs_alloc_freelist(mp, pag, &min_free, NULL);
> +	if (!xfs_alloc_space_available(args, min_free, alloc_flags))
>  		goto out_agbp_relse;
>  
>  	if (IS_ENABLED(CONFIG_XFS_DEBUG) && args->alloc_minlen_only) {
> @@ -2944,7 +2953,7 @@ xfs_alloc_fix_freelist(
>  	else
>  		targs.oinfo = XFS_RMAP_OINFO_AG;
>  	while (!(alloc_flags & XFS_ALLOC_FLAG_NOSHRINK) &&
> -			pag->pagf_flcount > need) {
> +			pag->pagf_flcount > min_free) {
>  		error = xfs_alloc_get_freelist(pag, tp, agbp, &bno, 0);
>  		if (error)
>  			goto out_agbp_relse;
> @@ -2978,9 +2987,9 @@ xfs_alloc_fix_freelist(
>  		goto out_agbp_relse;
>  
>  	/* Make the freelist longer if it's too short. */
> -	while (pag->pagf_flcount < need) {
> +	while (pag->pagf_flcount < min_free) {
>  		targs.agbno = 0;
> -		targs.maxlen = need - pag->pagf_flcount;
> +		targs.maxlen = min_free - pag->pagf_flcount;
>  		targs.resv = XFS_AG_RESV_AGFL;
>  
>  		/* Allocate as many blocks as possible at once. */
> diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
> index 50ef79a1ed41..44a10f4a22a2 100644
> --- a/fs/xfs/libxfs/xfs_alloc.h
> +++ b/fs/xfs/libxfs/xfs_alloc.h
> @@ -71,8 +71,8 @@ unsigned int xfs_alloc_ag_max_usable(struct xfs_mount *mp);
>  
>  xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_perag *pag,
>  		xfs_extlen_t need, xfs_extlen_t reserved);
> -unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp,
> -		struct xfs_perag *pag);
> +void xfs_alloc_freelist(struct xfs_mount *mp, struct xfs_perag *pag,
> +		unsigned int *min_free, unsigned int *max_free);
>  int xfs_alloc_get_freelist(struct xfs_perag *pag, struct xfs_trans *tp,
>  		struct xfs_buf *agfbp, xfs_agblock_t *bnop, int	 btreeblk);
>  int xfs_alloc_put_freelist(struct xfs_perag *pag, struct xfs_trans *tp,
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index ae91f63455c5..d6be6734bd90 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -3149,6 +3149,7 @@ xfs_bmap_longest_free_extent(
>  	xfs_extlen_t		*blen)
>  {
>  	xfs_extlen_t		longest;
> +	unsigned int		min_free;
>  	int			error = 0;
>  
>  	if (!xfs_perag_initialised_agf(pag)) {
> @@ -3158,8 +3159,8 @@ xfs_bmap_longest_free_extent(
>  			return error;
>  	}
>  
> -	longest = xfs_alloc_longest_free_extent(pag,
> -				xfs_alloc_min_freelist(pag_mount(pag), pag),
> +	xfs_alloc_freelist(pag_mount(pag), pag, &min_free, NULL);
> +	longest = xfs_alloc_longest_free_extent(pag, min_free,
>  				xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE));
>  	if (*blen < longest)
>  		*blen = longest;
> diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
> index e31611cabd4d..e705f681ed44 100644
> --- a/fs/xfs/libxfs/xfs_ialloc.c
> +++ b/fs/xfs/libxfs/xfs_ialloc.c
> @@ -3074,6 +3074,7 @@ xfs_ialloc_calc_rootino(
>  {
>  	struct xfs_ino_geometry	*igeo = M_IGEO(mp);
>  	xfs_agblock_t		first_bno;
> +	unsigned int		min_free;
>  
>  	/*
>  	 * Pre-calculate the geometry of AG 0.  We know what it looks like
> @@ -3092,7 +3093,8 @@ xfs_ialloc_calc_rootino(
>  	first_bno += 1;
>  
>  	/* ...the initial AGFL... */
> -	first_bno += xfs_alloc_min_freelist(mp, NULL);
> +	xfs_alloc_freelist(mp, NULL, &min_free, NULL);
> +	first_bno += min_free;
>  
>  	/* ...the free inode btree root... */
>  	if (xfs_has_finobt(mp))
> -- 
> 2.55.0
> 
> 

  reply	other threads:[~2026-09-24  0:38 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-23 16:15 [PATCH v4 0/4] xfs: fix a couple sparse chunk alloc problems Brian Foster
2026-09-23 16:15 ` [PATCH v4 1/4] xfs: set minleft correctly for sparse chunk errortag allocation Brian Foster
2026-09-23 16:15 ` [PATCH v4 2/4] xfs: support additional levels in the agfl minimum calculation Brian Foster
2026-09-23 16:15 ` [PATCH v4 3/4] xfs: calculate AGFL max to support multiple-alloc transactions Brian Foster
2026-09-24  0:38   ` Darrick J. Wong [this message]
2026-09-23 16:15 ` [PATCH v4 4/4] xfs: incorporate increased AGFL min requirement for minleft allocs Brian Foster
2026-09-24  1:15   ` Darrick J. Wong
2026-09-24 13:14     ` Brian Foster
2026-09-24 18:56       ` Darrick J. Wong
2026-09-25 18:48         ` Brian Foster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260924003802.GG2705364@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=bfoster@redhat.com \
    --cc=cem@kernel.org \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox