summaryrefslogtreecommitdiffstats
path: root/mm/migrate.c
diff options
context:
space:
mode:
authorMinchan Kim <minchan@kernel.org>2016-07-26 18:23:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-26 19:19:19 -0400
commitbda807d4445414e8e77da704f116bb0880fe0c76 (patch)
tree4e3b462d23437d7521081758c2005ae0025978f7 /mm/migrate.c
parentc6c919eb90e021fbcfcbfa9dd3d55930cdbb67f9 (diff)
mm: migrate: support non-lru movable page migration
We have allowed migration for only LRU pages until now and it was enough to make high-order pages. But recently, embedded system(e.g., webOS, android) uses lots of non-movable pages(e.g., zram, GPU memory) so we have seen several reports about troubles of small high-order allocation. For fixing the problem, there were several efforts (e,g,. enhance compaction algorithm, SLUB fallback to 0-order page, reserved memory, vmalloc and so on) but if there are lots of non-movable pages in system, their solutions are void in the long run. So, this patch is to support facility to change non-movable pages with movable. For the feature, this patch introduces functions related to migration to address_space_operations as well as some page flags. If a driver want to make own pages movable, it should define three functions which are function pointers of struct address_space_operations. 1. bool (*isolate_page) (struct page *page, isolate_mode_t mode); What VM expects on isolate_page function of driver is to return *true* if driver isolates page successfully. On returing true, VM marks the page as PG_isolated so concurrent isolation in several CPUs skip the page for isolation. If a driver cannot isolate the page, it should return *false*. Once page is successfully isolated, VM uses page.lru fields so driver shouldn't expect to preserve values in that fields. 2. int (*migratepage) (struct address_space *mapping, struct page *newpage, struct page *oldpage, enum migrate_mode); After isolation, VM calls migratepage of driver with isolated page. The function of migratepage is to move content of the old page to new page and set up fields of struct page newpage. Keep in mind that you should indicate to the VM the oldpage is no longer movable via __ClearPageMovable() under page_lock if you migrated the oldpage successfully and returns 0. If driver cannot migrate the page at the moment, driver can return -EAGAIN. On -EAGAIN, VM will retry page migration in a short time because VM interprets -EAGAIN as "temporal migration failure". On returning any error except -EAGAIN, VM will give up the page migration without retrying in this time. Driver shouldn't touch page.lru field VM using in the functions. 3. void (*putback_page)(struct page *); If migration fails on isolated page, VM should return the isolated page to the driver so VM calls driver's putback_page with migration failed page. In this function, driver should put the isolated page back to the own data structure. 4. non-lru movable page flags There are two page flags for supporting non-lru movable page. * PG_movable Driver should use the below function to make page movable under page_lock. void __SetPageMovable(struct page *page, struct address_space *mapping) It needs argument of address_space for registering migration family functions which will be called by VM. Exactly speaking, PG_movable is not a real flag of struct page. Rather than, VM reuses page->mapping's lower bits to represent it. #define PAGE_MAPPING_MOVABLE 0x2 page->mapping = page->mapping | PAGE_MAPPING_MOVABLE; so driver shouldn't access page->mapping directly. Instead, driver should use page_mapping which mask off the low two bits of page->mapping so it can get right struct address_space. For testing of non-lru movable page, VM supports __PageMovable function. However, it doesn't guarantee to identify non-lru movable page because page->mapping field is unified with other variables in struct page. As well, if driver releases the page after isolation by VM, page->mapping doesn't have stable value although it has PAGE_MAPPING_MOVABLE (Look at __ClearPageMovable). But __PageMovable is cheap to catch whether page is LRU or non-lru movable once the page has been isolated. Because LRU pages never can have PAGE_MAPPING_MOVABLE in page->mapping. It is also good for just peeking to test non-lru movable pages before more expensive checking with lock_page in pfn scanning to select victim. For guaranteeing non-lru movable page, VM provides PageMovable function. Unlike __PageMovable, PageMovable functions validates page->mapping and mapping->a_ops->isolate_page under lock_page. The lock_page prevents sudden destroying of page->mapping. Driver using __SetPageMovable should clear the flag via __ClearMovablePage under page_lock before the releasing the page. * PG_isolated To prevent concurrent isolation among several CPUs, VM marks isolated page as PG_isolated under lock_page. So if a CPU encounters PG_isolated non-lru movable page, it can skip it. Driver doesn't need to manipulate the flag because VM will set/clear it automatically. Keep in mind that if driver sees PG_isolated page, it means the page have been isolated by VM so it shouldn't touch page.lru field. PG_isolated is alias with PG_reclaim flag so driver shouldn't use the flag for own purpose. [opensource.ganesh@gmail.com: mm/compaction: remove local variable is_lru] Link: http://lkml.kernel.org/r/20160618014841.GA7422@leo-test Link: http://lkml.kernel.org/r/1464736881-24886-3-git-send-email-minchan@kernel.org Signed-off-by: Gioh Kim <gi-oh.kim@profitbricks.com> Signed-off-by: Minchan Kim <minchan@kernel.org> Signed-off-by: Ganesh Mahendran <opensource.ganesh@gmail.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Cc: Rik van Riel <riel@redhat.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Hugh Dickins <hughd@google.com> Cc: Rafael Aquini <aquini@redhat.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: John Einar Reitan <john.reitan@foss.arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/migrate.c')
-rw-r--r--mm/migrate.c192
1 files changed, 174 insertions, 18 deletions
diff --git a/mm/migrate.c b/mm/migrate.c
index c74412b381ff..8119fdc563f8 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -31,6 +31,7 @@
31#include <linux/vmalloc.h> 31#include <linux/vmalloc.h>
32#include <linux/security.h> 32#include <linux/security.h>
33#include <linux/backing-dev.h> 33#include <linux/backing-dev.h>
34#include <linux/compaction.h>
34#include <linux/syscalls.h> 35#include <linux/syscalls.h>
35#include <linux/hugetlb.h> 36#include <linux/hugetlb.h>
36#include <linux/hugetlb_cgroup.h> 37#include <linux/hugetlb_cgroup.h>
@@ -73,6 +74,81 @@ int migrate_prep_local(void)
73 return 0; 74 return 0;
74} 75}
75 76
77bool isolate_movable_page(struct page *page, isolate_mode_t mode)
78{
79 struct address_space *mapping;
80
81 /*
82 * Avoid burning cycles with pages that are yet under __free_pages(),
83 * or just got freed under us.
84 *
85 * In case we 'win' a race for a movable page being freed under us and
86 * raise its refcount preventing __free_pages() from doing its job
87 * the put_page() at the end of this block will take care of
88 * release this page, thus avoiding a nasty leakage.
89 */
90 if (unlikely(!get_page_unless_zero(page)))
91 goto out;
92
93 /*
94 * Check PageMovable before holding a PG_lock because page's owner
95 * assumes anybody doesn't touch PG_lock of newly allocated page
96 * so unconditionally grapping the lock ruins page's owner side.
97 */
98 if (unlikely(!__PageMovable(page)))
99 goto out_putpage;
100 /*
101 * As movable pages are not isolated from LRU lists, concurrent
102 * compaction threads can race against page migration functions
103 * as well as race against the releasing a page.
104 *
105 * In order to avoid having an already isolated movable page
106 * being (wrongly) re-isolated while it is under migration,
107 * or to avoid attempting to isolate pages being released,
108 * lets be sure we have the page lock
109 * before proceeding with the movable page isolation steps.
110 */
111 if (unlikely(!trylock_page(page)))
112 goto out_putpage;
113
114 if (!PageMovable(page) || PageIsolated(page))
115 goto out_no_isolated;
116
117 mapping = page_mapping(page);
118 VM_BUG_ON_PAGE(!mapping, page);
119
120 if (!mapping->a_ops->isolate_page(page, mode))
121 goto out_no_isolated;
122
123 /* Driver shouldn't use PG_isolated bit of page->flags */
124 WARN_ON_ONCE(PageIsolated(page));
125 __SetPageIsolated(page);
126 unlock_page(page);
127
128 return true;
129
130out_no_isolated:
131 unlock_page(page);
132out_putpage:
133 put_page(page);
134out:
135 return false;
136}
137
138/* It should be called on page which is PG_movable */
139void putback_movable_page(struct page *page)
140{
141 struct address_space *mapping;
142
143 VM_BUG_ON_PAGE(!PageLocked(page), page);
144 VM_BUG_ON_PAGE(!PageMovable(page), page);
145 VM_BUG_ON_PAGE(!PageIsolated(page), page);
146
147 mapping = page_mapping(page);
148 mapping->a_ops->putback_page(page);
149 __ClearPageIsolated(page);
150}
151
76/* 152/*
77 * Put previously isolated pages back onto the appropriate lists 153 * Put previously isolated pages back onto the appropriate lists
78 * from where they were once taken off for compaction/migration. 154 * from where they were once taken off for compaction/migration.
@@ -94,10 +170,25 @@ void putback_movable_pages(struct list_head *l)
94 list_del(&page->lru); 170 list_del(&page->lru);
95 dec_zone_page_state(page, NR_ISOLATED_ANON + 171 dec_zone_page_state(page, NR_ISOLATED_ANON +
96 page_is_file_cache(page)); 172 page_is_file_cache(page));
97 if (unlikely(isolated_balloon_page(page))) 173 if (unlikely(isolated_balloon_page(page))) {
98 balloon_page_putback(page); 174 balloon_page_putback(page);
99 else 175 /*
176 * We isolated non-lru movable page so here we can use
177 * __PageMovable because LRU page's mapping cannot have
178 * PAGE_MAPPING_MOVABLE.
179 */
180 } else if (unlikely(__PageMovable(page))) {
181 VM_BUG_ON_PAGE(!PageIsolated(page), page);
182 lock_page(page);
183 if (PageMovable(page))
184 putback_movable_page(page);
185 else
186 __ClearPageIsolated(page);
187 unlock_page(page);
188 put_page(page);
189 } else {
100 putback_lru_page(page); 190 putback_lru_page(page);
191 }
101 } 192 }
102} 193}
103 194
@@ -594,7 +685,7 @@ EXPORT_SYMBOL(migrate_page_copy);
594 ***********************************************************/ 685 ***********************************************************/
595 686
596/* 687/*
597 * Common logic to directly migrate a single page suitable for 688 * Common logic to directly migrate a single LRU page suitable for
598 * pages that do not use PagePrivate/PagePrivate2. 689 * pages that do not use PagePrivate/PagePrivate2.
599 * 690 *
600 * Pages are locked upon entry and exit. 691 * Pages are locked upon entry and exit.
@@ -757,33 +848,72 @@ static int move_to_new_page(struct page *newpage, struct page *page,
757 enum migrate_mode mode) 848 enum migrate_mode mode)
758{ 849{
759 struct address_space *mapping; 850 struct address_space *mapping;
760 int rc; 851 int rc = -EAGAIN;
852 bool is_lru = !__PageMovable(page);
761 853
762 VM_BUG_ON_PAGE(!PageLocked(page), page); 854 VM_BUG_ON_PAGE(!PageLocked(page), page);
763 VM_BUG_ON_PAGE(!PageLocked(newpage), newpage); 855 VM_BUG_ON_PAGE(!PageLocked(newpage), newpage);
764 856
765 mapping = page_mapping(page); 857 mapping = page_mapping(page);
766 if (!mapping) 858
767 rc = migrate_page(mapping, newpage, page, mode); 859 if (likely(is_lru)) {
768 else if (mapping->a_ops->migratepage) 860 if (!mapping)
861 rc = migrate_page(mapping, newpage, page, mode);
862 else if (mapping->a_ops->migratepage)
863 /*
864 * Most pages have a mapping and most filesystems
865 * provide a migratepage callback. Anonymous pages
866 * are part of swap space which also has its own
867 * migratepage callback. This is the most common path
868 * for page migration.
869 */
870 rc = mapping->a_ops->migratepage(mapping, newpage,
871 page, mode);
872 else
873 rc = fallback_migrate_page(mapping, newpage,
874 page, mode);
875 } else {
769 /* 876 /*
770 * Most pages have a mapping and most filesystems provide a 877 * In case of non-lru page, it could be released after
771 * migratepage callback. Anonymous pages are part of swap 878 * isolation step. In that case, we shouldn't try migration.
772 * space which also has its own migratepage callback. This
773 * is the most common path for page migration.
774 */ 879 */
775 rc = mapping->a_ops->migratepage(mapping, newpage, page, mode); 880 VM_BUG_ON_PAGE(!PageIsolated(page), page);
776 else 881 if (!PageMovable(page)) {
777 rc = fallback_migrate_page(mapping, newpage, page, mode); 882 rc = MIGRATEPAGE_SUCCESS;
883 __ClearPageIsolated(page);
884 goto out;
885 }
886
887 rc = mapping->a_ops->migratepage(mapping, newpage,
888 page, mode);
889 WARN_ON_ONCE(rc == MIGRATEPAGE_SUCCESS &&
890 !PageIsolated(page));
891 }
778 892
779 /* 893 /*
780 * When successful, old pagecache page->mapping must be cleared before 894 * When successful, old pagecache page->mapping must be cleared before
781 * page is freed; but stats require that PageAnon be left as PageAnon. 895 * page is freed; but stats require that PageAnon be left as PageAnon.
782 */ 896 */
783 if (rc == MIGRATEPAGE_SUCCESS) { 897 if (rc == MIGRATEPAGE_SUCCESS) {
784 if (!PageAnon(page)) 898 if (__PageMovable(page)) {
899 VM_BUG_ON_PAGE(!PageIsolated(page), page);
900
901 /*
902 * We clear PG_movable under page_lock so any compactor
903 * cannot try to migrate this page.
904 */
905 __ClearPageIsolated(page);
906 }
907
908 /*
909 * Anonymous and movable page->mapping will be cleard by
910 * free_pages_prepare so don't reset it here for keeping
911 * the type to work PageAnon, for example.
912 */
913 if (!PageMappingFlags(page))
785 page->mapping = NULL; 914 page->mapping = NULL;
786 } 915 }
916out:
787 return rc; 917 return rc;
788} 918}
789 919
@@ -793,6 +923,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
793 int rc = -EAGAIN; 923 int rc = -EAGAIN;
794 int page_was_mapped = 0; 924 int page_was_mapped = 0;
795 struct anon_vma *anon_vma = NULL; 925 struct anon_vma *anon_vma = NULL;
926 bool is_lru = !__PageMovable(page);
796 927
797 if (!trylock_page(page)) { 928 if (!trylock_page(page)) {
798 if (!force || mode == MIGRATE_ASYNC) 929 if (!force || mode == MIGRATE_ASYNC)
@@ -873,6 +1004,11 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
873 goto out_unlock_both; 1004 goto out_unlock_both;
874 } 1005 }
875 1006
1007 if (unlikely(!is_lru)) {
1008 rc = move_to_new_page(newpage, page, mode);
1009 goto out_unlock_both;
1010 }
1011
876 /* 1012 /*
877 * Corner case handling: 1013 * Corner case handling:
878 * 1. When a new swap-cache page is read into, it is added to the LRU 1014 * 1. When a new swap-cache page is read into, it is added to the LRU
@@ -922,7 +1058,8 @@ out:
922 * list in here. 1058 * list in here.
923 */ 1059 */
924 if (rc == MIGRATEPAGE_SUCCESS) { 1060 if (rc == MIGRATEPAGE_SUCCESS) {
925 if (unlikely(__is_movable_balloon_page(newpage))) 1061 if (unlikely(__is_movable_balloon_page(newpage) ||
1062 __PageMovable(newpage)))
926 put_page(newpage); 1063 put_page(newpage);
927 else 1064 else
928 putback_lru_page(newpage); 1065 putback_lru_page(newpage);
@@ -963,6 +1100,12 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page,
963 /* page was freed from under us. So we are done. */ 1100 /* page was freed from under us. So we are done. */
964 ClearPageActive(page); 1101 ClearPageActive(page);
965 ClearPageUnevictable(page); 1102 ClearPageUnevictable(page);
1103 if (unlikely(__PageMovable(page))) {
1104 lock_page(page);
1105 if (!PageMovable(page))
1106 __ClearPageIsolated(page);
1107 unlock_page(page);
1108 }
966 if (put_new_page) 1109 if (put_new_page)
967 put_new_page(newpage, private); 1110 put_new_page(newpage, private);
968 else 1111 else
@@ -1012,8 +1155,21 @@ out:
1012 num_poisoned_pages_inc(); 1155 num_poisoned_pages_inc();
1013 } 1156 }
1014 } else { 1157 } else {
1015 if (rc != -EAGAIN) 1158 if (rc != -EAGAIN) {
1016 putback_lru_page(page); 1159 if (likely(!__PageMovable(page))) {
1160 putback_lru_page(page);
1161 goto put_new;
1162 }
1163
1164 lock_page(page);
1165 if (PageMovable(page))
1166 putback_movable_page(page);
1167 else
1168 __ClearPageIsolated(page);
1169 unlock_page(page);
1170 put_page(page);
1171 }
1172put_new:
1017 if (put_new_page) 1173 if (put_new_page)
1018 put_new_page(newpage, private); 1174 put_new_page(newpage, private);
1019 else 1175 else