diff options
Diffstat (limited to 'mm/page_isolation.c')
-rw-r--r-- | mm/page_isolation.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/mm/page_isolation.c b/mm/page_isolation.c index 6744235d2d0e..5f34a9053ce0 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c | |||
@@ -201,8 +201,20 @@ __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn) | |||
201 | } | 201 | } |
202 | page = pfn_to_page(pfn); | 202 | page = pfn_to_page(pfn); |
203 | if (PageBuddy(page)) { | 203 | if (PageBuddy(page)) { |
204 | if (get_freepage_migratetype(page) != MIGRATE_ISOLATE) | 204 | /* |
205 | break; | 205 | * If race between isolatation and allocation happens, |
206 | * some free pages could be in MIGRATE_MOVABLE list | ||
207 | * although pageblock's migratation type of the page | ||
208 | * is MIGRATE_ISOLATE. Catch it and move the page into | ||
209 | * MIGRATE_ISOLATE list. | ||
210 | */ | ||
211 | if (get_freepage_migratetype(page) != MIGRATE_ISOLATE) { | ||
212 | struct page *end_page; | ||
213 | |||
214 | end_page = page + (1 << page_order(page)) - 1; | ||
215 | move_freepages(page_zone(page), page, end_page, | ||
216 | MIGRATE_ISOLATE); | ||
217 | } | ||
206 | pfn += 1 << page_order(page); | 218 | pfn += 1 << page_order(page); |
207 | } | 219 | } |
208 | else if (page_count(page) == 0 && | 220 | else if (page_count(page) == 0 && |