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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox