The auto_movable_can_online_movable() function currently walks all populated zones when nid == NUMA_NO_NODE, Since adjust_present_page_count() is called every time memory is onlined/offlined and already updates present page counts, we can maintain cached global statistics that are updated incrementally. This eliminates the need to walk all zones for the NUMA_NO_NODE case. This patch introduces a static global_auto_movable_stats structure that caches kernel_early_pages and movable_pages counts. The cache is updated in adjust_present_page_count() whenever pages are onlined/offlined, and is read directly in auto_movable_can_online_movable() when nid == NUMA_NO_NODE. Testing: Built and booted the kernel successfully. Ran the memory management test suite in tools/testing/selftests/mm/ with ./run_vmtests.sh - all tests passed. Signed-off-by: Swaraj Gaikwad --- mm/memory_hotplug.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 63b9d500ec6c..ba43edba8c92 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -50,6 +50,8 @@ enum { static int memmap_mode __read_mostly = MEMMAP_ON_MEMORY_DISABLE; +static struct auto_movable_stats global_auto_movable_stats; + static inline unsigned long memory_block_memmap_size(void) { return PHYS_PFN(memory_block_size_bytes()) * sizeof(struct page); @@ -851,9 +853,7 @@ static bool auto_movable_can_online_movable(int nid, struct memory_group *group, /* Walk all relevant zones and collect MOVABLE vs. KERNEL stats. */ if (nid == NUMA_NO_NODE) { - /* TODO: cache values */ - for_each_populated_zone(zone) - auto_movable_stats_account_zone(&stats, zone); + stats = global_auto_movable_stats; } else { for (i = 0; i < MAX_NR_ZONES; i++) { pg_data_t *pgdat = NODE_DATA(nid); @@ -1071,12 +1071,13 @@ void adjust_present_page_count(struct page *page, struct memory_group *group, { struct zone *zone = page_zone(page); const bool movable = zone_idx(zone) == ZONE_MOVABLE; + const bool early = early_section(__pfn_to_section(page_to_pfn(page))); /* * We only support onlining/offlining/adding/removing of complete * memory blocks; therefore, either all is either early or hotplugged. */ - if (early_section(__pfn_to_section(page_to_pfn(page)))) + if (early) zone->present_early_pages += nr_pages; zone->present_pages += nr_pages; zone->zone_pgdat->node_present_pages += nr_pages; @@ -1085,6 +1086,12 @@ void adjust_present_page_count(struct page *page, struct memory_group *group, group->present_movable_pages += nr_pages; else if (group && !movable) group->present_kernel_pages += nr_pages; + + if (movable) { + global_auto_movable_stats.movable_pages += nr_pages; + } else if (early) { + global_auto_movable_stats.kernel_early_pages += nr_pages; + } } int mhp_init_memmap_on_memory(unsigned long pfn, unsigned long nr_pages, base-commit: 3cfeff1d2304237b1c14628d695a6df44daff48f -- 2.52.0