When debug_pagealloc is enabled, we currently allocate the page_ext array to mark guard pages with the PAGE_EXT_DEBUG_GUARD flag. Now that we have the page_type field in struct page, we can use that instead, as guard pages are neither PageSlab nor mapped to userspace. This reduces memory overhead when debug_pagealloc is enabled and there are no other features requiring the page_ext array.
Unified · Split
| @@ -805,12 +805,10 @@ · 804 unmodified lines | ||
| 805 | 805 | tracking down these problems. |
| 806 | 806 | |
| 807 | 807 | debug_pagealloc= |
| 808 | − [KNL] When CONFIG_DEBUG_PAGEALLOC is set, this | |
| 809 | − parameter enables the feature at boot time. In | |
| 810 | − default, it is disabled. We can avoid allocating huge | |
| 811 | − chunk of memory for debug pagealloc if we don't enable | |
| 812 | − it at boot time and the system will work mostly same | |
| 813 | − with the kernel built without CONFIG_DEBUG_PAGEALLOC. | |
| 808 | + [KNL] When CONFIG_DEBUG_PAGEALLOC is set, this parameter | |
| 809 | + enables the feature at boot time. By default, it is | |
| 810 | + disabled and the system will work mostly the same as a | |
| 811 | + kernel built without CONFIG_DEBUG_PAGEALLOC. | |
| 814 | 812 | on: enable the feature |
| 815 | 813 | |
| 816 | 814 | debugpat [X86] Enable PAT debugging |
| @@ -2862,8 +2862,6 @@ extern long copy_huge_page_from_user(struct page *dst_page, · 2861 unmodified lines | ||
| 2862 | 2862 | bool allow_pagefault); |
| 2863 | 2863 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */ |
| 2864 | 2864 | |
| 2865 | −extern struct page_ext_operations debug_guardpage_ops; | |
| 2866 | − | |
| 2867 | 2865 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 2868 | 2866 | extern unsigned int _debug_guardpage_minorder; |
| 2869 | 2867 | DECLARE_STATIC_KEY_FALSE(_debug_guardpage_enabled); |
| @@ -2880,16 +2878,10 @@ static inline bool debug_guardpage_enabled(void) · 10 unmodified lines | ||
| 2880 | 2878 | |
| 2881 | 2879 | static inline bool page_is_guard(struct page *page) |
| 2882 | 2880 | { |
| 2883 | − struct page_ext *page_ext; | |
| 2884 | − | |
| 2885 | 2881 | if (!debug_guardpage_enabled()) |
| 2886 | 2882 | return false; |
| 2887 | 2883 | |
| 2888 | − page_ext = lookup_page_ext(page); | |
| 2889 | − if (unlikely(!page_ext)) | |
| 2890 | − return false; | |
| 2891 | − | |
| 2892 | − return test_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags); | |
| 2884 | + return PageGuard(page); | |
| 2893 | 2885 | } |
| 2894 | 2886 | #else |
| 2895 | 2887 | static inline unsigned int debug_guardpage_minorder(void) { return 0; } |
| @@ -703,6 +703,7 @@ PAGEFLAG_FALSE(DoubleMap) · 702 unmodified lines | ||
| 703 | 703 | #define PG_offline 0x00000100 |
| 704 | 704 | #define PG_kmemcg 0x00000200 |
| 705 | 705 | #define PG_table 0x00000400 |
| 706 | +#define PG_guard 0x00000800 | |
| 706 | 707 | |
| 707 | 708 | #define PageType(page, flag) \ |
| 708 | 709 | ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE) |
| @@ -754,6 +755,11 @@ PAGE_TYPE_OPS(Kmemcg, kmemcg) · 45 unmodified lines | ||
| 754 | 755 | */ |
| 755 | 756 | PAGE_TYPE_OPS(Table, table) |
| 756 | 757 | |
| 758 | +/* | |
| 759 | + * Marks guardpages used with debug_pagealloc. | |
| 760 | + */ | |
| 761 | +PAGE_TYPE_OPS(Guard, guard) | |
| 762 | + | |
| 757 | 763 | extern bool is_free_buddy_page(struct page *page); |
| 758 | 764 | |
| 759 | 765 | __PAGEFLAG(Isolated, isolated, PF_ANY); |
| @@ -17,7 +17,6 @@ struct page_ext_operations { · 16 unmodified lines | ||
| 17 | 17 | #ifdef CONFIG_PAGE_EXTENSION |
| 18 | 18 | |
| 19 | 19 | enum page_ext_flags { |
| 20 | − PAGE_EXT_DEBUG_GUARD, | |
| 21 | 20 | PAGE_EXT_OWNER, |
| 22 | 21 | #if defined(CONFIG_IDLE_PAGE_TRACKING) && !defined(CONFIG_64BIT) |
| 23 | 22 | PAGE_EXT_YOUNG, |
| @@ -12,7 +12,6 @@ config DEBUG_PAGEALLOC · 11 unmodified lines | ||
| 12 | 12 | bool "Debug page memory allocations" |
| 13 | 13 | depends on DEBUG_KERNEL |
| 14 | 14 | depends on !HIBERNATION || ARCH_SUPPORTS_DEBUG_PAGEALLOC && !PPC && !SPARC |
| 15 | − select PAGE_EXTENSION | |
| 16 | 15 | select PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC |
| 17 | 16 | ---help--- |
| 18 | 17 | Unmap pages from the kernel linear mapping after free_pages(). |
| @@ -50,7 +50,6 @@ · 49 unmodified lines | ||
| 50 | 50 | #include <linux/backing-dev.h> |
| 51 | 51 | #include <linux/fault-inject.h> |
| 52 | 52 | #include <linux/page-isolation.h> |
| 53 | −#include <linux/page_ext.h> | |
| 54 | 53 | #include <linux/debugobjects.h> |
| 55 | 54 | #include <linux/kmemleak.h> |
| 56 | 55 | #include <linux/compaction.h> |
| @@ -668,18 +667,6 @@ static int __init early_debug_pagealloc(char *buf) · 611 unmodified lines | ||
| 668 | 667 | } |
| 669 | 668 | early_param("debug_pagealloc", early_debug_pagealloc); |
| 670 | 669 | |
| 671 | −static bool need_debug_guardpage(void) | |
| 672 | −{ | |
| 673 | − /* If we don't use debug_pagealloc, we don't need guard page */ | |
| 674 | − if (!debug_pagealloc_enabled()) | |
| 675 | − return false; | |
| 676 | − | |
| 677 | − if (!debug_guardpage_minorder()) | |
| 678 | − return false; | |
| 679 | − | |
| 680 | − return true; | |
| 681 | −} | |
| 682 | − | |
| 683 | 670 | static void init_debug_guardpage(void) |
| 684 | 671 | { |
| 685 | 672 | if (!debug_pagealloc_enabled()) |
| @@ -691,11 +678,6 @@ static void init_debug_guardpage(void) · 5 unmodified lines | ||
| 691 | 678 | static_branch_enable(&_debug_guardpage_enabled); |
| 692 | 679 | } |
| 693 | 680 | |
| 694 | −struct page_ext_operations debug_guardpage_ops = { | |
| 695 | − .need = need_debug_guardpage, | |
| 696 | − .init = init_debug_guardpage, | |
| 697 | −}; | |
| 698 | − | |
| 699 | 681 | static int __init debug_guardpage_minorder_setup(char *buf) |
| 700 | 682 | { |
| 701 | 683 | unsigned long res; |
| @@ -713,20 +695,13 @@ early_param("debug_guardpage_minorder", debug_guardpage_minorder_setup); · 11 unmodified lines | ||
| 713 | 695 | static inline bool set_page_guard(struct zone *zone, struct page *page, |
| 714 | 696 | unsigned int order, int migratetype) |
| 715 | 697 | { |
| 716 | − struct page_ext *page_ext; | |
| 717 | − | |
| 718 | 698 | if (!debug_guardpage_enabled()) |
| 719 | 699 | return false; |
| 720 | 700 | |
| 721 | 701 | if (order >= debug_guardpage_minorder()) |
| 722 | 702 | return false; |
| 723 | 703 | |
| 724 | − page_ext = lookup_page_ext(page); | |
| 725 | − if (unlikely(!page_ext)) | |
| 726 | − return false; | |
| 727 | − | |
| 728 | − __set_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags); | |
| 729 | − | |
| 704 | + __SetPageGuard(page); | |
| 730 | 705 | INIT_LIST_HEAD(&page->lru); |
| 731 | 706 | set_page_private(page, order); |
| 732 | 707 | /* Guard pages are not available for any usage */ |
| @@ -738,23 +713,16 @@ static inline bool set_page_guard(struct zone *zone, struct page *page, · 5 unmodified lines | ||
| 738 | 713 | static inline void clear_page_guard(struct zone *zone, struct page *page, |
| 739 | 714 | unsigned int order, int migratetype) |
| 740 | 715 | { |
| 741 | − struct page_ext *page_ext; | |
| 742 | − | |
| 743 | 716 | if (!debug_guardpage_enabled()) |
| 744 | 717 | return; |
| 745 | 718 | |
| 746 | − page_ext = lookup_page_ext(page); | |
| 747 | − if (unlikely(!page_ext)) | |
| 748 | − return; | |
| 749 | − | |
| 750 | − __clear_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags); | |
| 719 | + __ClearPageGuard(page); | |
| 751 | 720 | |
| 752 | 721 | set_page_private(page, 0); |
| 753 | 722 | if (!is_migrate_isolate(migratetype)) |
| 754 | 723 | __mod_zone_freepage_state(zone, (1 << order), migratetype); |
| 755 | 724 | } |
| 756 | 725 | #else |
| 757 | −struct page_ext_operations debug_guardpage_ops; | |
| 758 | 726 | static inline bool set_page_guard(struct zone *zone, struct page *page, |
| 759 | 727 | unsigned int order, int migratetype) { return false; } |
| 760 | 728 | static inline void clear_page_guard(struct zone *zone, struct page *page, |
| @@ -1930,6 +1898,10 @@ void __init page_alloc_init_late(void) · 1169 unmodified lines | ||
| 1930 | 1898 | |
| 1931 | 1899 | for_each_populated_zone(zone) |
| 1932 | 1900 | set_zone_contiguous(zone); |
| 1901 | + | |
| 1902 | +#ifdef CONFIG_DEBUG_PAGEALLOC | |
| 1903 | + init_debug_guardpage(); | |
| 1904 | +#endif | |
| 1933 | 1905 | } |
| 1934 | 1906 | |
| 1935 | 1907 | #ifdef CONFIG_CMA |
| @@ -59,9 +59,6 @@ · 58 unmodified lines | ||
| 59 | 59 | */ |
| 60 | 60 | |
| 61 | 61 | static struct page_ext_operations *page_ext_ops[] = { |
| 62 | −#ifdef CONFIG_DEBUG_PAGEALLOC | |
| 63 | − &debug_guardpage_ops, | |
| 64 | −#endif | |
| 65 | 62 | #ifdef CONFIG_PAGE_OWNER |
| 66 | 63 | &page_owner_ops, |
| 67 | 64 | #endif |