summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Ghiti <alex@ghiti.fr>2019-05-13 20:19:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-14 12:47:47 -0400
commit4eb0716e868eed963967adb0b1b11d9bd8ca1d01 (patch)
tree9a0c02c0e31c0c3c462796f024986a02e3b1fc45
parent8df995f6bde01de96ce93373785f41c3bd13ad1c (diff)
hugetlb: allow to free gigantic pages regardless of the configuration
On systems without CONTIG_ALLOC activated but that support gigantic pages, boottime reserved gigantic pages can not be freed at all. This patch simply enables the possibility to hand back those pages to memory allocator. Link: http://lkml.kernel.org/r/20190327063626.18421-5-alex@ghiti.fr Signed-off-by: Alexandre Ghiti <alex@ghiti.fr> Acked-by: David S. Miller <davem@davemloft.net> [sparc] Reviewed-by: Mike Kravetz <mike.kravetz@oracle.com> Cc: Andy Lutomirsky <luto@kernel.org> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: "H . Peter Anvin" <hpa@zytor.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rich Felker <dalias@libc.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Will Deacon <will.deacon@arm.com> Cc: Yoshinori Sato <ysato@users.sourceforge.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/arm64/Kconfig2
-rw-r--r--arch/arm64/include/asm/hugetlb.h4
-rw-r--r--arch/powerpc/include/asm/book3s/64/hugetlb.h5
-rw-r--r--arch/powerpc/platforms/Kconfig.cputype2
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/s390/include/asm/hugetlb.h8
-rw-r--r--arch/sh/Kconfig2
-rw-r--r--arch/sparc/Kconfig2
-rw-r--r--arch/x86/Kconfig2
-rw-r--r--arch/x86/include/asm/hugetlb.h4
-rw-r--r--include/asm-generic/hugetlb.h7
-rw-r--r--include/linux/gfp.h2
-rw-r--r--mm/hugetlb.c54
-rw-r--r--mm/page_alloc.c4
14 files changed, 61 insertions, 39 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 7f7fbd8bd9d5..7a1aa53d188d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -19,7 +19,7 @@ config ARM64
19 select ARCH_HAS_FAST_MULTIPLIER 19 select ARCH_HAS_FAST_MULTIPLIER
20 select ARCH_HAS_FORTIFY_SOURCE 20 select ARCH_HAS_FORTIFY_SOURCE
21 select ARCH_HAS_GCOV_PROFILE_ALL 21 select ARCH_HAS_GCOV_PROFILE_ALL
22 select ARCH_HAS_GIGANTIC_PAGE if CONTIG_ALLOC 22 select ARCH_HAS_GIGANTIC_PAGE
23 select ARCH_HAS_KCOV 23 select ARCH_HAS_KCOV
24 select ARCH_HAS_KEEPINITRD 24 select ARCH_HAS_KEEPINITRD
25 select ARCH_HAS_MEMBARRIER_SYNC_CORE 25 select ARCH_HAS_MEMBARRIER_SYNC_CORE
diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index c6a07a3b433e..4aad6382f631 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -70,8 +70,4 @@ extern void set_huge_swap_pte_at(struct mm_struct *mm, unsigned long addr,
70 70
71#include <asm-generic/hugetlb.h> 71#include <asm-generic/hugetlb.h>
72 72
73#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
74static inline bool gigantic_page_supported(void) { return true; }
75#endif
76
77#endif /* __ASM_HUGETLB_H */ 73#endif /* __ASM_HUGETLB_H */
diff --git a/arch/powerpc/include/asm/book3s/64/hugetlb.h b/arch/powerpc/include/asm/book3s/64/hugetlb.h
index 56140d19c85f..12e150e615b7 100644
--- a/arch/powerpc/include/asm/book3s/64/hugetlb.h
+++ b/arch/powerpc/include/asm/book3s/64/hugetlb.h
@@ -36,8 +36,8 @@ static inline int hstate_get_psize(struct hstate *hstate)
36 } 36 }
37} 37}
38 38
39#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE 39#define __HAVE_ARCH_GIGANTIC_PAGE_RUNTIME_SUPPORTED
40static inline bool gigantic_page_supported(void) 40static inline bool gigantic_page_runtime_supported(void)
41{ 41{
42 /* 42 /*
43 * We used gigantic page reservation with hypervisor assist in some case. 43 * We used gigantic page reservation with hypervisor assist in some case.
@@ -49,7 +49,6 @@ static inline bool gigantic_page_supported(void)
49 49
50 return true; 50 return true;
51} 51}
52#endif
53 52
54/* hugepd entry valid bit */ 53/* hugepd entry valid bit */
55#define HUGEPD_VAL_BITS (0x8000000000000000UL) 54#define HUGEPD_VAL_BITS (0x8000000000000000UL)
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 3a31d4289ea4..2794235e9d3e 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -331,7 +331,7 @@ config ARCH_ENABLE_SPLIT_PMD_PTLOCK
331config PPC_RADIX_MMU 331config PPC_RADIX_MMU
332 bool "Radix MMU Support" 332 bool "Radix MMU Support"
333 depends on PPC_BOOK3S_64 && HUGETLB_PAGE 333 depends on PPC_BOOK3S_64 && HUGETLB_PAGE
334 select ARCH_HAS_GIGANTIC_PAGE if CONTIG_ALLOC 334 select ARCH_HAS_GIGANTIC_PAGE
335 select PPC_HAVE_KUEP 335 select PPC_HAVE_KUEP
336 select PPC_HAVE_KUAP 336 select PPC_HAVE_KUAP
337 default y 337 default y
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 724dbc6b7d33..d0c046af65fa 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -63,7 +63,7 @@ config S390
63 select ARCH_HAS_ELF_RANDOMIZE 63 select ARCH_HAS_ELF_RANDOMIZE
64 select ARCH_HAS_FORTIFY_SOURCE 64 select ARCH_HAS_FORTIFY_SOURCE
65 select ARCH_HAS_GCOV_PROFILE_ALL 65 select ARCH_HAS_GCOV_PROFILE_ALL
66 select ARCH_HAS_GIGANTIC_PAGE if CONTIG_ALLOC 66 select ARCH_HAS_GIGANTIC_PAGE
67 select ARCH_HAS_KCOV 67 select ARCH_HAS_KCOV
68 select ARCH_HAS_PTE_SPECIAL 68 select ARCH_HAS_PTE_SPECIAL
69 select ARCH_HAS_SET_MEMORY 69 select ARCH_HAS_SET_MEMORY
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index 2d1afa58a4b6..bb59dd964590 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -116,7 +116,9 @@ static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)
116 return pte_modify(pte, newprot); 116 return pte_modify(pte, newprot);
117} 117}
118 118
119#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE 119static inline bool gigantic_page_runtime_supported(void)
120static inline bool gigantic_page_supported(void) { return true; } 120{
121#endif 121 return true;
122}
123
122#endif /* _ASM_S390_HUGETLB_H */ 124#endif /* _ASM_S390_HUGETLB_H */
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 2a5ec643fec0..2a77033e1e7c 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -53,7 +53,7 @@ config SUPERH
53 select HAVE_FUTEX_CMPXCHG if FUTEX 53 select HAVE_FUTEX_CMPXCHG if FUTEX
54 select HAVE_NMI 54 select HAVE_NMI
55 select NEED_SG_DMA_LENGTH 55 select NEED_SG_DMA_LENGTH
56 select ARCH_HAS_GIGANTIC_PAGE if CONTIG_ALLOC 56 select ARCH_HAS_GIGANTIC_PAGE
57 57
58 help 58 help
59 The SuperH is a RISC processor targeted for use in embedded systems 59 The SuperH is a RISC processor targeted for use in embedded systems
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 566de738e487..7c93f3121ee6 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -92,7 +92,7 @@ config SPARC64
92 select ARCH_CLOCKSOURCE_DATA 92 select ARCH_CLOCKSOURCE_DATA
93 select ARCH_HAS_PTE_SPECIAL 93 select ARCH_HAS_PTE_SPECIAL
94 select PCI_DOMAINS if PCI 94 select PCI_DOMAINS if PCI
95 select ARCH_HAS_GIGANTIC_PAGE if CONTIG_ALLOC 95 select ARCH_HAS_GIGANTIC_PAGE
96 96
97config ARCH_DEFCONFIG 97config ARCH_DEFCONFIG
98 string 98 string
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 526d95abfe5e..f21bc56e5d7b 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -22,7 +22,7 @@ config X86_64
22 def_bool y 22 def_bool y
23 depends on 64BIT 23 depends on 64BIT
24 # Options that are inherently 64-bit kernel only: 24 # Options that are inherently 64-bit kernel only:
25 select ARCH_HAS_GIGANTIC_PAGE if CONTIG_ALLOC 25 select ARCH_HAS_GIGANTIC_PAGE
26 select ARCH_SUPPORTS_INT128 26 select ARCH_SUPPORTS_INT128
27 select ARCH_USE_CMPXCHG_LOCKREF 27 select ARCH_USE_CMPXCHG_LOCKREF
28 select HAVE_ARCH_SOFT_DIRTY 28 select HAVE_ARCH_SOFT_DIRTY
diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h
index 7469d321f072..f65cfb48cfdd 100644
--- a/arch/x86/include/asm/hugetlb.h
+++ b/arch/x86/include/asm/hugetlb.h
@@ -17,8 +17,4 @@ static inline void arch_clear_hugepage_flags(struct page *page)
17{ 17{
18} 18}
19 19
20#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
21static inline bool gigantic_page_supported(void) { return true; }
22#endif
23
24#endif /* _ASM_X86_HUGETLB_H */ 20#endif /* _ASM_X86_HUGETLB_H */
diff --git a/include/asm-generic/hugetlb.h b/include/asm-generic/hugetlb.h
index 71d7b77eea50..822f433ac95c 100644
--- a/include/asm-generic/hugetlb.h
+++ b/include/asm-generic/hugetlb.h
@@ -126,4 +126,11 @@ static inline pte_t huge_ptep_get(pte_t *ptep)
126} 126}
127#endif 127#endif
128 128
129#ifndef __HAVE_ARCH_GIGANTIC_PAGE_RUNTIME_SUPPORTED
130static inline bool gigantic_page_runtime_supported(void)
131{
132 return IS_ENABLED(CONFIG_ARCH_HAS_GIGANTIC_PAGE);
133}
134#endif /* __HAVE_ARCH_GIGANTIC_PAGE_RUNTIME_SUPPORTED */
135
129#endif /* _ASM_GENERIC_HUGETLB_H */ 136#endif /* _ASM_GENERIC_HUGETLB_H */
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index e77ab30e9328..fb07b503dc45 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -589,8 +589,8 @@ static inline bool pm_suspended_storage(void)
589/* The below functions must be run on a range from a single zone. */ 589/* The below functions must be run on a range from a single zone. */
590extern int alloc_contig_range(unsigned long start, unsigned long end, 590extern int alloc_contig_range(unsigned long start, unsigned long end,
591 unsigned migratetype, gfp_t gfp_mask); 591 unsigned migratetype, gfp_t gfp_mask);
592extern void free_contig_range(unsigned long pfn, unsigned nr_pages);
593#endif 592#endif
593void free_contig_range(unsigned long pfn, unsigned int nr_pages);
594 594
595#ifdef CONFIG_CMA 595#ifdef CONFIG_CMA
596/* CMA stuff */ 596/* CMA stuff */
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index dffe5d9d03ae..2f901a6e13d2 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1059,6 +1059,7 @@ static void free_gigantic_page(struct page *page, unsigned int order)
1059 free_contig_range(page_to_pfn(page), 1 << order); 1059 free_contig_range(page_to_pfn(page), 1 << order);
1060} 1060}
1061 1061
1062#ifdef CONFIG_CONTIG_ALLOC
1062static int __alloc_gigantic_page(unsigned long start_pfn, 1063static int __alloc_gigantic_page(unsigned long start_pfn,
1063 unsigned long nr_pages, gfp_t gfp_mask) 1064 unsigned long nr_pages, gfp_t gfp_mask)
1064{ 1065{
@@ -1143,11 +1144,20 @@ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
1143 1144
1144static void prep_new_huge_page(struct hstate *h, struct page *page, int nid); 1145static void prep_new_huge_page(struct hstate *h, struct page *page, int nid);
1145static void prep_compound_gigantic_page(struct page *page, unsigned int order); 1146static void prep_compound_gigantic_page(struct page *page, unsigned int order);
1147#else /* !CONFIG_CONTIG_ALLOC */
1148static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
1149 int nid, nodemask_t *nodemask)
1150{
1151 return NULL;
1152}
1153#endif /* CONFIG_CONTIG_ALLOC */
1146 1154
1147#else /* !CONFIG_ARCH_HAS_GIGANTIC_PAGE */ 1155#else /* !CONFIG_ARCH_HAS_GIGANTIC_PAGE */
1148static inline bool gigantic_page_supported(void) { return false; }
1149static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask, 1156static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
1150 int nid, nodemask_t *nodemask) { return NULL; } 1157 int nid, nodemask_t *nodemask)
1158{
1159 return NULL;
1160}
1151static inline void free_gigantic_page(struct page *page, unsigned int order) { } 1161static inline void free_gigantic_page(struct page *page, unsigned int order) { }
1152static inline void destroy_compound_gigantic_page(struct page *page, 1162static inline void destroy_compound_gigantic_page(struct page *page,
1153 unsigned int order) { } 1163 unsigned int order) { }
@@ -1157,7 +1167,7 @@ static void update_and_free_page(struct hstate *h, struct page *page)
1157{ 1167{
1158 int i; 1168 int i;
1159 1169
1160 if (hstate_is_gigantic(h) && !gigantic_page_supported()) 1170 if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported())
1161 return; 1171 return;
1162 1172
1163 h->nr_huge_pages--; 1173 h->nr_huge_pages--;
@@ -2278,13 +2288,27 @@ found:
2278} 2288}
2279 2289
2280#define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages) 2290#define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages)
2281static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count, 2291static int set_max_huge_pages(struct hstate *h, unsigned long count,
2282 nodemask_t *nodes_allowed) 2292 nodemask_t *nodes_allowed)
2283{ 2293{
2284 unsigned long min_count, ret; 2294 unsigned long min_count, ret;
2285 2295
2286 if (hstate_is_gigantic(h) && !gigantic_page_supported()) 2296 spin_lock(&hugetlb_lock);
2287 return h->max_huge_pages; 2297
2298 /*
2299 * Gigantic pages runtime allocation depend on the capability for large
2300 * page range allocation.
2301 * If the system does not provide this feature, return an error when
2302 * the user tries to allocate gigantic pages but let the user free the
2303 * boottime allocated gigantic pages.
2304 */
2305 if (hstate_is_gigantic(h) && !IS_ENABLED(CONFIG_CONTIG_ALLOC)) {
2306 if (count > persistent_huge_pages(h)) {
2307 spin_unlock(&hugetlb_lock);
2308 return -EINVAL;
2309 }
2310 /* Fall through to decrease pool */
2311 }
2288 2312
2289 /* 2313 /*
2290 * Increase the pool size 2314 * Increase the pool size
@@ -2297,7 +2321,6 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
2297 * pool might be one hugepage larger than it needs to be, but 2321 * pool might be one hugepage larger than it needs to be, but
2298 * within all the constraints specified by the sysctls. 2322 * within all the constraints specified by the sysctls.
2299 */ 2323 */
2300 spin_lock(&hugetlb_lock);
2301 while (h->surplus_huge_pages && count > persistent_huge_pages(h)) { 2324 while (h->surplus_huge_pages && count > persistent_huge_pages(h)) {
2302 if (!adjust_pool_surplus(h, nodes_allowed, -1)) 2325 if (!adjust_pool_surplus(h, nodes_allowed, -1))
2303 break; 2326 break;
@@ -2352,9 +2375,10 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
2352 break; 2375 break;
2353 } 2376 }
2354out: 2377out:
2355 ret = persistent_huge_pages(h); 2378 h->max_huge_pages = persistent_huge_pages(h);
2356 spin_unlock(&hugetlb_lock); 2379 spin_unlock(&hugetlb_lock);
2357 return ret; 2380
2381 return 0;
2358} 2382}
2359 2383
2360#define HSTATE_ATTR_RO(_name) \ 2384#define HSTATE_ATTR_RO(_name) \
@@ -2406,7 +2430,7 @@ static ssize_t __nr_hugepages_store_common(bool obey_mempolicy,
2406 int err; 2430 int err;
2407 NODEMASK_ALLOC(nodemask_t, nodes_allowed, GFP_KERNEL | __GFP_NORETRY); 2431 NODEMASK_ALLOC(nodemask_t, nodes_allowed, GFP_KERNEL | __GFP_NORETRY);
2408 2432
2409 if (hstate_is_gigantic(h) && !gigantic_page_supported()) { 2433 if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported()) {
2410 err = -EINVAL; 2434 err = -EINVAL;
2411 goto out; 2435 goto out;
2412 } 2436 }
@@ -2430,15 +2454,13 @@ static ssize_t __nr_hugepages_store_common(bool obey_mempolicy,
2430 } else 2454 } else
2431 nodes_allowed = &node_states[N_MEMORY]; 2455 nodes_allowed = &node_states[N_MEMORY];
2432 2456
2433 h->max_huge_pages = set_max_huge_pages(h, count, nodes_allowed); 2457 err = set_max_huge_pages(h, count, nodes_allowed);
2434 2458
2459out:
2435 if (nodes_allowed != &node_states[N_MEMORY]) 2460 if (nodes_allowed != &node_states[N_MEMORY])
2436 NODEMASK_FREE(nodes_allowed); 2461 NODEMASK_FREE(nodes_allowed);
2437 2462
2438 return len; 2463 return err ? err : len;
2439out:
2440 NODEMASK_FREE(nodes_allowed);
2441 return err;
2442} 2464}
2443 2465
2444static ssize_t nr_hugepages_store_common(bool obey_mempolicy, 2466static ssize_t nr_hugepages_store_common(bool obey_mempolicy,
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2efb6525d932..4ea71bc70413 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -8346,8 +8346,9 @@ done:
8346 pfn_max_align_up(end), migratetype); 8346 pfn_max_align_up(end), migratetype);
8347 return ret; 8347 return ret;
8348} 8348}
8349#endif /* CONFIG_CONTIG_ALLOC */
8349 8350
8350void free_contig_range(unsigned long pfn, unsigned nr_pages) 8351void free_contig_range(unsigned long pfn, unsigned int nr_pages)
8351{ 8352{
8352 unsigned int count = 0; 8353 unsigned int count = 0;
8353 8354
@@ -8359,7 +8360,6 @@ void free_contig_range(unsigned long pfn, unsigned nr_pages)
8359 } 8360 }
8360 WARN(count != 0, "%d pages are still in use!\n", count); 8361 WARN(count != 0, "%d pages are still in use!\n", count);
8361} 8362}
8362#endif
8363 8363
8364#ifdef CONFIG_MEMORY_HOTPLUG 8364#ifdef CONFIG_MEMORY_HOTPLUG
8365/* 8365/*