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
>
>
next prev parent 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