Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm/page_owner: set correct gfp_mask on page_owner

Currently, we set wrong gfp_mask to page_owner info in case of isolated
freepage by compaction and split page. It causes incorrect mixed
pageblock report that we can get from '/proc/pagetypeinfo'. This metric
is really useful to measure fragmentation effect so should be accurate.
This patch fixes it by setting correct information.

Without this patch, after kernel build workload is finished, number of
mixed pageblock is 112 among roughly 210 movable pageblocks.

But, with this fix, output shows that mixed pageblock is just 57.

Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Joonsoo Kim and committed by
Linus Torvalds
e2cfc911 f3a14ced

+25 -3
+13
include/linux/page_owner.h
··· 8 8 extern void __reset_page_owner(struct page *page, unsigned int order); 9 9 extern void __set_page_owner(struct page *page, 10 10 unsigned int order, gfp_t gfp_mask); 11 + extern gfp_t __get_page_owner_gfp(struct page *page); 11 12 12 13 static inline void reset_page_owner(struct page *page, unsigned int order) 13 14 { ··· 26 25 27 26 __set_page_owner(page, order, gfp_mask); 28 27 } 28 + 29 + static inline gfp_t get_page_owner_gfp(struct page *page) 30 + { 31 + if (likely(!page_owner_inited)) 32 + return 0; 33 + 34 + return __get_page_owner_gfp(page); 35 + } 29 36 #else 30 37 static inline void reset_page_owner(struct page *page, unsigned int order) 31 38 { ··· 41 32 static inline void set_page_owner(struct page *page, 42 33 unsigned int order, gfp_t gfp_mask) 43 34 { 35 + } 36 + static inline gfp_t get_page_owner_gfp(struct page *page) 37 + { 38 + return 0; 44 39 } 45 40 46 41 #endif /* CONFIG_PAGE_OWNER */
+5 -3
mm/page_alloc.c
··· 1948 1948 void split_page(struct page *page, unsigned int order) 1949 1949 { 1950 1950 int i; 1951 + gfp_t gfp_mask; 1951 1952 1952 1953 VM_BUG_ON_PAGE(PageCompound(page), page); 1953 1954 VM_BUG_ON_PAGE(!page_count(page), page); ··· 1962 1961 split_page(virt_to_page(page[0].shadow), order); 1963 1962 #endif 1964 1963 1965 - set_page_owner(page, 0, 0); 1964 + gfp_mask = get_page_owner_gfp(page); 1965 + set_page_owner(page, 0, gfp_mask); 1966 1966 for (i = 1; i < (1 << order); i++) { 1967 1967 set_page_refcounted(page + i); 1968 - set_page_owner(page + i, 0, 0); 1968 + set_page_owner(page + i, 0, gfp_mask); 1969 1969 } 1970 1970 } 1971 1971 EXPORT_SYMBOL_GPL(split_page); ··· 1996 1994 zone->free_area[order].nr_free--; 1997 1995 rmv_page_order(page); 1998 1996 1999 - set_page_owner(page, order, 0); 1997 + set_page_owner(page, order, __GFP_MOVABLE); 2000 1998 2001 1999 /* Set the pageblock if the isolated page is at least a pageblock */ 2002 2000 if (order >= pageblock_order - 1) {
+7
mm/page_owner.c
··· 76 76 __set_bit(PAGE_EXT_OWNER, &page_ext->flags); 77 77 } 78 78 79 + gfp_t __get_page_owner_gfp(struct page *page) 80 + { 81 + struct page_ext *page_ext = lookup_page_ext(page); 82 + 83 + return page_ext->gfp_mask; 84 + } 85 + 79 86 static ssize_t 80 87 print_page_owner(char __user *buf, size_t count, unsigned long pfn, 81 88 struct page *page, struct page_ext *page_ext)