From: Michal Hocko <mhocko@suse.com>
To: Vlastimil Babka <vbabka@suse.cz>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Suren Baghdasaryan <surenb@google.com>,
Brendan Jackman <jackmanb@google.com>,
Johannes Weiner <hannes@cmpxchg.org>, Zi Yan <ziy@nvidia.com>,
David Rientjes <rientjes@google.com>,
David Hildenbrand <david@kernel.org>,
Lorenzo Stoakes <lorenzo.stoakes@oracle.com>,
"Liam R. Howlett" <Liam.Howlett@oracle.com>,
Mike Rapoport <rppt@kernel.org>,
Joshua Hahn <joshua.hahnjy@gmail.com>,
Pedro Falcato <pfalcato@suse.de>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH mm-unstable v3 2/3] mm/page_alloc: refactor the initial compaction handling
Date: Tue, 6 Jan 2026 14:56:24 +0100 [thread overview]
Message-ID: <aV0UiNM1BXo17meQ@tiehlicka> (raw)
In-Reply-To: <20260106-thp-thisnode-tweak-v3-2-f5d67c21a193@suse.cz>
On Tue 06-01-26 12:52:37, Vlastimil Babka wrote:
> The initial direct compaction done in some cases in
> __alloc_pages_slowpath() stands out from the main retry loop of
> reclaim + compaction.
>
> We can simplify this by instead skipping the initial reclaim attempt via
> a new local variable compact_first, and handle the compact_prority as
> necessary to match the original behavior. No functional change intended.
>
> Suggested-by: Johannes Weiner <hannes@cmpxchg.org>
> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
> Reviewed-by: Joshua Hahn <joshua.hahnjy@gmail.com>
LGTM and it makes the code flow easier to follow
Acked-by: Michal Hocko <mhocko@suse.com>
> ---
> include/linux/gfp.h | 8 ++++-
> mm/page_alloc.c | 100 +++++++++++++++++++++++++---------------------------
> 2 files changed, 55 insertions(+), 53 deletions(-)
>
> diff --git a/include/linux/gfp.h b/include/linux/gfp.h
> index aa45989f410d..6ecf6dda93e0 100644
> --- a/include/linux/gfp.h
> +++ b/include/linux/gfp.h
> @@ -407,9 +407,15 @@ extern gfp_t gfp_allowed_mask;
> /* Returns true if the gfp_mask allows use of ALLOC_NO_WATERMARK */
> bool gfp_pfmemalloc_allowed(gfp_t gfp_mask);
>
> +/* A helper for checking if gfp includes all the specified flags */
> +static inline bool gfp_has_flags(gfp_t gfp, gfp_t flags)
> +{
> + return (gfp & flags) == flags;
> +}
> +
> static inline bool gfp_has_io_fs(gfp_t gfp)
> {
> - return (gfp & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS);
> + return gfp_has_flags(gfp, __GFP_IO | __GFP_FS);
> }
>
> /*
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index b06b1cb01e0e..3b2579c5716f 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -4702,7 +4702,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
> struct alloc_context *ac)
> {
> bool can_direct_reclaim = gfp_mask & __GFP_DIRECT_RECLAIM;
> - bool can_compact = gfp_compaction_allowed(gfp_mask);
> + bool can_compact = can_direct_reclaim && gfp_compaction_allowed(gfp_mask);
> bool nofail = gfp_mask & __GFP_NOFAIL;
> const bool costly_order = order > PAGE_ALLOC_COSTLY_ORDER;
> struct page *page = NULL;
> @@ -4715,6 +4715,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
> unsigned int cpuset_mems_cookie;
> unsigned int zonelist_iter_cookie;
> int reserve_flags;
> + bool compact_first = false;
>
> if (unlikely(nofail)) {
> /*
> @@ -4738,6 +4739,19 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
> cpuset_mems_cookie = read_mems_allowed_begin();
> zonelist_iter_cookie = zonelist_iter_begin();
>
> + /*
> + * For costly allocations, try direct compaction first, as it's likely
> + * that we have enough base pages and don't need to reclaim. For non-
> + * movable high-order allocations, do that as well, as compaction will
> + * try prevent permanent fragmentation by migrating from blocks of the
> + * same migratetype.
> + */
> + if (can_compact && (costly_order || (order > 0 &&
> + ac->migratetype != MIGRATE_MOVABLE))) {
> + compact_first = true;
> + compact_priority = INIT_COMPACT_PRIORITY;
> + }
> +
> /*
> * The fast path uses conservative alloc_flags to succeed only until
> * kswapd needs to be woken up, and to avoid the cost of setting up
> @@ -4780,53 +4794,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
> if (page)
> goto got_pg;
>
> - /*
> - * For costly allocations, try direct compaction first, as it's likely
> - * that we have enough base pages and don't need to reclaim. For non-
> - * movable high-order allocations, do that as well, as compaction will
> - * try prevent permanent fragmentation by migrating from blocks of the
> - * same migratetype.
> - * Don't try this for allocations that are allowed to ignore
> - * watermarks, as the ALLOC_NO_WATERMARKS attempt didn't yet happen.
> - */
> - if (can_direct_reclaim && can_compact &&
> - (costly_order ||
> - (order > 0 && ac->migratetype != MIGRATE_MOVABLE))
> - && !gfp_pfmemalloc_allowed(gfp_mask)) {
> - page = __alloc_pages_direct_compact(gfp_mask, order,
> - alloc_flags, ac,
> - INIT_COMPACT_PRIORITY,
> - &compact_result);
> - if (page)
> - goto got_pg;
> -
> - /*
> - * Checks for costly allocations with __GFP_NORETRY, which
> - * includes some THP page fault allocations
> - */
> - if (costly_order && (gfp_mask & __GFP_NORETRY)) {
> - /*
> - * THP page faults may attempt local node only first,
> - * but are then allowed to only compact, not reclaim,
> - * see alloc_pages_mpol().
> - *
> - * Compaction has failed above and we don't want such
> - * THP allocations to put reclaim pressure on a single
> - * node in a situation where other nodes might have
> - * plenty of available memory.
> - */
> - if (gfp_mask & __GFP_THISNODE)
> - goto nopage;
> -
> - /*
> - * Proceed with single round of reclaim/compaction, but
> - * since sync compaction could be very expensive, keep
> - * using async compaction.
> - */
> - compact_priority = INIT_COMPACT_PRIORITY;
> - }
> - }
> -
> retry:
> /*
> * Deal with possible cpuset update races or zonelist updates to avoid
> @@ -4870,10 +4837,12 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
> goto nopage;
>
> /* Try direct reclaim and then allocating */
> - page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags, ac,
> - &did_some_progress);
> - if (page)
> - goto got_pg;
> + if (!compact_first) {
> + page = __alloc_pages_direct_reclaim(gfp_mask, order, alloc_flags,
> + ac, &did_some_progress);
> + if (page)
> + goto got_pg;
> + }
>
> /* Try direct compaction and then allocating */
> page = __alloc_pages_direct_compact(gfp_mask, order, alloc_flags, ac,
> @@ -4881,6 +4850,33 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
> if (page)
> goto got_pg;
>
> + if (compact_first) {
> + /*
> + * THP page faults may attempt local node only first, but are
> + * then allowed to only compact, not reclaim, see
> + * alloc_pages_mpol().
> + *
> + * Compaction has failed above and we don't want such THP
> + * allocations to put reclaim pressure on a single node in a
> + * situation where other nodes might have plenty of available
> + * memory.
> + */
> + if (gfp_has_flags(gfp_mask, __GFP_NORETRY | __GFP_THISNODE))
> + goto nopage;
> +
> + /*
> + * For the initial compaction attempt we have lowered its
> + * priority. Restore it for further retries, if those are
> + * allowed. With __GFP_NORETRY there will be a single round of
> + * reclaim and compaction with the lowered priority.
> + */
> + if (!(gfp_mask & __GFP_NORETRY))
> + compact_priority = DEF_COMPACT_PRIORITY;
> +
> + compact_first = false;
> + goto retry;
> + }
> +
> /* Do not loop if specifically requested */
> if (gfp_mask & __GFP_NORETRY)
> goto nopage;
>
> --
> 2.52.0
--
Michal Hocko
SUSE Labs
next prev parent reply other threads:[~2026-01-06 13:56 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-06 11:52 [PATCH mm-unstable v3 0/3] tweaks for __alloc_pages_slowpath() Vlastimil Babka
2026-01-06 11:52 ` [PATCH mm-unstable v3 1/3] mm/page_alloc: ignore the exact initial compaction result Vlastimil Babka
2026-01-06 13:51 ` Michal Hocko
2026-01-06 11:52 ` [PATCH mm-unstable v3 2/3] mm/page_alloc: refactor the initial compaction handling Vlastimil Babka
2026-01-06 13:56 ` Michal Hocko [this message]
2026-01-06 11:52 ` [PATCH mm-unstable v3 3/3] mm/page_alloc: simplify __alloc_pages_slowpath() flow Vlastimil Babka
2026-01-06 14:00 ` Michal Hocko
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=aV0UiNM1BXo17meQ@tiehlicka \
--to=mhocko@suse.com \
--cc=Liam.Howlett@oracle.com \
--cc=akpm@linux-foundation.org \
--cc=david@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=jackmanb@google.com \
--cc=joshua.hahnjy@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=pfalcato@suse.de \
--cc=rientjes@google.com \
--cc=rppt@kernel.org \
--cc=surenb@google.com \
--cc=vbabka@suse.cz \
--cc=ziy@nvidia.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.