diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/debug.c | 11 | ||||
-rw-r--r-- | mm/migrate.c | 10 | ||||
-rw-r--r-- | mm/page_owner.c | 17 |
3 files changed, 35 insertions, 3 deletions
diff --git a/mm/debug.c b/mm/debug.c index 231e1452a912..78dc54877075 100644 --- a/mm/debug.c +++ b/mm/debug.c | |||
@@ -10,9 +10,20 @@ | |||
10 | #include <linux/trace_events.h> | 10 | #include <linux/trace_events.h> |
11 | #include <linux/memcontrol.h> | 11 | #include <linux/memcontrol.h> |
12 | #include <trace/events/mmflags.h> | 12 | #include <trace/events/mmflags.h> |
13 | #include <linux/migrate.h> | ||
13 | 14 | ||
14 | #include "internal.h" | 15 | #include "internal.h" |
15 | 16 | ||
17 | char *migrate_reason_names[MR_TYPES] = { | ||
18 | "compaction", | ||
19 | "memory_failure", | ||
20 | "memory_hotplug", | ||
21 | "syscall_or_cpuset", | ||
22 | "mempolicy_mbind", | ||
23 | "numa_misplaced", | ||
24 | "cma", | ||
25 | }; | ||
26 | |||
16 | const struct trace_print_flags pageflag_names[] = { | 27 | const struct trace_print_flags pageflag_names[] = { |
17 | __def_pageflag_names, | 28 | __def_pageflag_names, |
18 | {0, NULL} | 29 | {0, NULL} |
diff --git a/mm/migrate.c b/mm/migrate.c index 8133805431ba..432ecd0172cd 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -955,8 +955,10 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page, | |||
955 | } | 955 | } |
956 | 956 | ||
957 | rc = __unmap_and_move(page, newpage, force, mode); | 957 | rc = __unmap_and_move(page, newpage, force, mode); |
958 | if (rc == MIGRATEPAGE_SUCCESS) | 958 | if (rc == MIGRATEPAGE_SUCCESS) { |
959 | put_new_page = NULL; | 959 | put_new_page = NULL; |
960 | set_page_owner_migrate_reason(newpage, reason); | ||
961 | } | ||
960 | 962 | ||
961 | out: | 963 | out: |
962 | if (rc != -EAGAIN) { | 964 | if (rc != -EAGAIN) { |
@@ -1021,7 +1023,7 @@ out: | |||
1021 | static int unmap_and_move_huge_page(new_page_t get_new_page, | 1023 | static int unmap_and_move_huge_page(new_page_t get_new_page, |
1022 | free_page_t put_new_page, unsigned long private, | 1024 | free_page_t put_new_page, unsigned long private, |
1023 | struct page *hpage, int force, | 1025 | struct page *hpage, int force, |
1024 | enum migrate_mode mode) | 1026 | enum migrate_mode mode, int reason) |
1025 | { | 1027 | { |
1026 | int rc = -EAGAIN; | 1028 | int rc = -EAGAIN; |
1027 | int *result = NULL; | 1029 | int *result = NULL; |
@@ -1079,6 +1081,7 @@ put_anon: | |||
1079 | if (rc == MIGRATEPAGE_SUCCESS) { | 1081 | if (rc == MIGRATEPAGE_SUCCESS) { |
1080 | hugetlb_cgroup_migrate(hpage, new_hpage); | 1082 | hugetlb_cgroup_migrate(hpage, new_hpage); |
1081 | put_new_page = NULL; | 1083 | put_new_page = NULL; |
1084 | set_page_owner_migrate_reason(new_hpage, reason); | ||
1082 | } | 1085 | } |
1083 | 1086 | ||
1084 | unlock_page(hpage); | 1087 | unlock_page(hpage); |
@@ -1151,7 +1154,7 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page, | |||
1151 | if (PageHuge(page)) | 1154 | if (PageHuge(page)) |
1152 | rc = unmap_and_move_huge_page(get_new_page, | 1155 | rc = unmap_and_move_huge_page(get_new_page, |
1153 | put_new_page, private, page, | 1156 | put_new_page, private, page, |
1154 | pass > 2, mode); | 1157 | pass > 2, mode, reason); |
1155 | else | 1158 | else |
1156 | rc = unmap_and_move(get_new_page, put_new_page, | 1159 | rc = unmap_and_move(get_new_page, put_new_page, |
1157 | private, page, pass > 2, mode, | 1160 | private, page, pass > 2, mode, |
@@ -1842,6 +1845,7 @@ fail_putback: | |||
1842 | set_page_memcg(new_page, page_memcg(page)); | 1845 | set_page_memcg(new_page, page_memcg(page)); |
1843 | set_page_memcg(page, NULL); | 1846 | set_page_memcg(page, NULL); |
1844 | page_remove_rmap(page, true); | 1847 | page_remove_rmap(page, true); |
1848 | set_page_owner_migrate_reason(new_page, MR_NUMA_MISPLACED); | ||
1845 | 1849 | ||
1846 | spin_unlock(ptl); | 1850 | spin_unlock(ptl); |
1847 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); | 1851 | mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end); |
diff --git a/mm/page_owner.c b/mm/page_owner.c index 774b55623212..a57068cfe52f 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/stacktrace.h> | 6 | #include <linux/stacktrace.h> |
7 | #include <linux/page_owner.h> | 7 | #include <linux/page_owner.h> |
8 | #include <linux/jump_label.h> | 8 | #include <linux/jump_label.h> |
9 | #include <linux/migrate.h> | ||
9 | #include "internal.h" | 10 | #include "internal.h" |
10 | 11 | ||
11 | static bool page_owner_disabled = true; | 12 | static bool page_owner_disabled = true; |
@@ -73,10 +74,18 @@ void __set_page_owner(struct page *page, unsigned int order, gfp_t gfp_mask) | |||
73 | page_ext->order = order; | 74 | page_ext->order = order; |
74 | page_ext->gfp_mask = gfp_mask; | 75 | page_ext->gfp_mask = gfp_mask; |
75 | page_ext->nr_entries = trace.nr_entries; | 76 | page_ext->nr_entries = trace.nr_entries; |
77 | page_ext->last_migrate_reason = -1; | ||
76 | 78 | ||
77 | __set_bit(PAGE_EXT_OWNER, &page_ext->flags); | 79 | __set_bit(PAGE_EXT_OWNER, &page_ext->flags); |
78 | } | 80 | } |
79 | 81 | ||
82 | void __set_page_owner_migrate_reason(struct page *page, int reason) | ||
83 | { | ||
84 | struct page_ext *page_ext = lookup_page_ext(page); | ||
85 | |||
86 | page_ext->last_migrate_reason = reason; | ||
87 | } | ||
88 | |||
80 | gfp_t __get_page_owner_gfp(struct page *page) | 89 | gfp_t __get_page_owner_gfp(struct page *page) |
81 | { | 90 | { |
82 | struct page_ext *page_ext = lookup_page_ext(page); | 91 | struct page_ext *page_ext = lookup_page_ext(page); |
@@ -151,6 +160,14 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn, | |||
151 | if (ret >= count) | 160 | if (ret >= count) |
152 | goto err; | 161 | goto err; |
153 | 162 | ||
163 | if (page_ext->last_migrate_reason != -1) { | ||
164 | ret += snprintf(kbuf + ret, count - ret, | ||
165 | "Page has been migrated, last migrate reason: %s\n", | ||
166 | migrate_reason_names[page_ext->last_migrate_reason]); | ||
167 | if (ret >= count) | ||
168 | goto err; | ||
169 | } | ||
170 | |||
154 | ret += snprintf(kbuf + ret, count - ret, "\n"); | 171 | ret += snprintf(kbuf + ret, count - ret, "\n"); |
155 | if (ret >= count) | 172 | if (ret >= count) |
156 | goto err; | 173 | goto err; |