Skip to content

Commit 326e1b8

Browse files
djbwtorvalds
authored andcommitted
mm/sparsemem: introduce a SECTION_IS_EARLY flag
In preparation for sub-section hotplug, track whether a given section was created during early memory initialization, or later via memory hotplug. This distinction is needed to maintain the coarse expectation that pfn_valid() returns true for any pfn within a given section even if that section has pages that are reserved from the page allocator. For example one of the of goals of subsection hotplug is to support cases where the system physical memory layout collides System RAM and PMEM within a section. Several pfn_valid() users expect to just check if a section is valid, but they are not careful to check if the given pfn is within a "System RAM" boundary and instead expect pgdat information to further validate the pfn. Rather than unwind those paths to make their pfn_valid() queries more precise a follow on patch uses the SECTION_IS_EARLY flag to maintain the traditional expectation that pfn_valid() returns true for all early sections. Link: https://lore.kernel.org/lkml/[email protected]/ Link: http://lkml.kernel.org/r/156092350358.979959.5817209875548072819.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams <[email protected]> Reported-by: Qian Cai <[email protected]> Tested-by: Aneesh Kumar K.V <[email protected]> [ppc64] Reviewed-by: Oscar Salvador <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Logan Gunthorpe <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Pavel Tatashin <[email protected]> Cc: Jane Chu <[email protected]> Cc: Jeff Moyer <[email protected]> Cc: Jérôme Glisse <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Mike Rapoport <[email protected]> Cc: Toshi Kani <[email protected]> Cc: Vlastimil Babka <[email protected]> Cc: Wei Yang <[email protected]> Cc: Jason Gunthorpe <[email protected]> Cc: Christoph Hellwig <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent f1eca35 commit 326e1b8

File tree

2 files changed

+16
-12
lines changed

2 files changed

+16
-12
lines changed

include/linux/mmzone.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,8 @@ extern size_t mem_section_usage_size(void);
12601260
#define SECTION_MARKED_PRESENT (1UL<<0)
12611261
#define SECTION_HAS_MEM_MAP (1UL<<1)
12621262
#define SECTION_IS_ONLINE (1UL<<2)
1263-
#define SECTION_MAP_LAST_BIT (1UL<<3)
1263+
#define SECTION_IS_EARLY (1UL<<3)
1264+
#define SECTION_MAP_LAST_BIT (1UL<<4)
12641265
#define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1))
12651266
#define SECTION_NID_SHIFT 3
12661267

@@ -1286,6 +1287,11 @@ static inline int valid_section(struct mem_section *section)
12861287
return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP));
12871288
}
12881289

1290+
static inline int early_section(struct mem_section *section)
1291+
{
1292+
return (section && (section->section_mem_map & SECTION_IS_EARLY));
1293+
}
1294+
12891295
static inline int valid_section_nr(unsigned long nr)
12901296
{
12911297
return valid_section(__nr_to_section(nr));

mm/sparse.c

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -288,11 +288,11 @@ struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pn
288288

289289
static void __meminit sparse_init_one_section(struct mem_section *ms,
290290
unsigned long pnum, struct page *mem_map,
291-
struct mem_section_usage *usage)
291+
struct mem_section_usage *usage, unsigned long flags)
292292
{
293293
ms->section_mem_map &= ~SECTION_MAP_MASK;
294-
ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum) |
295-
SECTION_HAS_MEM_MAP;
294+
ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum)
295+
| SECTION_HAS_MEM_MAP | flags;
296296
ms->usage = usage;
297297
}
298298

@@ -497,7 +497,8 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
497497
goto failed;
498498
}
499499
check_usemap_section_nr(nid, usage);
500-
sparse_init_one_section(__nr_to_section(pnum), pnum, map, usage);
500+
sparse_init_one_section(__nr_to_section(pnum), pnum, map, usage,
501+
SECTION_IS_EARLY);
501502
usage = (void *) usage + mem_section_usage_size();
502503
}
503504
sparse_buffer_fini();
@@ -732,7 +733,7 @@ int __meminit sparse_add_one_section(int nid, unsigned long start_pfn,
732733

733734
set_section_nid(section_nr, nid);
734735
section_mark_present(ms);
735-
sparse_init_one_section(ms, section_nr, memmap, usage);
736+
sparse_init_one_section(ms, section_nr, memmap, usage, 0);
736737

737738
out:
738739
if (ret < 0) {
@@ -772,19 +773,16 @@ static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
772773
}
773774
#endif
774775

775-
static void free_section_usage(struct page *memmap,
776+
static void free_section_usage(struct mem_section *ms, struct page *memmap,
776777
struct mem_section_usage *usage, struct vmem_altmap *altmap)
777778
{
778-
struct page *usage_page;
779-
780779
if (!usage)
781780
return;
782781

783-
usage_page = virt_to_page(usage);
784782
/*
785783
* Check to see if allocation came from hot-plug-add
786784
*/
787-
if (PageSlab(usage_page) || PageCompound(usage_page)) {
785+
if (!early_section(ms)) {
788786
kfree(usage);
789787
if (memmap)
790788
__kfree_section_memmap(memmap, altmap);
@@ -816,6 +814,6 @@ void sparse_remove_one_section(struct mem_section *ms, unsigned long map_offset,
816814

817815
clear_hwpoisoned_pages(memmap + map_offset,
818816
PAGES_PER_SECTION - map_offset);
819-
free_section_usage(memmap, usage, altmap);
817+
free_section_usage(ms, memmap, usage, altmap);
820818
}
821819
#endif /* CONFIG_MEMORY_HOTPLUG */

0 commit comments

Comments
 (0)