Skip to content

Commit 0386aaa

Browse files
Matthew Wilcox (Oracle)akpm00
authored andcommitted
bootmem: stop using page->index
Encode the type into the bottom four bits of page->private and the info into the remaining bits. Also turn the bootmem type into a named enum. [arnd@arndb.de: bootmem: add bootmem_type stub function] Link: https://lkml.kernel.org/r/20241015143802.577613-1-arnd@kernel.org [akpm@linux-foundation.org: fix build with !CONFIG_HAVE_BOOTMEM_INFO_NODE] Link: https://lore.kernel.org/oe-kbuild-all/202410090311.eaqcL7IZ-lkp@intel.com/ Link: https://lkml.kernel.org/r/20241005200121.3231142-6-willy@infradead.org Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: kernel test robot <lkp@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 68158bf commit 0386aaa

File tree

4 files changed

+56
-26
lines changed

4 files changed

+56
-26
lines changed

arch/x86/mm/init_64.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -985,22 +985,32 @@ int arch_add_memory(int nid, u64 start, u64 size,
985985
return add_pages(nid, start_pfn, nr_pages, params);
986986
}
987987

988-
static void __meminit free_pagetable(struct page *page, int order)
988+
static void free_reserved_pages(struct page *page, unsigned long nr_pages)
989989
{
990-
unsigned long magic;
991-
unsigned int nr_pages = 1 << order;
990+
while (nr_pages--)
991+
free_reserved_page(page++);
992+
}
992993

994+
static void __meminit free_pagetable(struct page *page, int order)
995+
{
993996
/* bootmem page has reserved flag */
994997
if (PageReserved(page)) {
995-
magic = page->index;
996-
if (magic == SECTION_INFO || magic == MIX_SECTION_INFO) {
998+
unsigned long nr_pages = 1 << order;
999+
#ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE
1000+
enum bootmem_type type = bootmem_type(page);
1001+
1002+
if (type == SECTION_INFO || type == MIX_SECTION_INFO) {
9971003
while (nr_pages--)
9981004
put_page_bootmem(page++);
999-
} else
1000-
while (nr_pages--)
1001-
free_reserved_page(page++);
1002-
} else
1005+
} else {
1006+
free_reserved_pages(page, nr_pages);
1007+
}
1008+
#else
1009+
free_reserved_pages(page, nr_pages);
1010+
#endif
1011+
} else {
10031012
free_pages((unsigned long)page_address(page), order);
1013+
}
10041014
}
10051015

10061016
static void __meminit free_hugepage_table(struct page *page,

include/linux/bootmem_info.h

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
#include <linux/kmemleak.h>
77

88
/*
9-
* Types for free bootmem stored in page->lru.next. These have to be in
10-
* some random range in unsigned long space for debugging purposes.
9+
* Types for free bootmem stored in the low bits of page->private.
1110
*/
12-
enum {
13-
MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE = 12,
11+
enum bootmem_type {
12+
MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE = 1,
1413
SECTION_INFO = MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE,
1514
MIX_SECTION_INFO,
1615
NODE_INFO,
@@ -21,25 +20,35 @@ enum {
2120
void __init register_page_bootmem_info_node(struct pglist_data *pgdat);
2221

2322
void get_page_bootmem(unsigned long info, struct page *page,
24-
unsigned long type);
23+
enum bootmem_type type);
2524
void put_page_bootmem(struct page *page);
2625

26+
static inline enum bootmem_type bootmem_type(const struct page *page)
27+
{
28+
return (unsigned long)page->private & 0xf;
29+
}
30+
31+
static inline unsigned long bootmem_info(const struct page *page)
32+
{
33+
return (unsigned long)page->private >> 4;
34+
}
35+
2736
/*
2837
* Any memory allocated via the memblock allocator and not via the
2938
* buddy will be marked reserved already in the memmap. For those
3039
* pages, we can call this function to free it to buddy allocator.
3140
*/
3241
static inline void free_bootmem_page(struct page *page)
3342
{
34-
unsigned long magic = page->index;
43+
enum bootmem_type type = bootmem_type(page);
3544

3645
/*
3746
* The reserve_bootmem_region sets the reserved flag on bootmem
3847
* pages.
3948
*/
4049
VM_BUG_ON_PAGE(page_ref_count(page) != 2, page);
4150

42-
if (magic == SECTION_INFO || magic == MIX_SECTION_INFO)
51+
if (type == SECTION_INFO || type == MIX_SECTION_INFO)
4352
put_page_bootmem(page);
4453
else
4554
VM_BUG_ON_PAGE(1, page);
@@ -53,8 +62,18 @@ static inline void put_page_bootmem(struct page *page)
5362
{
5463
}
5564

65+
static inline enum bootmem_type bootmem_type(const struct page *page)
66+
{
67+
return SECTION_INFO;
68+
}
69+
70+
static inline unsigned long bootmem_info(const struct page *page)
71+
{
72+
return 0;
73+
}
74+
5675
static inline void get_page_bootmem(unsigned long info, struct page *page,
57-
unsigned long type)
76+
enum bootmem_type type)
5877
{
5978
}
6079

mm/bootmem_info.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,24 @@
1414
#include <linux/memory_hotplug.h>
1515
#include <linux/kmemleak.h>
1616

17-
void get_page_bootmem(unsigned long info, struct page *page, unsigned long type)
17+
void get_page_bootmem(unsigned long info, struct page *page,
18+
enum bootmem_type type)
1819
{
19-
page->index = type;
20+
BUG_ON(type > 0xf);
21+
BUG_ON(info > (ULONG_MAX >> 4));
2022
SetPagePrivate(page);
21-
set_page_private(page, info);
23+
set_page_private(page, info << 4 | type);
2224
page_ref_inc(page);
2325
}
2426

2527
void put_page_bootmem(struct page *page)
2628
{
27-
unsigned long type = page->index;
29+
enum bootmem_type type = bootmem_type(page);
2830

2931
BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
3032
type > MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE);
3133

3234
if (page_ref_dec_return(page) == 1) {
33-
page->index = 0;
3435
ClearPagePrivate(page);
3536
set_page_private(page, 0);
3637
INIT_LIST_HEAD(&page->lru);

mm/sparse.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -720,19 +720,19 @@ static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages,
720720
static void free_map_bootmem(struct page *memmap)
721721
{
722722
unsigned long maps_section_nr, removing_section_nr, i;
723-
unsigned long magic, nr_pages;
723+
unsigned long type, nr_pages;
724724
struct page *page = virt_to_page(memmap);
725725

726726
nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
727727
>> PAGE_SHIFT;
728728

729729
for (i = 0; i < nr_pages; i++, page++) {
730-
magic = page->index;
730+
type = bootmem_type(page);
731731

732-
BUG_ON(magic == NODE_INFO);
732+
BUG_ON(type == NODE_INFO);
733733

734734
maps_section_nr = pfn_to_section_nr(page_to_pfn(page));
735-
removing_section_nr = page_private(page);
735+
removing_section_nr = bootmem_info(page);
736736

737737
/*
738738
* When this function is called, the removing section is

0 commit comments

Comments
 (0)