diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 137 |
1 files changed, 101 insertions, 36 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index df542feaac3b..fa974d87f60d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/backing-dev.h> | 48 | #include <linux/backing-dev.h> |
49 | #include <linux/fault-inject.h> | 49 | #include <linux/fault-inject.h> |
50 | #include <linux/page-isolation.h> | 50 | #include <linux/page-isolation.h> |
51 | #include <linux/page_ext.h> | ||
51 | #include <linux/debugobjects.h> | 52 | #include <linux/debugobjects.h> |
52 | #include <linux/kmemleak.h> | 53 | #include <linux/kmemleak.h> |
53 | #include <linux/compaction.h> | 54 | #include <linux/compaction.h> |
@@ -55,9 +56,10 @@ | |||
55 | #include <linux/prefetch.h> | 56 | #include <linux/prefetch.h> |
56 | #include <linux/mm_inline.h> | 57 | #include <linux/mm_inline.h> |
57 | #include <linux/migrate.h> | 58 | #include <linux/migrate.h> |
58 | #include <linux/page-debug-flags.h> | 59 | #include <linux/page_ext.h> |
59 | #include <linux/hugetlb.h> | 60 | #include <linux/hugetlb.h> |
60 | #include <linux/sched/rt.h> | 61 | #include <linux/sched/rt.h> |
62 | #include <linux/page_owner.h> | ||
61 | 63 | ||
62 | #include <asm/sections.h> | 64 | #include <asm/sections.h> |
63 | #include <asm/tlbflush.h> | 65 | #include <asm/tlbflush.h> |
@@ -424,6 +426,42 @@ static inline void prep_zero_page(struct page *page, unsigned int order, | |||
424 | 426 | ||
425 | #ifdef CONFIG_DEBUG_PAGEALLOC | 427 | #ifdef CONFIG_DEBUG_PAGEALLOC |
426 | unsigned int _debug_guardpage_minorder; | 428 | unsigned int _debug_guardpage_minorder; |
429 | bool _debug_pagealloc_enabled __read_mostly; | ||
430 | bool _debug_guardpage_enabled __read_mostly; | ||
431 | |||
432 | static int __init early_debug_pagealloc(char *buf) | ||
433 | { | ||
434 | if (!buf) | ||
435 | return -EINVAL; | ||
436 | |||
437 | if (strcmp(buf, "on") == 0) | ||
438 | _debug_pagealloc_enabled = true; | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | early_param("debug_pagealloc", early_debug_pagealloc); | ||
443 | |||
444 | static bool need_debug_guardpage(void) | ||
445 | { | ||
446 | /* If we don't use debug_pagealloc, we don't need guard page */ | ||
447 | if (!debug_pagealloc_enabled()) | ||
448 | return false; | ||
449 | |||
450 | return true; | ||
451 | } | ||
452 | |||
453 | static void init_debug_guardpage(void) | ||
454 | { | ||
455 | if (!debug_pagealloc_enabled()) | ||
456 | return; | ||
457 | |||
458 | _debug_guardpage_enabled = true; | ||
459 | } | ||
460 | |||
461 | struct page_ext_operations debug_guardpage_ops = { | ||
462 | .need = need_debug_guardpage, | ||
463 | .init = init_debug_guardpage, | ||
464 | }; | ||
427 | 465 | ||
428 | static int __init debug_guardpage_minorder_setup(char *buf) | 466 | static int __init debug_guardpage_minorder_setup(char *buf) |
429 | { | 467 | { |
@@ -439,18 +477,44 @@ static int __init debug_guardpage_minorder_setup(char *buf) | |||
439 | } | 477 | } |
440 | __setup("debug_guardpage_minorder=", debug_guardpage_minorder_setup); | 478 | __setup("debug_guardpage_minorder=", debug_guardpage_minorder_setup); |
441 | 479 | ||
442 | static inline void set_page_guard_flag(struct page *page) | 480 | static inline void set_page_guard(struct zone *zone, struct page *page, |
481 | unsigned int order, int migratetype) | ||
443 | { | 482 | { |
444 | __set_bit(PAGE_DEBUG_FLAG_GUARD, &page->debug_flags); | 483 | struct page_ext *page_ext; |
484 | |||
485 | if (!debug_guardpage_enabled()) | ||
486 | return; | ||
487 | |||
488 | page_ext = lookup_page_ext(page); | ||
489 | __set_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags); | ||
490 | |||
491 | INIT_LIST_HEAD(&page->lru); | ||
492 | set_page_private(page, order); | ||
493 | /* Guard pages are not available for any usage */ | ||
494 | __mod_zone_freepage_state(zone, -(1 << order), migratetype); | ||
445 | } | 495 | } |
446 | 496 | ||
447 | static inline void clear_page_guard_flag(struct page *page) | 497 | static inline void clear_page_guard(struct zone *zone, struct page *page, |
498 | unsigned int order, int migratetype) | ||
448 | { | 499 | { |
449 | __clear_bit(PAGE_DEBUG_FLAG_GUARD, &page->debug_flags); | 500 | struct page_ext *page_ext; |
501 | |||
502 | if (!debug_guardpage_enabled()) | ||
503 | return; | ||
504 | |||
505 | page_ext = lookup_page_ext(page); | ||
506 | __clear_bit(PAGE_EXT_DEBUG_GUARD, &page_ext->flags); | ||
507 | |||
508 | set_page_private(page, 0); | ||
509 | if (!is_migrate_isolate(migratetype)) | ||
510 | __mod_zone_freepage_state(zone, (1 << order), migratetype); | ||
450 | } | 511 | } |
451 | #else | 512 | #else |
452 | static inline void set_page_guard_flag(struct page *page) { } | 513 | struct page_ext_operations debug_guardpage_ops = { NULL, }; |
453 | static inline void clear_page_guard_flag(struct page *page) { } | 514 | static inline void set_page_guard(struct zone *zone, struct page *page, |
515 | unsigned int order, int migratetype) {} | ||
516 | static inline void clear_page_guard(struct zone *zone, struct page *page, | ||
517 | unsigned int order, int migratetype) {} | ||
454 | #endif | 518 | #endif |
455 | 519 | ||
456 | static inline void set_page_order(struct page *page, unsigned int order) | 520 | static inline void set_page_order(struct page *page, unsigned int order) |
@@ -581,12 +645,7 @@ static inline void __free_one_page(struct page *page, | |||
581 | * merge with it and move up one order. | 645 | * merge with it and move up one order. |
582 | */ | 646 | */ |
583 | if (page_is_guard(buddy)) { | 647 | if (page_is_guard(buddy)) { |
584 | clear_page_guard_flag(buddy); | 648 | clear_page_guard(zone, buddy, order, migratetype); |
585 | set_page_private(buddy, 0); | ||
586 | if (!is_migrate_isolate(migratetype)) { | ||
587 | __mod_zone_freepage_state(zone, 1 << order, | ||
588 | migratetype); | ||
589 | } | ||
590 | } else { | 649 | } else { |
591 | list_del(&buddy->lru); | 650 | list_del(&buddy->lru); |
592 | zone->free_area[order].nr_free--; | 651 | zone->free_area[order].nr_free--; |
@@ -755,6 +814,8 @@ static bool free_pages_prepare(struct page *page, unsigned int order) | |||
755 | if (bad) | 814 | if (bad) |
756 | return false; | 815 | return false; |
757 | 816 | ||
817 | reset_page_owner(page, order); | ||
818 | |||
758 | if (!PageHighMem(page)) { | 819 | if (!PageHighMem(page)) { |
759 | debug_check_no_locks_freed(page_address(page), | 820 | debug_check_no_locks_freed(page_address(page), |
760 | PAGE_SIZE << order); | 821 | PAGE_SIZE << order); |
@@ -861,23 +922,18 @@ static inline void expand(struct zone *zone, struct page *page, | |||
861 | size >>= 1; | 922 | size >>= 1; |
862 | VM_BUG_ON_PAGE(bad_range(zone, &page[size]), &page[size]); | 923 | VM_BUG_ON_PAGE(bad_range(zone, &page[size]), &page[size]); |
863 | 924 | ||
864 | #ifdef CONFIG_DEBUG_PAGEALLOC | 925 | if (IS_ENABLED(CONFIG_DEBUG_PAGEALLOC) && |
865 | if (high < debug_guardpage_minorder()) { | 926 | debug_guardpage_enabled() && |
927 | high < debug_guardpage_minorder()) { | ||
866 | /* | 928 | /* |
867 | * Mark as guard pages (or page), that will allow to | 929 | * Mark as guard pages (or page), that will allow to |
868 | * merge back to allocator when buddy will be freed. | 930 | * merge back to allocator when buddy will be freed. |
869 | * Corresponding page table entries will not be touched, | 931 | * Corresponding page table entries will not be touched, |
870 | * pages will stay not present in virtual address space | 932 | * pages will stay not present in virtual address space |
871 | */ | 933 | */ |
872 | INIT_LIST_HEAD(&page[size].lru); | 934 | set_page_guard(zone, &page[size], high, migratetype); |
873 | set_page_guard_flag(&page[size]); | ||
874 | set_page_private(&page[size], high); | ||
875 | /* Guard pages are not available for any usage */ | ||
876 | __mod_zone_freepage_state(zone, -(1 << high), | ||
877 | migratetype); | ||
878 | continue; | 935 | continue; |
879 | } | 936 | } |
880 | #endif | ||
881 | list_add(&page[size].lru, &area->free_list[migratetype]); | 937 | list_add(&page[size].lru, &area->free_list[migratetype]); |
882 | area->nr_free++; | 938 | area->nr_free++; |
883 | set_page_order(&page[size], high); | 939 | set_page_order(&page[size], high); |
@@ -935,6 +991,8 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags) | |||
935 | if (order && (gfp_flags & __GFP_COMP)) | 991 | if (order && (gfp_flags & __GFP_COMP)) |
936 | prep_compound_page(page, order); | 992 | prep_compound_page(page, order); |
937 | 993 | ||
994 | set_page_owner(page, order, gfp_flags); | ||
995 | |||
938 | return 0; | 996 | return 0; |
939 | } | 997 | } |
940 | 998 | ||
@@ -1507,8 +1565,11 @@ void split_page(struct page *page, unsigned int order) | |||
1507 | split_page(virt_to_page(page[0].shadow), order); | 1565 | split_page(virt_to_page(page[0].shadow), order); |
1508 | #endif | 1566 | #endif |
1509 | 1567 | ||
1510 | for (i = 1; i < (1 << order); i++) | 1568 | set_page_owner(page, 0, 0); |
1569 | for (i = 1; i < (1 << order); i++) { | ||
1511 | set_page_refcounted(page + i); | 1570 | set_page_refcounted(page + i); |
1571 | set_page_owner(page + i, 0, 0); | ||
1572 | } | ||
1512 | } | 1573 | } |
1513 | EXPORT_SYMBOL_GPL(split_page); | 1574 | EXPORT_SYMBOL_GPL(split_page); |
1514 | 1575 | ||
@@ -1548,6 +1609,7 @@ int __isolate_free_page(struct page *page, unsigned int order) | |||
1548 | } | 1609 | } |
1549 | } | 1610 | } |
1550 | 1611 | ||
1612 | set_page_owner(page, order, 0); | ||
1551 | return 1UL << order; | 1613 | return 1UL << order; |
1552 | } | 1614 | } |
1553 | 1615 | ||
@@ -4856,6 +4918,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, | |||
4856 | #endif | 4918 | #endif |
4857 | init_waitqueue_head(&pgdat->kswapd_wait); | 4919 | init_waitqueue_head(&pgdat->kswapd_wait); |
4858 | init_waitqueue_head(&pgdat->pfmemalloc_wait); | 4920 | init_waitqueue_head(&pgdat->pfmemalloc_wait); |
4921 | pgdat_page_ext_init(pgdat); | ||
4859 | 4922 | ||
4860 | for (j = 0; j < MAX_NR_ZONES; j++) { | 4923 | for (j = 0; j < MAX_NR_ZONES; j++) { |
4861 | struct zone *zone = pgdat->node_zones + j; | 4924 | struct zone *zone = pgdat->node_zones + j; |
@@ -4874,16 +4937,18 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, | |||
4874 | * and per-cpu initialisations | 4937 | * and per-cpu initialisations |
4875 | */ | 4938 | */ |
4876 | memmap_pages = calc_memmap_size(size, realsize); | 4939 | memmap_pages = calc_memmap_size(size, realsize); |
4877 | if (freesize >= memmap_pages) { | 4940 | if (!is_highmem_idx(j)) { |
4878 | freesize -= memmap_pages; | 4941 | if (freesize >= memmap_pages) { |
4879 | if (memmap_pages) | 4942 | freesize -= memmap_pages; |
4880 | printk(KERN_DEBUG | 4943 | if (memmap_pages) |
4881 | " %s zone: %lu pages used for memmap\n", | 4944 | printk(KERN_DEBUG |
4882 | zone_names[j], memmap_pages); | 4945 | " %s zone: %lu pages used for memmap\n", |
4883 | } else | 4946 | zone_names[j], memmap_pages); |
4884 | printk(KERN_WARNING | 4947 | } else |
4885 | " %s zone: %lu pages exceeds freesize %lu\n", | 4948 | printk(KERN_WARNING |
4886 | zone_names[j], memmap_pages, freesize); | 4949 | " %s zone: %lu pages exceeds freesize %lu\n", |
4950 | zone_names[j], memmap_pages, freesize); | ||
4951 | } | ||
4887 | 4952 | ||
4888 | /* Account for reserved pages */ | 4953 | /* Account for reserved pages */ |
4889 | if (j == 0 && freesize > dma_reserve) { | 4954 | if (j == 0 && freesize > dma_reserve) { |
@@ -6221,9 +6286,9 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count, | |||
6221 | if (!PageLRU(page)) | 6286 | if (!PageLRU(page)) |
6222 | found++; | 6287 | found++; |
6223 | /* | 6288 | /* |
6224 | * If there are RECLAIMABLE pages, we need to check it. | 6289 | * If there are RECLAIMABLE pages, we need to check |
6225 | * But now, memory offline itself doesn't call shrink_slab() | 6290 | * it. But now, memory offline itself doesn't call |
6226 | * and it still to be fixed. | 6291 | * shrink_node_slabs() and it still to be fixed. |
6227 | */ | 6292 | */ |
6228 | /* | 6293 | /* |
6229 | * If the page is not RAM, page_count()should be 0. | 6294 | * If the page is not RAM, page_count()should be 0. |