aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoonsoo Kim <js1304@gmail.com>2015-07-17 19:24:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-07-17 19:39:54 -0400
commite2cfc91120fa01e3458167054af993fb83d7d0ec (patch)
tree22ffd1c08779eb7ff49c313202cfe03492397c29
parentf3a14ced32513d103a3ed0ce89c4e713fac01461 (diff)
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>
-rw-r--r--include/linux/page_owner.h13
-rw-r--r--mm/page_alloc.c8
-rw-r--r--mm/page_owner.c7
3 files changed, 25 insertions, 3 deletions
diff --git a/include/linux/page_owner.h b/include/linux/page_owner.h
index b48c3471c254..cacaabea8a09 100644
--- a/include/linux/page_owner.h
+++ b/include/linux/page_owner.h
@@ -8,6 +8,7 @@ extern struct page_ext_operations page_owner_ops;
8extern void __reset_page_owner(struct page *page, unsigned int order); 8extern void __reset_page_owner(struct page *page, unsigned int order);
9extern void __set_page_owner(struct page *page, 9extern void __set_page_owner(struct page *page,
10 unsigned int order, gfp_t gfp_mask); 10 unsigned int order, gfp_t gfp_mask);
11extern gfp_t __get_page_owner_gfp(struct page *page);
11 12
12static inline void reset_page_owner(struct page *page, unsigned int order) 13static inline void reset_page_owner(struct page *page, unsigned int order)
13{ 14{
@@ -25,6 +26,14 @@ static inline void set_page_owner(struct page *page,
25 26
26 __set_page_owner(page, order, gfp_mask); 27 __set_page_owner(page, order, gfp_mask);
27} 28}
29
30static inline gfp_t get_page_owner_gfp(struct page *page)
31{
32 if (likely(!page_owner_inited))
33 return 0;
34
35 return __get_page_owner_gfp(page);
36}
28#else 37#else
29static inline void reset_page_owner(struct page *page, unsigned int order) 38static inline void reset_page_owner(struct page *page, unsigned int order)
30{ 39{
@@ -33,6 +42,10 @@ static inline void set_page_owner(struct page *page,
33 unsigned int order, gfp_t gfp_mask) 42 unsigned int order, gfp_t gfp_mask)
34{ 43{
35} 44}
45static inline gfp_t get_page_owner_gfp(struct page *page)
46{
47 return 0;
48}
36 49
37#endif /* CONFIG_PAGE_OWNER */ 50#endif /* CONFIG_PAGE_OWNER */
38#endif /* __LINUX_PAGE_OWNER_H */ 51#endif /* __LINUX_PAGE_OWNER_H */
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index fbba675a0bd9..ef19f22b2b7d 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1948,6 +1948,7 @@ void free_hot_cold_page_list(struct list_head *list, bool cold)
1948void split_page(struct page *page, unsigned int order) 1948void split_page(struct page *page, unsigned int order)
1949{ 1949{
1950 int i; 1950 int i;
1951 gfp_t gfp_mask;
1951 1952
1952 VM_BUG_ON_PAGE(PageCompound(page), page); 1953 VM_BUG_ON_PAGE(PageCompound(page), page);
1953 VM_BUG_ON_PAGE(!page_count(page), page); 1954 VM_BUG_ON_PAGE(!page_count(page), page);
@@ -1961,10 +1962,11 @@ void split_page(struct page *page, unsigned int order)
1961 split_page(virt_to_page(page[0].shadow), order); 1962 split_page(virt_to_page(page[0].shadow), order);
1962#endif 1963#endif
1963 1964
1964 set_page_owner(page, 0, 0); 1965 gfp_mask = get_page_owner_gfp(page);
1966 set_page_owner(page, 0, gfp_mask);
1965 for (i = 1; i < (1 << order); i++) { 1967 for (i = 1; i < (1 << order); i++) {
1966 set_page_refcounted(page + i); 1968 set_page_refcounted(page + i);
1967 set_page_owner(page + i, 0, 0); 1969 set_page_owner(page + i, 0, gfp_mask);
1968 } 1970 }
1969} 1971}
1970EXPORT_SYMBOL_GPL(split_page); 1972EXPORT_SYMBOL_GPL(split_page);
@@ -1994,7 +1996,7 @@ int __isolate_free_page(struct page *page, unsigned int order)
1994 zone->free_area[order].nr_free--; 1996 zone->free_area[order].nr_free--;
1995 rmv_page_order(page); 1997 rmv_page_order(page);
1996 1998
1997 set_page_owner(page, order, 0); 1999 set_page_owner(page, order, __GFP_MOVABLE);
1998 2000
1999 /* Set the pageblock if the isolated page is at least a pageblock */ 2001 /* Set the pageblock if the isolated page is at least a pageblock */
2000 if (order >= pageblock_order - 1) { 2002 if (order >= pageblock_order - 1) {
diff --git a/mm/page_owner.c b/mm/page_owner.c
index bd5f842b56d2..983c3a10fa07 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -76,6 +76,13 @@ void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask)
76 __set_bit(PAGE_EXT_OWNER, &page_ext->flags); 76 __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
77} 77}
78 78
79gfp_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
79static ssize_t 86static ssize_t
80print_page_owner(char __user *buf, size_t count, unsigned long pfn, 87print_page_owner(char __user *buf, size_t count, unsigned long pfn,
81 struct page *page, struct page_ext *page_ext) 88 struct page *page, struct page_ext *page_ext)