diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index fae1bd6f9f37..e361001519d3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -445,15 +445,15 @@ out: | |||
445 | /* | 445 | /* |
446 | * Higher-order pages are called "compound pages". They are structured thusly: | 446 | * Higher-order pages are called "compound pages". They are structured thusly: |
447 | * | 447 | * |
448 | * The first PAGE_SIZE page is called the "head page". | 448 | * The first PAGE_SIZE page is called the "head page" and have PG_head set. |
449 | * | 449 | * |
450 | * The remaining PAGE_SIZE pages are called "tail pages". | 450 | * The remaining PAGE_SIZE pages are called "tail pages". PageTail() is encoded |
451 | * in bit 0 of page->compound_head. The rest of bits is pointer to head page. | ||
451 | * | 452 | * |
452 | * All pages have PG_compound set. All tail pages have their ->first_page | 453 | * The first tail page's ->compound_dtor holds the offset in array of compound |
453 | * pointing at the head page. | 454 | * page destructors. See compound_page_dtors. |
454 | * | 455 | * |
455 | * The first tail page's ->lru.next holds the address of the compound page's | 456 | * The first tail page's ->compound_order holds the order of allocation. |
456 | * put_page() function. Its ->lru.prev holds the order of allocation. | ||
457 | * This usage means that zero-order pages may not be compound. | 457 | * This usage means that zero-order pages may not be compound. |
458 | */ | 458 | */ |
459 | 459 | ||
@@ -473,10 +473,7 @@ void prep_compound_page(struct page *page, unsigned long order) | |||
473 | for (i = 1; i < nr_pages; i++) { | 473 | for (i = 1; i < nr_pages; i++) { |
474 | struct page *p = page + i; | 474 | struct page *p = page + i; |
475 | set_page_count(p, 0); | 475 | set_page_count(p, 0); |
476 | p->first_page = page; | 476 | set_compound_head(p, page); |
477 | /* Make sure p->first_page is always valid for PageTail() */ | ||
478 | smp_wmb(); | ||
479 | __SetPageTail(p); | ||
480 | } | 477 | } |
481 | } | 478 | } |
482 | 479 | ||
@@ -854,17 +851,30 @@ static void free_one_page(struct zone *zone, | |||
854 | 851 | ||
855 | static int free_tail_pages_check(struct page *head_page, struct page *page) | 852 | static int free_tail_pages_check(struct page *head_page, struct page *page) |
856 | { | 853 | { |
857 | if (!IS_ENABLED(CONFIG_DEBUG_VM)) | 854 | int ret = 1; |
858 | return 0; | 855 | |
856 | /* | ||
857 | * We rely page->lru.next never has bit 0 set, unless the page | ||
858 | * is PageTail(). Let's make sure that's true even for poisoned ->lru. | ||
859 | */ | ||
860 | BUILD_BUG_ON((unsigned long)LIST_POISON1 & 1); | ||
861 | |||
862 | if (!IS_ENABLED(CONFIG_DEBUG_VM)) { | ||
863 | ret = 0; | ||
864 | goto out; | ||
865 | } | ||
859 | if (unlikely(!PageTail(page))) { | 866 | if (unlikely(!PageTail(page))) { |
860 | bad_page(page, "PageTail not set", 0); | 867 | bad_page(page, "PageTail not set", 0); |
861 | return 1; | 868 | goto out; |
862 | } | 869 | } |
863 | if (unlikely(page->first_page != head_page)) { | 870 | if (unlikely(compound_head(page) != head_page)) { |
864 | bad_page(page, "first_page not consistent", 0); | 871 | bad_page(page, "compound_head not consistent", 0); |
865 | return 1; | 872 | goto out; |
866 | } | 873 | } |
867 | return 0; | 874 | ret = 0; |
875 | out: | ||
876 | clear_compound_head(page); | ||
877 | return ret; | ||
868 | } | 878 | } |
869 | 879 | ||
870 | static void __meminit __init_single_page(struct page *page, unsigned long pfn, | 880 | static void __meminit __init_single_page(struct page *page, unsigned long pfn, |
@@ -931,6 +941,10 @@ void __meminit reserve_bootmem_region(unsigned long start, unsigned long end) | |||
931 | struct page *page = pfn_to_page(start_pfn); | 941 | struct page *page = pfn_to_page(start_pfn); |
932 | 942 | ||
933 | init_reserved_page(start_pfn); | 943 | init_reserved_page(start_pfn); |
944 | |||
945 | /* Avoid false-positive PageTail() */ | ||
946 | INIT_LIST_HEAD(&page->lru); | ||
947 | |||
934 | SetPageReserved(page); | 948 | SetPageReserved(page); |
935 | } | 949 | } |
936 | } | 950 | } |