Skip to content

Commit e9c0a3f

Browse files
djbwtorvalds
authored andcommitted
mm/sparsemem: convert kmalloc_section_memmap() to populate_section_memmap()
Allow sub-section sized ranges to be added to the memmap. populate_section_memmap() takes an explict pfn range rather than assuming a full section, and those parameters are plumbed all the way through to vmmemap_populate(). There should be no sub-section usage in current deployments. New warnings are added to clarify which memmap allocation paths are sub-section capable. Link: http://lkml.kernel.org/r/156092352058.979959.6551283472062305149.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams <[email protected]> Reviewed-by: Pavel Tatashin <[email protected]> Tested-by: Aneesh Kumar K.V <[email protected]> [ppc64] Reviewed-by: Oscar Salvador <[email protected]> Cc: Michal Hocko <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Logan Gunthorpe <[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 49ba3c6 commit e9c0a3f

File tree

4 files changed

+46
-33
lines changed

4 files changed

+46
-33
lines changed

arch/x86/mm/init_64.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1518,7 +1518,9 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
15181518
{
15191519
int err;
15201520

1521-
if (boot_cpu_has(X86_FEATURE_PSE))
1521+
if (end - start < PAGES_PER_SECTION * sizeof(struct page))
1522+
err = vmemmap_populate_basepages(start, end, node);
1523+
else if (boot_cpu_has(X86_FEATURE_PSE))
15221524
err = vmemmap_populate_hugepages(start, end, node, altmap);
15231525
else if (altmap) {
15241526
pr_err_once("%s: no cpu support for altmap allocations\n",

include/linux/mm.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2767,8 +2767,8 @@ static inline void print_vma_addr(char *prefix, unsigned long rip)
27672767
#endif
27682768

27692769
void *sparse_buffer_alloc(unsigned long size);
2770-
struct page *sparse_mem_map_populate(unsigned long pnum, int nid,
2771-
struct vmem_altmap *altmap);
2770+
struct page * __populate_section_memmap(unsigned long pfn,
2771+
unsigned long nr_pages, int nid, struct vmem_altmap *altmap);
27722772
pgd_t *vmemmap_pgd_populate(unsigned long addr, int node);
27732773
p4d_t *vmemmap_p4d_populate(pgd_t *pgd, unsigned long addr, int node);
27742774
pud_t *vmemmap_pud_populate(p4d_t *p4d, unsigned long addr, int node);

mm/sparse-vmemmap.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -245,19 +245,26 @@ int __meminit vmemmap_populate_basepages(unsigned long start,
245245
return 0;
246246
}
247247

248-
struct page * __meminit sparse_mem_map_populate(unsigned long pnum, int nid,
249-
struct vmem_altmap *altmap)
248+
struct page * __meminit __populate_section_memmap(unsigned long pfn,
249+
unsigned long nr_pages, int nid, struct vmem_altmap *altmap)
250250
{
251251
unsigned long start;
252252
unsigned long end;
253-
struct page *map;
254253

255-
map = pfn_to_page(pnum * PAGES_PER_SECTION);
256-
start = (unsigned long)map;
257-
end = (unsigned long)(map + PAGES_PER_SECTION);
254+
/*
255+
* The minimum granularity of memmap extensions is
256+
* PAGES_PER_SUBSECTION as allocations are tracked in the
257+
* 'subsection_map' bitmap of the section.
258+
*/
259+
end = ALIGN(pfn + nr_pages, PAGES_PER_SUBSECTION);
260+
pfn &= PAGE_SUBSECTION_MASK;
261+
nr_pages = end - pfn;
262+
263+
start = (unsigned long) pfn_to_page(pfn);
264+
end = start + nr_pages * sizeof(struct page);
258265

259266
if (vmemmap_populate(start, end, nid, altmap))
260267
return NULL;
261268

262-
return map;
269+
return pfn_to_page(pfn);
263270
}

mm/sparse.c

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,8 @@ static unsigned long __init section_map_size(void)
439439
return PAGE_ALIGN(sizeof(struct page) * PAGES_PER_SECTION);
440440
}
441441

442-
struct page __init *sparse_mem_map_populate(unsigned long pnum, int nid,
443-
struct vmem_altmap *altmap)
442+
struct page __init *__populate_section_memmap(unsigned long pfn,
443+
unsigned long nr_pages, int nid, struct vmem_altmap *altmap)
444444
{
445445
unsigned long size = section_map_size();
446446
struct page *map = sparse_buffer_alloc(size);
@@ -521,10 +521,13 @@ static void __init sparse_init_nid(int nid, unsigned long pnum_begin,
521521
}
522522
sparse_buffer_init(map_count * section_map_size(), nid);
523523
for_each_present_section_nr(pnum_begin, pnum) {
524+
unsigned long pfn = section_nr_to_pfn(pnum);
525+
524526
if (pnum >= pnum_end)
525527
break;
526528

527-
map = sparse_mem_map_populate(pnum, nid, NULL);
529+
map = __populate_section_memmap(pfn, PAGES_PER_SECTION,
530+
nid, NULL);
528531
if (!map) {
529532
pr_err("%s: node[%d] memory map backing failed. Some memory will not be available.",
530533
__func__, nid);
@@ -625,17 +628,17 @@ void offline_mem_sections(unsigned long start_pfn, unsigned long end_pfn)
625628
#endif
626629

627630
#ifdef CONFIG_SPARSEMEM_VMEMMAP
628-
static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
629-
struct vmem_altmap *altmap)
631+
static struct page *populate_section_memmap(unsigned long pfn,
632+
unsigned long nr_pages, int nid, struct vmem_altmap *altmap)
630633
{
631-
/* This will make the necessary allocations eventually. */
632-
return sparse_mem_map_populate(pnum, nid, altmap);
634+
return __populate_section_memmap(pfn, nr_pages, nid, altmap);
633635
}
634-
static void __kfree_section_memmap(struct page *memmap,
636+
637+
static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages,
635638
struct vmem_altmap *altmap)
636639
{
637-
unsigned long start = (unsigned long)memmap;
638-
unsigned long end = (unsigned long)(memmap + PAGES_PER_SECTION);
640+
unsigned long start = (unsigned long) pfn_to_page(pfn);
641+
unsigned long end = start + nr_pages * sizeof(struct page);
639642

640643
vmemmap_free(start, end, altmap);
641644
}
@@ -647,7 +650,8 @@ static void free_map_bootmem(struct page *memmap)
647650
vmemmap_free(start, end, NULL);
648651
}
649652
#else
650-
static struct page *__kmalloc_section_memmap(void)
653+
struct page *populate_section_memmap(unsigned long pfn,
654+
unsigned long nr_pages, int nid, struct vmem_altmap *altmap)
651655
{
652656
struct page *page, *ret;
653657
unsigned long memmap_size = sizeof(struct page) * PAGES_PER_SECTION;
@@ -668,15 +672,11 @@ static struct page *__kmalloc_section_memmap(void)
668672
return ret;
669673
}
670674

671-
static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
675+
static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages,
672676
struct vmem_altmap *altmap)
673677
{
674-
return __kmalloc_section_memmap();
675-
}
678+
struct page *memmap = pfn_to_page(pfn);
676679

677-
static void __kfree_section_memmap(struct page *memmap,
678-
struct vmem_altmap *altmap)
679-
{
680680
if (is_vmalloc_addr(memmap))
681681
vfree(memmap);
682682
else
@@ -745,12 +745,13 @@ int __meminit sparse_add_one_section(int nid, unsigned long start_pfn,
745745
if (ret < 0 && ret != -EEXIST)
746746
return ret;
747747
ret = 0;
748-
memmap = kmalloc_section_memmap(section_nr, nid, altmap);
748+
memmap = populate_section_memmap(start_pfn, PAGES_PER_SECTION, nid,
749+
altmap);
749750
if (!memmap)
750751
return -ENOMEM;
751752
usage = kzalloc(mem_section_usage_size(), GFP_KERNEL);
752753
if (!usage) {
753-
__kfree_section_memmap(memmap, altmap);
754+
depopulate_section_memmap(start_pfn, PAGES_PER_SECTION, altmap);
754755
return -ENOMEM;
755756
}
756757

@@ -773,7 +774,7 @@ int __meminit sparse_add_one_section(int nid, unsigned long start_pfn,
773774
out:
774775
if (ret < 0) {
775776
kfree(usage);
776-
__kfree_section_memmap(memmap, altmap);
777+
depopulate_section_memmap(start_pfn, PAGES_PER_SECTION, altmap);
777778
}
778779
return ret;
779780
}
@@ -809,7 +810,8 @@ static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
809810
#endif
810811

811812
static void free_section_usage(struct mem_section *ms, struct page *memmap,
812-
struct mem_section_usage *usage, struct vmem_altmap *altmap)
813+
struct mem_section_usage *usage, unsigned long pfn,
814+
unsigned long nr_pages, struct vmem_altmap *altmap)
813815
{
814816
if (!usage)
815817
return;
@@ -820,7 +822,7 @@ static void free_section_usage(struct mem_section *ms, struct page *memmap,
820822
if (!early_section(ms)) {
821823
kfree(usage);
822824
if (memmap)
823-
__kfree_section_memmap(memmap, altmap);
825+
depopulate_section_memmap(pfn, nr_pages, altmap);
824826
return;
825827
}
826828

@@ -849,6 +851,8 @@ void sparse_remove_one_section(struct mem_section *ms, unsigned long map_offset,
849851

850852
clear_hwpoisoned_pages(memmap + map_offset,
851853
PAGES_PER_SECTION - map_offset);
852-
free_section_usage(ms, memmap, usage, altmap);
854+
free_section_usage(ms, memmap, usage,
855+
section_nr_to_pfn(__section_nr(ms)),
856+
PAGES_PER_SECTION, altmap);
853857
}
854858
#endif /* CONFIG_MEMORY_HOTPLUG */

0 commit comments

Comments
 (0)