[PATCH v5 12/12] mm/mmzone: remove zonelist_node_idx()
From: Gregory Price (Meta)
Date: Sat Oct 31 2026 - 22:18:27 EST
zonelist_node_idx() looks like it returns a field of the zoneref, as
zonelist_zone_idx() does, but it loads the zone from the slot again.
Memory hotplug rewrites zonelists in place, so a caller that has already
checked the slot can get a different zone, or the NULL terminator, from
that second load.
__next_zones_zonelist() and mempolicy_slab_node() had this bug.
Remove the helper and open-code it in its two remaining callers, neither
of which can race with a rebuild. local_memory_node() runs either inside
__build_all_zonelists() or during CPU bring-up, which holds
cpu_hotplug_lock for write and so excludes mem_hotplug_begin().
The lookup in mpol_misplaced() is unreachable: it needs a policy with
MPOL_F_MOF but not MPOL_F_MORON, and nothing sets one without the other.
Signed-off-by: Gregory Price (Meta) <gourry@xxxxxxxxxx>
---
include/linux/mmzone.h | 6 ------
mm/mempolicy.c | 2 +-
mm/page_alloc.c | 2 +-
3 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 4bc2318ac37f..72ffb2959c4f 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1439,7 +1439,6 @@ struct zoneref {
*
* zonelist_zone() - Return the struct zone * for an entry in _zonerefs
* zonelist_zone_idx() - Return the index of the zone for an entry
- * zonelist_node_idx() - Return the index of the node for an entry
*/
struct zonelist {
struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1];
@@ -1864,11 +1863,6 @@ static inline int zonelist_zone_idx(const struct zoneref *zoneref)
return zoneref->zone_idx;
}
-static inline int zonelist_node_idx(const struct zoneref *zoneref)
-{
- return zone_to_nid(zoneref->zone);
-}
-
struct zoneref *__next_zones_zonelist(struct zoneref *z,
enum zone_type highest_zoneidx,
const nodemask_t *nodes);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index cd63c3e2c029..267576054980 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -3087,7 +3087,7 @@ int mpol_misplaced(struct folio *folio, struct vm_fault *vmf,
node_zonelist(thisnid, GFP_HIGHUSER),
gfp_zone(GFP_HIGHUSER),
&pol->nodes);
- polnid = zonelist_node_idx(z);
+ polnid = zone_to_nid(zonelist_zone(z));
break;
default:
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 91ad979409e5..81c1de714658 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -5973,7 +5973,7 @@ int local_memory_node(int node)
z = first_zones_zonelist(node_zonelist(node, GFP_KERNEL),
gfp_zone(GFP_KERNEL),
NULL);
- return zonelist_node_idx(z);
+ return zone_to_nid(zonelist_zone(z));
}
#endif
--
2.56.0