diff --git a/include/linux/mm.h b/include/linux/mm.h index b370c9bb9f89499db89953828254c18b14592bd0..c24da9b0870c3400f30b66469afa55404d43a5c1 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -3056,7 +3056,7 @@ extern int sysctl_memory_failure_recovery; extern void shake_page(struct page *p, int access); extern atomic_long_t num_poisoned_pages __read_mostly; extern int soft_offline_page(unsigned long pfn, int flags); - +extern unsigned int sysctl_vmemmap_block_from_dram; /* * Error handlers for various types of pages. diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4fbc106aa195cba3cbd2b89aadb6ebbded69a9a4..7c52ac56d88d639ecbecb4c25777bb74ff4a200e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -3158,6 +3158,15 @@ static struct ctl_table vm_table[] = { .extra2 = SYSCTL_ONE, }, #endif + { + .procname = "vmemmap_block_from_dram", + .data = &sysctl_vmemmap_block_from_dram, + .maxlen = sizeof(sysctl_vmemmap_block_from_dram), + .mode = 0600, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, { } }; diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index b9de2df5b835891be27307e0fac121945900d5ce..949d28e66e5930c966bcc839183009a852e24e7f 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -914,6 +914,7 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid) /* we can use NODE_DATA(nid) from here */ pgdat->node_id = nid; pgdat->node_start_pfn = 0; + pgdat->peer_node = find_best_peer_node(nid); /* init node's zones as empty zones, we don't have any present pages.*/ free_area_init_core_hotplug(nid); diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index 16183d85a7d505538a14bc1d958ae672a547148d..1ed6b19d72329d5b9dcac3622ade9d658c83535e 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -30,6 +30,8 @@ #include #include +unsigned int sysctl_vmemmap_block_from_dram; + /* * Allocate a block of memory to be used to back the virtual memory map * or to back the page tables that are used to create the mapping. @@ -54,6 +56,12 @@ void * __meminit vmemmap_alloc_block(unsigned long size, int node) static bool warned; struct page *page; + /* if node is pmem node, alloc_pages from it's peer + * dram node to accelerate access to page struct + */ + if (is_node_pmem(node) && sysctl_vmemmap_block_from_dram) + node = NODE_DATA(node)->peer_node; + page = alloc_pages_node(node, gfp_mask, order); if (page) return page_address(page);