Skip to content

Commit 426e5c4

Browse files
Muchun Songtorvalds
authored andcommitted
mm: memory_hotplug: factor out bootmem core functions to bootmem_info.c
Patch series "Free some vmemmap pages of HugeTLB page", v23. This patch series will free some vmemmap pages(struct page structures) associated with each HugeTLB page when preallocated to save memory. In order to reduce the difficulty of the first version of code review. In this version, we disable PMD/huge page mapping of vmemmap if this feature was enabled. This acutely eliminates a bunch of the complex code doing page table manipulation. When this patch series is solid, we cam add the code of vmemmap page table manipulation in the future. The struct page structures (page structs) are used to describe a physical page frame. By default, there is an one-to-one mapping from a page frame to it's corresponding page struct. The HugeTLB pages consist of multiple base page size pages and is supported by many architectures. See hugetlbpage.rst in the Documentation directory for more details. On the x86 architecture, HugeTLB pages of size 2MB and 1GB are currently supported. Since the base page size on x86 is 4KB, a 2MB HugeTLB page consists of 512 base pages and a 1GB HugeTLB page consists of 4096 base pages. For each base page, there is a corresponding page struct. Within the HugeTLB subsystem, only the first 4 page structs are used to contain unique information about a HugeTLB page. HUGETLB_CGROUP_MIN_ORDER provides this upper limit. The only 'useful' information in the remaining page structs is the compound_head field, and this field is the same for all tail pages. By removing redundant page structs for HugeTLB pages, memory can returned to the buddy allocator for other uses. When the system boot up, every 2M HugeTLB has 512 struct page structs which size is 8 pages(sizeof(struct page) * 512 / PAGE_SIZE). HugeTLB struct pages(8 pages) page frame(8 pages) +-----------+ ---virt_to_page---> +-----------+ mapping to +-----------+ | | | 0 | -------------> | 0 | | | +-----------+ +-----------+ | | | 1 | -------------> | 1 | | | +-----------+ +-----------+ | | | 2 | -------------> | 2 | | | +-----------+ +-----------+ | | | 3 | -------------> | 3 | | | +-----------+ +-----------+ | | | 4 | -------------> | 4 | | 2MB | +-----------+ +-----------+ | | | 5 | -------------> | 5 | | | +-----------+ +-----------+ | | | 6 | -------------> | 6 | | | +-----------+ +-----------+ | | | 7 | -------------> | 7 | | | +-----------+ +-----------+ | | | | | | +-----------+ The value of page->compound_head is the same for all tail pages. The first page of page structs (page 0) associated with the HugeTLB page contains the 4 page structs necessary to describe the HugeTLB. The only use of the remaining pages of page structs (page 1 to page 7) is to point to page->compound_head. Therefore, we can remap pages 2 to 7 to page 1. Only 2 pages of page structs will be used for each HugeTLB page. This will allow us to free the remaining 6 pages to the buddy allocator. Here is how things look after remapping. HugeTLB struct pages(8 pages) page frame(8 pages) +-----------+ ---virt_to_page---> +-----------+ mapping to +-----------+ | | | 0 | -------------> | 0 | | | +-----------+ +-----------+ | | | 1 | -------------> | 1 | | | +-----------+ +-----------+ | | | 2 | ----------------^ ^ ^ ^ ^ ^ | | +-----------+ | | | | | | | | 3 | ------------------+ | | | | | | +-----------+ | | | | | | | 4 | --------------------+ | | | | 2MB | +-----------+ | | | | | | 5 | ----------------------+ | | | | +-----------+ | | | | | 6 | ------------------------+ | | | +-----------+ | | | | 7 | --------------------------+ | | +-----------+ | | | | | | +-----------+ When a HugeTLB is freed to the buddy system, we should allocate 6 pages for vmemmap pages and restore the previous mapping relationship. Apart from 2MB HugeTLB page, we also have 1GB HugeTLB page. It is similar to the 2MB HugeTLB page. We also can use this approach to free the vmemmap pages. In this case, for the 1GB HugeTLB page, we can save 4094 pages. This is a very substantial gain. On our server, run some SPDK/QEMU applications which will use 1024GB HugeTLB page. With this feature enabled, we can save ~16GB (1G hugepage)/~12GB (2MB hugepage) memory. Because there are vmemmap page tables reconstruction on the freeing/allocating path, it increases some overhead. Here are some overhead analysis. 1) Allocating 10240 2MB HugeTLB pages. a) With this patch series applied: # time echo 10240 > /proc/sys/vm/nr_hugepages real 0m0.166s user 0m0.000s sys 0m0.166s # bpftrace -e 'kprobe:alloc_fresh_huge_page { @start[tid] = nsecs; } kretprobe:alloc_fresh_huge_page /@start[tid]/ { @Latency = hist(nsecs - @start[tid]); delete(@start[tid]); }' Attaching 2 probes... @Latency: [8K, 16K) 5476 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [16K, 32K) 4760 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ | [32K, 64K) 4 | | b) Without this patch series: # time echo 10240 > /proc/sys/vm/nr_hugepages real 0m0.067s user 0m0.000s sys 0m0.067s # bpftrace -e 'kprobe:alloc_fresh_huge_page { @start[tid] = nsecs; } kretprobe:alloc_fresh_huge_page /@start[tid]/ { @Latency = hist(nsecs - @start[tid]); delete(@start[tid]); }' Attaching 2 probes... @Latency: [4K, 8K) 10147 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [8K, 16K) 93 | | Summarize: this feature is about ~2x slower than before. 2) Freeing 10240 2MB HugeTLB pages. a) With this patch series applied: # time echo 0 > /proc/sys/vm/nr_hugepages real 0m0.213s user 0m0.000s sys 0m0.213s # bpftrace -e 'kprobe:free_pool_huge_page { @start[tid] = nsecs; } kretprobe:free_pool_huge_page /@start[tid]/ { @Latency = hist(nsecs - @start[tid]); delete(@start[tid]); }' Attaching 2 probes... @Latency: [8K, 16K) 6 | | [16K, 32K) 10227 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [32K, 64K) 7 | | b) Without this patch series: # time echo 0 > /proc/sys/vm/nr_hugepages real 0m0.081s user 0m0.000s sys 0m0.081s # bpftrace -e 'kprobe:free_pool_huge_page { @start[tid] = nsecs; } kretprobe:free_pool_huge_page /@start[tid]/ { @Latency = hist(nsecs - @start[tid]); delete(@start[tid]); }' Attaching 2 probes... @Latency: [4K, 8K) 6805 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@| [8K, 16K) 3427 |@@@@@@@@@@@@@@@@@@@@@@@@@@ | [16K, 32K) 8 | | Summary: The overhead of __free_hugepage is about ~2-3x slower than before. Although the overhead has increased, the overhead is not significant. Like Mike said, "However, remember that the majority of use cases create HugeTLB pages at or shortly after boot time and add them to the pool. So, additional overhead is at pool creation time. There is no change to 'normal run time' operations of getting a page from or returning a page to the pool (think page fault/unmap)". Despite the overhead and in addition to the memory gains from this series. The following data is obtained by Joao Martins. Very thanks to his effort. There's an additional benefit which is page (un)pinners will see an improvement and Joao presumes because there are fewer memmap pages and thus the tail/head pages are staying in cache more often. Out of the box Joao saw (when comparing linux-next against linux-next + this series) with gup_test and pinning a 16G HugeTLB file (with 1G pages): get_user_pages(): ~32k -> ~9k unpin_user_pages(): ~75k -> ~70k Usually any tight loop fetching compound_head(), or reading tail pages data (e.g. compound_head) benefit a lot. There's some unpinning inefficiencies Joao was fixing[2], but with that in added it shows even more: unpin_user_pages(): ~27k -> ~3.8k [1] https://lore.kernel.org/linux-mm/20210409205254.242291-1-mike.kravetz@oracle.com/ [2] https://lore.kernel.org/linux-mm/20210204202500.26474-1-joao.m.martins@oracle.com/ This patch (of 9): Move bootmem info registration common API to individual bootmem_info.c. And we will use {get,put}_page_bootmem() to initialize the page for the vmemmap pages or free the vmemmap pages to buddy in the later patch. So move them out of CONFIG_MEMORY_HOTPLUG_SPARSE. This is just code movement without any functional change. Link: https://lkml.kernel.org/r/20210510030027.56044-1-songmuchun@bytedance.com Link: https://lkml.kernel.org/r/20210510030027.56044-2-songmuchun@bytedance.com Signed-off-by: Muchun Song <songmuchun@bytedance.com> Acked-by: Mike Kravetz <mike.kravetz@oracle.com> Reviewed-by: Oscar Salvador <osalvador@suse.de> Reviewed-by: David Hildenbrand <david@redhat.com> Reviewed-by: Miaohe Lin <linmiaohe@huawei.com> Tested-by: Chen Huang <chenhuang5@huawei.com> Tested-by: Bodeddula Balasubramaniam <bodeddub@amazon.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: x86@kernel.org Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Paul E. McKenney <paulmck@kernel.org> Cc: Pawan Gupta <pawan.kumar.gupta@linux.intel.com> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Oliver Neukum <oneukum@suse.com> Cc: Anshuman Khandual <anshuman.khandual@arm.com> Cc: Joerg Roedel <jroedel@suse.de> Cc: Mina Almasry <almasrymina@google.com> Cc: David Rientjes <rientjes@google.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Barry Song <song.bao.hua@hisilicon.com> Cc: HORIGUCHI NAOYA <naoya.horiguchi@nec.com> Cc: Joao Martins <joao.m.martins@oracle.com> Cc: Xiongchun Duan <duanxiongchun@bytedance.com> Cc: Balbir Singh <bsingharora@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 0ed950d commit 426e5c4

File tree

8 files changed

+172
-144
lines changed

8 files changed

+172
-144
lines changed

arch/sparc/mm/init_64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/percpu.h>
2828
#include <linux/mmzone.h>
2929
#include <linux/gfp.h>
30+
#include <linux/bootmem_info.h>
3031

3132
#include <asm/head.h>
3233
#include <asm/page.h>

arch/x86/mm/init_64.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <linux/nmi.h>
3434
#include <linux/gfp.h>
3535
#include <linux/kcore.h>
36+
#include <linux/bootmem_info.h>
3637

3738
#include <asm/processor.h>
3839
#include <asm/bios_ebda.h>
@@ -1623,7 +1624,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
16231624
return err;
16241625
}
16251626

1626-
#if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) && defined(CONFIG_HAVE_BOOTMEM_INFO_NODE)
1627+
#ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE
16271628
void register_page_bootmem_memmap(unsigned long section_nr,
16281629
struct page *start_page, unsigned long nr_pages)
16291630
{

include/linux/bootmem_info.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef __LINUX_BOOTMEM_INFO_H
3+
#define __LINUX_BOOTMEM_INFO_H
4+
5+
#include <linux/mmzone.h>
6+
7+
/*
8+
* Types for free bootmem stored in page->lru.next. These have to be in
9+
* some random range in unsigned long space for debugging purposes.
10+
*/
11+
enum {
12+
MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE = 12,
13+
SECTION_INFO = MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE,
14+
MIX_SECTION_INFO,
15+
NODE_INFO,
16+
MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE = NODE_INFO,
17+
};
18+
19+
#ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE
20+
void __init register_page_bootmem_info_node(struct pglist_data *pgdat);
21+
22+
void get_page_bootmem(unsigned long info, struct page *page,
23+
unsigned long type);
24+
void put_page_bootmem(struct page *page);
25+
#else
26+
static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
27+
{
28+
}
29+
30+
static inline void put_page_bootmem(struct page *page)
31+
{
32+
}
33+
34+
static inline void get_page_bootmem(unsigned long info, struct page *page,
35+
unsigned long type)
36+
{
37+
}
38+
#endif
39+
40+
#endif /* __LINUX_BOOTMEM_INFO_H */

include/linux/memory_hotplug.h

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,6 @@ struct vmem_altmap;
1818
#ifdef CONFIG_MEMORY_HOTPLUG
1919
struct page *pfn_to_online_page(unsigned long pfn);
2020

21-
/*
22-
* Types for free bootmem stored in page->lru.next. These have to be in
23-
* some random range in unsigned long space for debugging purposes.
24-
*/
25-
enum {
26-
MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE = 12,
27-
SECTION_INFO = MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE,
28-
MIX_SECTION_INFO,
29-
NODE_INFO,
30-
MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE = NODE_INFO,
31-
};
32-
3321
/* Types for control the zone type of onlined and offlined memory */
3422
enum {
3523
/* Offline the memory. */
@@ -222,17 +210,6 @@ static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
222210
#endif /* CONFIG_NUMA */
223211
#endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
224212

225-
#ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE
226-
extern void __init register_page_bootmem_info_node(struct pglist_data *pgdat);
227-
#else
228-
static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
229-
{
230-
}
231-
#endif
232-
extern void put_page_bootmem(struct page *page);
233-
extern void get_page_bootmem(unsigned long ingo, struct page *page,
234-
unsigned long type);
235-
236213
void get_online_mems(void);
237214
void put_online_mems(void);
238215

@@ -260,10 +237,6 @@ static inline void zone_span_writelock(struct zone *zone) {}
260237
static inline void zone_span_writeunlock(struct zone *zone) {}
261238
static inline void zone_seqlock_init(struct zone *zone) {}
262239

263-
static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
264-
{
265-
}
266-
267240
static inline int try_online_node(int nid)
268241
{
269242
return 0;

mm/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,4 @@ obj-$(CONFIG_MAPPING_DIRTY_HELPERS) += mapping_dirty_helpers.o
125125
obj-$(CONFIG_PTDUMP_CORE) += ptdump.o
126126
obj-$(CONFIG_PAGE_REPORTING) += page_reporting.o
127127
obj-$(CONFIG_IO_MAPPING) += io-mapping.o
128+
obj-$(CONFIG_HAVE_BOOTMEM_INFO_NODE) += bootmem_info.o

mm/bootmem_info.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Bootmem core functions.
4+
*
5+
* Copyright (c) 2020, Bytedance.
6+
*
7+
* Author: Muchun Song <songmuchun@bytedance.com>
8+
*
9+
*/
10+
#include <linux/mm.h>
11+
#include <linux/compiler.h>
12+
#include <linux/memblock.h>
13+
#include <linux/bootmem_info.h>
14+
#include <linux/memory_hotplug.h>
15+
16+
void get_page_bootmem(unsigned long info, struct page *page, unsigned long type)
17+
{
18+
page->freelist = (void *)type;
19+
SetPagePrivate(page);
20+
set_page_private(page, info);
21+
page_ref_inc(page);
22+
}
23+
24+
void put_page_bootmem(struct page *page)
25+
{
26+
unsigned long type;
27+
28+
type = (unsigned long) page->freelist;
29+
BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
30+
type > MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE);
31+
32+
if (page_ref_dec_return(page) == 1) {
33+
page->freelist = NULL;
34+
ClearPagePrivate(page);
35+
set_page_private(page, 0);
36+
INIT_LIST_HEAD(&page->lru);
37+
free_reserved_page(page);
38+
}
39+
}
40+
41+
#ifndef CONFIG_SPARSEMEM_VMEMMAP
42+
static void register_page_bootmem_info_section(unsigned long start_pfn)
43+
{
44+
unsigned long mapsize, section_nr, i;
45+
struct mem_section *ms;
46+
struct page *page, *memmap;
47+
struct mem_section_usage *usage;
48+
49+
section_nr = pfn_to_section_nr(start_pfn);
50+
ms = __nr_to_section(section_nr);
51+
52+
/* Get section's memmap address */
53+
memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
54+
55+
/*
56+
* Get page for the memmap's phys address
57+
* XXX: need more consideration for sparse_vmemmap...
58+
*/
59+
page = virt_to_page(memmap);
60+
mapsize = sizeof(struct page) * PAGES_PER_SECTION;
61+
mapsize = PAGE_ALIGN(mapsize) >> PAGE_SHIFT;
62+
63+
/* remember memmap's page */
64+
for (i = 0; i < mapsize; i++, page++)
65+
get_page_bootmem(section_nr, page, SECTION_INFO);
66+
67+
usage = ms->usage;
68+
page = virt_to_page(usage);
69+
70+
mapsize = PAGE_ALIGN(mem_section_usage_size()) >> PAGE_SHIFT;
71+
72+
for (i = 0; i < mapsize; i++, page++)
73+
get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
74+
75+
}
76+
#else /* CONFIG_SPARSEMEM_VMEMMAP */
77+
static void register_page_bootmem_info_section(unsigned long start_pfn)
78+
{
79+
unsigned long mapsize, section_nr, i;
80+
struct mem_section *ms;
81+
struct page *page, *memmap;
82+
struct mem_section_usage *usage;
83+
84+
section_nr = pfn_to_section_nr(start_pfn);
85+
ms = __nr_to_section(section_nr);
86+
87+
memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
88+
89+
register_page_bootmem_memmap(section_nr, memmap, PAGES_PER_SECTION);
90+
91+
usage = ms->usage;
92+
page = virt_to_page(usage);
93+
94+
mapsize = PAGE_ALIGN(mem_section_usage_size()) >> PAGE_SHIFT;
95+
96+
for (i = 0; i < mapsize; i++, page++)
97+
get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
98+
}
99+
#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
100+
101+
void __init register_page_bootmem_info_node(struct pglist_data *pgdat)
102+
{
103+
unsigned long i, pfn, end_pfn, nr_pages;
104+
int node = pgdat->node_id;
105+
struct page *page;
106+
107+
nr_pages = PAGE_ALIGN(sizeof(struct pglist_data)) >> PAGE_SHIFT;
108+
page = virt_to_page(pgdat);
109+
110+
for (i = 0; i < nr_pages; i++, page++)
111+
get_page_bootmem(node, page, NODE_INFO);
112+
113+
pfn = pgdat->node_start_pfn;
114+
end_pfn = pgdat_end_pfn(pgdat);
115+
116+
/* register section info */
117+
for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
118+
/*
119+
* Some platforms can assign the same pfn to multiple nodes - on
120+
* node0 as well as nodeN. To avoid registering a pfn against
121+
* multiple nodes we check that this pfn does not already
122+
* reside in some other nodes.
123+
*/
124+
if (pfn_valid(pfn) && (early_pfn_to_nid(pfn) == node))
125+
register_page_bootmem_info_section(pfn);
126+
}
127+
}

mm/memory_hotplug.c

Lines changed: 0 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -154,122 +154,6 @@ static void release_memory_resource(struct resource *res)
154154
}
155155

156156
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
157-
void get_page_bootmem(unsigned long info, struct page *page,
158-
unsigned long type)
159-
{
160-
page->freelist = (void *)type;
161-
SetPagePrivate(page);
162-
set_page_private(page, info);
163-
page_ref_inc(page);
164-
}
165-
166-
void put_page_bootmem(struct page *page)
167-
{
168-
unsigned long type;
169-
170-
type = (unsigned long) page->freelist;
171-
BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
172-
type > MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE);
173-
174-
if (page_ref_dec_return(page) == 1) {
175-
page->freelist = NULL;
176-
ClearPagePrivate(page);
177-
set_page_private(page, 0);
178-
INIT_LIST_HEAD(&page->lru);
179-
free_reserved_page(page);
180-
}
181-
}
182-
183-
#ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE
184-
#ifndef CONFIG_SPARSEMEM_VMEMMAP
185-
static void register_page_bootmem_info_section(unsigned long start_pfn)
186-
{
187-
unsigned long mapsize, section_nr, i;
188-
struct mem_section *ms;
189-
struct page *page, *memmap;
190-
struct mem_section_usage *usage;
191-
192-
section_nr = pfn_to_section_nr(start_pfn);
193-
ms = __nr_to_section(section_nr);
194-
195-
/* Get section's memmap address */
196-
memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
197-
198-
/*
199-
* Get page for the memmap's phys address
200-
* XXX: need more consideration for sparse_vmemmap...
201-
*/
202-
page = virt_to_page(memmap);
203-
mapsize = sizeof(struct page) * PAGES_PER_SECTION;
204-
mapsize = PAGE_ALIGN(mapsize) >> PAGE_SHIFT;
205-
206-
/* remember memmap's page */
207-
for (i = 0; i < mapsize; i++, page++)
208-
get_page_bootmem(section_nr, page, SECTION_INFO);
209-
210-
usage = ms->usage;
211-
page = virt_to_page(usage);
212-
213-
mapsize = PAGE_ALIGN(mem_section_usage_size()) >> PAGE_SHIFT;
214-
215-
for (i = 0; i < mapsize; i++, page++)
216-
get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
217-
218-
}
219-
#else /* CONFIG_SPARSEMEM_VMEMMAP */
220-
static void register_page_bootmem_info_section(unsigned long start_pfn)
221-
{
222-
unsigned long mapsize, section_nr, i;
223-
struct mem_section *ms;
224-
struct page *page, *memmap;
225-
struct mem_section_usage *usage;
226-
227-
section_nr = pfn_to_section_nr(start_pfn);
228-
ms = __nr_to_section(section_nr);
229-
230-
memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
231-
232-
register_page_bootmem_memmap(section_nr, memmap, PAGES_PER_SECTION);
233-
234-
usage = ms->usage;
235-
page = virt_to_page(usage);
236-
237-
mapsize = PAGE_ALIGN(mem_section_usage_size()) >> PAGE_SHIFT;
238-
239-
for (i = 0; i < mapsize; i++, page++)
240-
get_page_bootmem(section_nr, page, MIX_SECTION_INFO);
241-
}
242-
#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
243-
244-
void __init register_page_bootmem_info_node(struct pglist_data *pgdat)
245-
{
246-
unsigned long i, pfn, end_pfn, nr_pages;
247-
int node = pgdat->node_id;
248-
struct page *page;
249-
250-
nr_pages = PAGE_ALIGN(sizeof(struct pglist_data)) >> PAGE_SHIFT;
251-
page = virt_to_page(pgdat);
252-
253-
for (i = 0; i < nr_pages; i++, page++)
254-
get_page_bootmem(node, page, NODE_INFO);
255-
256-
pfn = pgdat->node_start_pfn;
257-
end_pfn = pgdat_end_pfn(pgdat);
258-
259-
/* register section info */
260-
for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
261-
/*
262-
* Some platforms can assign the same pfn to multiple nodes - on
263-
* node0 as well as nodeN. To avoid registering a pfn against
264-
* multiple nodes we check that this pfn does not already
265-
* reside in some other nodes.
266-
*/
267-
if (pfn_valid(pfn) && (early_pfn_to_nid(pfn) == node))
268-
register_page_bootmem_info_section(pfn);
269-
}
270-
}
271-
#endif /* CONFIG_HAVE_BOOTMEM_INFO_NODE */
272-
273157
static int check_pfn_span(unsigned long pfn, unsigned long nr_pages,
274158
const char *reason)
275159
{

mm/sparse.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/vmalloc.h>
1414
#include <linux/swap.h>
1515
#include <linux/swapops.h>
16+
#include <linux/bootmem_info.h>
1617

1718
#include "internal.h"
1819
#include <asm/dma.h>

0 commit comments

Comments
 (0)