mm: let node_reclaim() return the number of pages reclaimed

There is only one caller, get_page_from_freelist(), and it does not make
any use of the reason for skipping the reclaim, nor does it make any
distinction between a full and partially successful reclaim.

Therefore, node_reclaim() can simply return the number of pages that have
been reclaimed, same as __node_reclaim(), and the NODE_RECLAIM_xxx macros
can be removed.

There is one small change of behavior when __node_reclaim() was attempted
but returned zero.  The allocation now skips the zone immediately; before
this patch, the zone watermarks were checked first.  I believe it was an
oversight rather than intention, because the chances that zone watermark
is OK after __node_reclaim() did not reclaim any pages are very close to
zero.

Originally, I was looking for occurences of NODE_RECLAIM_SOME and
NODE_RECLAIM_SUCCESS, but I couldn't find any.  That's because they are
typecast from the result of a relational operator.  This seemed a bit
fragile, so I dug a bit deeper and came up with this proposed cleanup.

Link: https://lore.kernel.org/20260714132300.2136018-1-ptesarik@suse.com
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Reviewed-by: Zi Yan <ziy@nvidia.com>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: Brendan Jackman <jackmanb@google.com>
Cc: Brendan Jackman <brendan.jackman@linux.dev>
Cc: David Hildenbrand <david@kernel.org>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Petr Tesarik
2026-07-14 15:23:00 +02:00
committed by Andrew Morton
parent 8315cf471e
commit ff3d40545f
3 changed files with 17 additions and 32 deletions

View File

@@ -1098,23 +1098,19 @@ static inline void mlock_drain_local(void) { }
static inline void mlock_drain_remote(int cpu) { }
#endif /* !CONFIG_MMU */
#define NODE_RECLAIM_NOSCAN -2
#define NODE_RECLAIM_FULL -1
#define NODE_RECLAIM_SOME 0
#define NODE_RECLAIM_SUCCESS 1
#ifdef CONFIG_NUMA
extern int node_reclaim_mode;
extern int node_reclaim(struct pglist_data *, gfp_t, unsigned int);
extern unsigned long node_reclaim(struct pglist_data *pgdat,
gfp_t gfp_mask, unsigned int order);
extern int find_next_best_node(int node, nodemask_t *used_node_mask);
#else
#define node_reclaim_mode 0
static inline int node_reclaim(struct pglist_data *pgdat, gfp_t mask,
unsigned int order)
static inline unsigned long node_reclaim(struct pglist_data *pgdat,
gfp_t mask, unsigned int order)
{
return NODE_RECLAIM_NOSCAN;
return 0;
}
static inline int find_next_best_node(int node, nodemask_t *used_node_mask)
{

View File

@@ -3908,8 +3908,6 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
if (!zone_watermark_fast(zone, order, mark,
ac->highest_zoneidx, alloc_flags,
gfp_mask)) {
int ret;
if (cond_accept_memory(zone, order, alloc_flags))
goto try_this_zone;
@@ -3930,22 +3928,13 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
!zone_allows_reclaim(zonelist_zone(ac->preferred_zoneref), zone))
continue;
ret = node_reclaim(zone->zone_pgdat, gfp_mask, order);
switch (ret) {
case NODE_RECLAIM_NOSCAN:
/* did not scan */
if (!node_reclaim(zone->zone_pgdat, gfp_mask, order))
continue;
case NODE_RECLAIM_FULL:
/* scanned but unreclaimable */
continue;
default:
/* did we reclaim enough */
if (zone_watermark_ok(zone, order, mark,
ac->highest_zoneidx, alloc_flags))
goto try_this_zone;
/* did we reclaim enough */
if (!zone_watermark_ok(zone, order, mark,
ac->highest_zoneidx, alloc_flags))
continue;
}
}
try_this_zone:

View File

@@ -7773,9 +7773,9 @@ static unsigned long __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask,
return sc->nr_reclaimed;
}
int node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order)
unsigned long node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order)
{
int ret;
unsigned long ret;
/* Minimum pages needed in order to stay on node */
const unsigned long nr_pages = 1 << order;
struct scan_control sc = {
@@ -7802,13 +7802,13 @@ int node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order)
if (node_pagecache_reclaimable(pgdat) <= pgdat->min_unmapped_pages &&
node_page_state_pages(pgdat, NR_SLAB_RECLAIMABLE_B) <=
pgdat->min_slab_pages)
return NODE_RECLAIM_FULL;
return 0;
/*
* Do not scan if the allocation should not be delayed.
*/
if (!gfpflags_allow_blocking(gfp_mask) || (current->flags & PF_MEMALLOC))
return NODE_RECLAIM_NOSCAN;
return 0;
/*
* Only run node reclaim on the local node or on nodes that do not
@@ -7817,15 +7817,15 @@ int node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned int order)
* as wide as possible.
*/
if (node_state(pgdat->node_id, N_CPU) && pgdat->node_id != numa_node_id())
return NODE_RECLAIM_NOSCAN;
return 0;
if (test_and_set_bit_lock(PGDAT_RECLAIM_LOCKED, &pgdat->flags))
return NODE_RECLAIM_NOSCAN;
return 0;
ret = __node_reclaim(pgdat, gfp_mask, nr_pages, &sc) >= nr_pages;
ret = __node_reclaim(pgdat, gfp_mask, nr_pages, &sc);
clear_bit_unlock(PGDAT_RECLAIM_LOCKED, &pgdat->flags);
if (ret)
if (ret >= nr_pages)
count_vm_event(PGSCAN_ZONE_RECLAIM_SUCCESS);
else
count_vm_event(PGSCAN_ZONE_RECLAIM_FAILED);