On Thu, 1 Aug 2024 09:08:07 +0300 Mike Rapoport <rppt@xxxxxxxxxx> wrote: > From: "Mike Rapoport (Microsoft)" <rppt@xxxxxxxxxx> > > There are no users of HAVE_ARCH_NODEDATA_EXTENSION left, so > arch_alloc_nodedata() and arch_refresh_nodedata() are not needed > anymore. > > Replace the call to arch_alloc_nodedata() in free_area_init() with > memblock_alloc(), remove arch_refresh_nodedata() and cleanup > include/linux/memory_hotplug.h from the associated ifdefery. > > Signed-off-by: Mike Rapoport (Microsoft) <rppt@xxxxxxxxxx> > Tested-by: Zi Yan <ziy@xxxxxxxxxx> # for x86_64 and arm64 Hi Mike, This has an accidental (I assume) functional change and if you have an initially offline node it all goes wrong. > --- > include/linux/memory_hotplug.h | 48 ---------------------------------- > mm/mm_init.c | 3 +-- > 2 files changed, 1 insertion(+), 50 deletions(-) > > diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h > index ebe876930e78..b27ddce5d324 100644 > --- a/include/linux/memory_hotplug.h > +++ b/include/linux/memory_hotplug.h > @@ -16,54 +16,6 @@ struct resource; > struct vmem_altmap; > struct dev_pagemap; > > -#ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION > -/* > - * For supporting node-hotadd, we have to allocate a new pgdat. > - * > - * If an arch has generic style NODE_DATA(), > - * node_data[nid] = kzalloc() works well. But it depends on the architecture. > - * > - * In general, generic_alloc_nodedata() is used. > - * > - */ > -extern pg_data_t *arch_alloc_nodedata(int nid); > -extern void arch_refresh_nodedata(int nid, pg_data_t *pgdat); > - > -#else /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */ > - > -#define arch_alloc_nodedata(nid) generic_alloc_nodedata(nid) > - > -#ifdef CONFIG_NUMA > -/* > - * XXX: node aware allocation can't work well to get new node's memory at this time. > - * Because, pgdat for the new node is not allocated/initialized yet itself. > - * To use new node's memory, more consideration will be necessary. > - */ > -#define generic_alloc_nodedata(nid) \ > -({ \ > - memblock_alloc(sizeof(*pgdat), SMP_CACHE_BYTES); \ > -}) > - > -extern pg_data_t *node_data[]; > -static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat) > -{ > - node_data[nid] = pgdat; > -} > - > -#else /* !CONFIG_NUMA */ > - > -/* never called */ > -static inline pg_data_t *generic_alloc_nodedata(int nid) > -{ > - BUG(); > - return NULL; > -} > -static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat) > -{ > -} > -#endif /* CONFIG_NUMA */ > -#endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */ > - > #ifdef CONFIG_MEMORY_HOTPLUG > struct page *pfn_to_online_page(unsigned long pfn); > > diff --git a/mm/mm_init.c b/mm/mm_init.c > index 75c3bd42799b..bcc2f2dd8021 100644 > --- a/mm/mm_init.c > +++ b/mm/mm_init.c > @@ -1838,11 +1838,10 @@ void __init free_area_init(unsigned long *max_zone_pfn) > > if (!node_online(nid)) { > /* Allocator not initialized yet */ > - pgdat = arch_alloc_nodedata(nid); > + pgdat = memblock_alloc(sizeof(*pgdat), SMP_CACHE_BYTES); > if (!pgdat) > panic("Cannot allocate %zuB for node %d.\n", > sizeof(*pgdat), nid); > - arch_refresh_nodedata(nid, pgdat); This allocates pgdat but never sets node_data[nid] to it and promptly leaks it on the line below. Just to sanity check this I spun up a qemu machine with no memory initially present on some nodes and it went boom as you'd expect. I tested with addition of NODE_DATA(nid) = pgdat; and it all seems to work as expected. Jonathan > } > > pgdat = NODE_DATA(nid);