aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/Kconfig.debug1
-rw-r--r--mm/debug-pagealloc.c37
-rw-r--r--mm/page_alloc.c38
-rw-r--r--mm/page_ext.c4
4 files changed, 73 insertions, 7 deletions
diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
index 1ba81c7769f7..56badfc4810a 100644
--- a/mm/Kconfig.debug
+++ b/mm/Kconfig.debug
@@ -12,6 +12,7 @@ config DEBUG_PAGEALLOC
12 depends on DEBUG_KERNEL 12 depends on DEBUG_KERNEL
13 depends on !HIBERNATION || ARCH_SUPPORTS_DEBUG_PAGEALLOC && !PPC && !SPARC 13 depends on !HIBERNATION || ARCH_SUPPORTS_DEBUG_PAGEALLOC && !PPC && !SPARC
14 depends on !KMEMCHECK 14 depends on !KMEMCHECK
15 select PAGE_EXTENSION
15 select PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC 16 select PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC
16 select PAGE_GUARD if ARCH_SUPPORTS_DEBUG_PAGEALLOC 17 select PAGE_GUARD if ARCH_SUPPORTS_DEBUG_PAGEALLOC
17 ---help--- 18 ---help---
diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c
index 789ff70c8a4a..0072f2c53331 100644
--- a/mm/debug-pagealloc.c
+++ b/mm/debug-pagealloc.c
@@ -2,23 +2,49 @@
2#include <linux/string.h> 2#include <linux/string.h>
3#include <linux/mm.h> 3#include <linux/mm.h>
4#include <linux/highmem.h> 4#include <linux/highmem.h>
5#include <linux/page-debug-flags.h> 5#include <linux/page_ext.h>
6#include <linux/poison.h> 6#include <linux/poison.h>
7#include <linux/ratelimit.h> 7#include <linux/ratelimit.h>
8 8
9static bool page_poisoning_enabled __read_mostly;
10
11static bool need_page_poisoning(void)
12{
13 return true;
14}
15
16static void init_page_poisoning(void)
17{
18 page_poisoning_enabled = true;
19}
20
21struct page_ext_operations page_poisoning_ops = {
22 .need = need_page_poisoning,
23 .init = init_page_poisoning,
24};
25
9static inline void set_page_poison(struct page *page) 26static inline void set_page_poison(struct page *page)
10{ 27{
11 __set_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); 28 struct page_ext *page_ext;
29
30 page_ext = lookup_page_ext(page);
31 __set_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
12} 32}
13 33
14static inline void clear_page_poison(struct page *page) 34static inline void clear_page_poison(struct page *page)
15{ 35{
16 __clear_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); 36 struct page_ext *page_ext;
37
38 page_ext = lookup_page_ext(page);
39 __clear_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
17} 40}
18 41
19static inline bool page_poison(struct page *page) 42static inline bool page_poison(struct page *page)
20{ 43{
21 return test_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); 44 struct page_ext *page_ext;
45
46 page_ext = lookup_page_ext(page);
47 return test_bit(PAGE_EXT_DEBUG_POISON, &page_ext->flags);
22} 48}
23 49
24static void poison_page(struct page *page) 50static void poison_page(struct page *page)
@@ -95,6 +121,9 @@ static void unpoison_pages(struct page *page, int n)
95 121
96void kernel_map_pages(struct page *page, int numpages, int enable) 122void kernel_map_pages(struct page *page, int numpages, int enable)
97{ 123{
124 if (!page_poisoning_enabled)
125 return;
126
98 if (enable) 127 if (enable)
99 unpoison_pages(page, numpages); 128 unpoison_pages(page, numpages);
100 else 129 else
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b64666cf5865..e0a39d328ca1 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -56,7 +56,7 @@
56#include <linux/prefetch.h> 56#include <linux/prefetch.h>
57#include <linux/mm_inline.h> 57#include <linux/mm_inline.h>
58#include <linux/migrate.h> 58#include <linux/migrate.h>
59#include <linux/page-debug-flags.h> 59#include <linux/page_ext.h>
60#include <linux/hugetlb.h> 60#include <linux/hugetlb.h>
61#include <linux/sched/rt.h> 61#include <linux/sched/rt.h>
62 62
@@ -425,6 +425,22 @@ static inline void prep_zero_page(struct page *page, unsigned int order,
425 425
426#ifdef CONFIG_DEBUG_PAGEALLOC 426#ifdef CONFIG_DEBUG_PAGEALLOC
427unsigned int _debug_guardpage_minorder; 427unsigned int _debug_guardpage_minorder;
428bool _debug_guardpage_enabled __read_mostly;
429
430static bool need_debug_guardpage(void)
431{
432 return true;
433}
434
435static void init_debug_guardpage(void)
436{
437 _debug_guardpage_enabled = true;
438}
439
440struct page_ext_operations debug_guardpage_ops = {
441 .need = need_debug_guardpage,
442 .init = init_debug_guardpage,
443};
428 444
429static int __init debug_guardpage_minorder_setup(char *buf) 445static int __init debug_guardpage_minorder_setup(char *buf)
430{ 446{
@@ -443,7 +459,14 @@ __setup("debug_guardpage_minorder=", debug_guardpage_minorder_setup);
443static inline void set_page_guard(struct zone *zone, struct page *page, 459static inline void set_page_guard(struct zone *zone, struct page *page,
444 unsigned int order, int migratetype) 460 unsigned int order, int migratetype)
445{ 461{
446 __set_bit(PAGE_DEBUG_FLAG_GUARD, &page->debug_flags); 462 struct page_ext *page_ext;
463
464 if (!debug_guardpage_enabled())
465 return;
466
467 page_ext = lookup_page_ext(page);
468 __set_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags);
469
447 INIT_LIST_HEAD(&page->lru); 470 INIT_LIST_HEAD(&page->lru);
448 set_page_private(page, order); 471 set_page_private(page, order);
449 /* Guard pages are not available for any usage */ 472 /* Guard pages are not available for any usage */
@@ -453,12 +476,20 @@ static inline void set_page_guard(struct zone *zone, struct page *page,
453static inline void clear_page_guard(struct zone *zone, struct page *page, 476static inline void clear_page_guard(struct zone *zone, struct page *page,
454 unsigned int order, int migratetype) 477 unsigned int order, int migratetype)
455{ 478{
456 __clear_bit(PAGE_DEBUG_FLAG_GUARD, &page->debug_flags); 479 struct page_ext *page_ext;
480
481 if (!debug_guardpage_enabled())
482 return;
483
484 page_ext = lookup_page_ext(page);
485 __clear_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags);
486
457 set_page_private(page, 0); 487 set_page_private(page, 0);
458 if (!is_migrate_isolate(migratetype)) 488 if (!is_migrate_isolate(migratetype))
459 __mod_zone_freepage_state(zone, (1 << order), migratetype); 489 __mod_zone_freepage_state(zone, (1 << order), migratetype);
460} 490}
461#else 491#else
492struct page_ext_operations debug_guardpage_ops = { NULL, };
462static inline void set_page_guard(struct zone *zone, struct page *page, 493static inline void set_page_guard(struct zone *zone, struct page *page,
463 unsigned int order, int migratetype) {} 494 unsigned int order, int migratetype) {}
464static inline void clear_page_guard(struct zone *zone, struct page *page, 495static inline void clear_page_guard(struct zone *zone, struct page *page,
@@ -869,6 +900,7 @@ static inline void expand(struct zone *zone, struct page *page,
869 VM_BUG_ON_PAGE(bad_range(zone, &page[size]), &page[size]); 900 VM_BUG_ON_PAGE(bad_range(zone, &page[size]), &page[size]);
870 901
871 if (IS_ENABLED(CONFIG_DEBUG_PAGEALLOC) && 902 if (IS_ENABLED(CONFIG_DEBUG_PAGEALLOC) &&
903 debug_guardpage_enabled() &&
872 high < debug_guardpage_minorder()) { 904 high < debug_guardpage_minorder()) {
873 /* 905 /*
874 * Mark as guard pages (or page), that will allow to 906 * Mark as guard pages (or page), that will allow to
diff --git a/mm/page_ext.c b/mm/page_ext.c
index 514a3bccd63f..c2cd7b15f0de 100644
--- a/mm/page_ext.c
+++ b/mm/page_ext.c
@@ -51,6 +51,10 @@
51 */ 51 */
52 52
53static struct page_ext_operations *page_ext_ops[] = { 53static struct page_ext_operations *page_ext_ops[] = {
54 &debug_guardpage_ops,
55#ifdef CONFIG_PAGE_POISONING
56 &page_poisoning_ops,
57#endif
54}; 58};
55 59
56static unsigned long total_usage; 60static unsigned long total_usage;