mm, memory_hotplug: reorganize new pgdat initialization
authorMichal Hocko <mhocko@suse.com>
Tue, 22 Mar 2022 21:47:00 +0000 (14:47 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 22 Mar 2022 22:57:10 +0000 (15:57 -0700)
When a !node_online node is brought up it needs a hotplug specific
initialization because the node could be either uninitialized yet or it
could have been recycled after previous hotremove.  hotadd_init_pgdat is
responsible for that.

Internal pgdat state is initialized at two places currently
- hotadd_init_pgdat
- free_area_init_core_hotplug

There is no real clear cut what should go where but this patch's chosen to
move the whole internal state initialization into
free_area_init_core_hotplug.  hotadd_init_pgdat is still responsible to
pull all the parts together - most notably to initialize zonelists because
those depend on the overall topology.

This patch doesn't introduce any functional change.

Link: https://lkml.kernel.org/r/20220127085305.20890-5-mhocko@kernel.org
Signed-off-by: Michal Hocko <mhocko@suse.com>
Acked-by: Rafael Aquini <raquini@redhat.com>
Acked-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Oscar Salvador <osalvador@suse.de>
Cc: Alexey Makhalov <amakhalov@vmware.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Dennis Zhou <dennis@kernel.org>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Mike Rapoport <rppt@linux.ibm.com>
Cc: Nico Pache <npache@redhat.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Wei Yang <richard.weiyang@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/memory_hotplug.h
mm/memory_hotplug.c
mm/page_alloc.c

index 60f09d3..76bf2de 100644 (file)
@@ -319,7 +319,7 @@ extern void set_zone_contiguous(struct zone *zone);
 extern void clear_zone_contiguous(struct zone *zone);
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-extern void __ref free_area_init_core_hotplug(int nid);
+extern void __ref free_area_init_core_hotplug(struct pglist_data *pgdat);
 extern int __add_memory(int nid, u64 start, u64 size, mhp_t mhp_flags);
 extern int add_memory(int nid, u64 start, u64 size, mhp_t mhp_flags);
 extern int add_memory_resource(int nid, struct resource *resource,
index 55c3e53..a4f69d3 100644 (file)
@@ -1166,39 +1166,16 @@ static pg_data_t __ref *hotadd_init_pgdat(int nid)
 {
        struct pglist_data *pgdat;
 
-       pgdat = NODE_DATA(nid);
-
        /*
         * NODE_DATA is preallocated (free_area_init) but its internal
         * state is not allocated completely. Add missing pieces.
         * Completely offline nodes stay around and they just need
         * reintialization.
         */
-       if (pgdat->per_cpu_nodestats == &boot_nodestats) {
-               pgdat->per_cpu_nodestats =
-                       alloc_percpu(struct per_cpu_nodestat);
-       } else {
-               int cpu;
-               /*
-                * Reset the nr_zones, order and highest_zoneidx before reuse.
-                * Note that kswapd will init kswapd_highest_zoneidx properly
-                * when it starts in the near future.
-                */
-               pgdat->nr_zones = 0;
-               pgdat->kswapd_order = 0;
-               pgdat->kswapd_highest_zoneidx = 0;
-               for_each_online_cpu(cpu) {
-                       struct per_cpu_nodestat *p;
-
-                       p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
-                       memset(p, 0, sizeof(*p));
-               }
-       }
-
-       pgdat->node_start_pfn = 0;
+       pgdat = NODE_DATA(nid);
 
        /* init node's zones as empty zones, we don't have any present pages.*/
-       free_area_init_core_hotplug(nid);
+       free_area_init_core_hotplug(pgdat);
 
        /*
         * The node we allocated has no zone fallback lists. For avoiding
@@ -1210,6 +1187,7 @@ static pg_data_t __ref *hotadd_init_pgdat(int nid)
         * When memory is hot-added, all the memory is in offline state. So
         * clear all zones' present_pages because they will be updated in
         * online_pages() and offline_pages().
+        * TODO: should be in free_area_init_core_hotplug?
         */
        reset_node_managed_pages(pgdat);
        reset_node_present_pages(pgdat);
index 4f141a4..d32a635 100644 (file)
@@ -7466,12 +7466,33 @@ static void __meminit zone_init_internals(struct zone *zone, enum zone_type idx,
  * NOTE: this function is only called during memory hotplug
  */
 #ifdef CONFIG_MEMORY_HOTPLUG
-void __ref free_area_init_core_hotplug(int nid)
+void __ref free_area_init_core_hotplug(struct pglist_data *pgdat)
 {
+       int nid = pgdat->node_id;
        enum zone_type z;
-       pg_data_t *pgdat = NODE_DATA(nid);
+       int cpu;
 
        pgdat_init_internals(pgdat);
+
+       if (pgdat->per_cpu_nodestats == &boot_nodestats)
+               pgdat->per_cpu_nodestats = alloc_percpu(struct per_cpu_nodestat);
+
+       /*
+        * Reset the nr_zones, order and highest_zoneidx before reuse.
+        * Note that kswapd will init kswapd_highest_zoneidx properly
+        * when it starts in the near future.
+        */
+       pgdat->nr_zones = 0;
+       pgdat->kswapd_order = 0;
+       pgdat->kswapd_highest_zoneidx = 0;
+       pgdat->node_start_pfn = 0;
+       for_each_online_cpu(cpu) {
+               struct per_cpu_nodestat *p;
+
+               p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
+               memset(p, 0, sizeof(*p));
+       }
+
        for (z = 0; z < MAX_NR_ZONES; z++)
                zone_init_internals(&pgdat->node_zones[z], z, nid, 0);
 }