summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/page-isolation.h2
-rw-r--r--mm/page_alloc.c12
-rw-r--r--mm/page_isolation.c10
3 files changed, 17 insertions, 7 deletions
diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h
index 05a04e603686..cdad58bbfd8b 100644
--- a/include/linux/page-isolation.h
+++ b/include/linux/page-isolation.h
@@ -31,7 +31,7 @@ static inline bool is_migrate_isolate(int migratetype)
31#endif 31#endif
32 32
33bool has_unmovable_pages(struct zone *zone, struct page *page, int count, 33bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
34 bool skip_hwpoisoned_pages); 34 int migratetype, bool skip_hwpoisoned_pages);
35void set_pageblock_migratetype(struct page *page, int migratetype); 35void set_pageblock_migratetype(struct page *page, int migratetype);
36int move_freepages_block(struct zone *zone, struct page *page, 36int move_freepages_block(struct zone *zone, struct page *page,
37 int migratetype, int *num_movable); 37 int migratetype, int *num_movable);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index e6d4234e0d1a..755f35f4bc8b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -7353,6 +7353,7 @@ void *__init alloc_large_system_hash(const char *tablename,
7353 * race condition. So you can't expect this function should be exact. 7353 * race condition. So you can't expect this function should be exact.
7354 */ 7354 */
7355bool has_unmovable_pages(struct zone *zone, struct page *page, int count, 7355bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
7356 int migratetype,
7356 bool skip_hwpoisoned_pages) 7357 bool skip_hwpoisoned_pages)
7357{ 7358{
7358 unsigned long pfn, iter, found; 7359 unsigned long pfn, iter, found;
@@ -7364,6 +7365,15 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
7364 if (zone_idx(zone) == ZONE_MOVABLE) 7365 if (zone_idx(zone) == ZONE_MOVABLE)
7365 return false; 7366 return false;
7366 7367
7368 /*
7369 * CMA allocations (alloc_contig_range) really need to mark isolate
7370 * CMA pageblocks even when they are not movable in fact so consider
7371 * them movable here.
7372 */
7373 if (is_migrate_cma(migratetype) &&
7374 is_migrate_cma(get_pageblock_migratetype(page)))
7375 return false;
7376
7367 pfn = page_to_pfn(page); 7377 pfn = page_to_pfn(page);
7368 for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) { 7378 for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) {
7369 unsigned long check = pfn + iter; 7379 unsigned long check = pfn + iter;
@@ -7446,7 +7456,7 @@ bool is_pageblock_removable_nolock(struct page *page)
7446 if (!zone_spans_pfn(zone, pfn)) 7456 if (!zone_spans_pfn(zone, pfn))
7447 return false; 7457 return false;
7448 7458
7449 return !has_unmovable_pages(zone, page, 0, true); 7459 return !has_unmovable_pages(zone, page, 0, MIGRATE_MOVABLE, true);
7450} 7460}
7451 7461
7452#if (defined(CONFIG_MEMORY_ISOLATION) && defined(CONFIG_COMPACTION)) || defined(CONFIG_CMA) 7462#if (defined(CONFIG_MEMORY_ISOLATION) && defined(CONFIG_COMPACTION)) || defined(CONFIG_CMA)
diff --git a/mm/page_isolation.c b/mm/page_isolation.c
index 44f213935bf6..165ed8117bd1 100644
--- a/mm/page_isolation.c
+++ b/mm/page_isolation.c
@@ -15,7 +15,7 @@
15#define CREATE_TRACE_POINTS 15#define CREATE_TRACE_POINTS
16#include <trace/events/page_isolation.h> 16#include <trace/events/page_isolation.h>
17 17
18static int set_migratetype_isolate(struct page *page, 18static int set_migratetype_isolate(struct page *page, int migratetype,
19 bool skip_hwpoisoned_pages) 19 bool skip_hwpoisoned_pages)
20{ 20{
21 struct zone *zone; 21 struct zone *zone;
@@ -52,7 +52,7 @@ static int set_migratetype_isolate(struct page *page,
52 * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. 52 * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
53 * We just check MOVABLE pages. 53 * We just check MOVABLE pages.
54 */ 54 */
55 if (!has_unmovable_pages(zone, page, arg.pages_found, 55 if (!has_unmovable_pages(zone, page, arg.pages_found, migratetype,
56 skip_hwpoisoned_pages)) 56 skip_hwpoisoned_pages))
57 ret = 0; 57 ret = 0;
58 58
@@ -64,14 +64,14 @@ static int set_migratetype_isolate(struct page *page,
64out: 64out:
65 if (!ret) { 65 if (!ret) {
66 unsigned long nr_pages; 66 unsigned long nr_pages;
67 int migratetype = get_pageblock_migratetype(page); 67 int mt = get_pageblock_migratetype(page);
68 68
69 set_pageblock_migratetype(page, MIGRATE_ISOLATE); 69 set_pageblock_migratetype(page, MIGRATE_ISOLATE);
70 zone->nr_isolate_pageblock++; 70 zone->nr_isolate_pageblock++;
71 nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE, 71 nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE,
72 NULL); 72 NULL);
73 73
74 __mod_zone_freepage_state(zone, -nr_pages, migratetype); 74 __mod_zone_freepage_state(zone, -nr_pages, mt);
75 } 75 }
76 76
77 spin_unlock_irqrestore(&zone->lock, flags); 77 spin_unlock_irqrestore(&zone->lock, flags);
@@ -183,7 +183,7 @@ int start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
183 pfn += pageblock_nr_pages) { 183 pfn += pageblock_nr_pages) {
184 page = __first_valid_page(pfn, pageblock_nr_pages); 184 page = __first_valid_page(pfn, pageblock_nr_pages);
185 if (page && 185 if (page &&
186 set_migratetype_isolate(page, skip_hwpoisoned_pages)) { 186 set_migratetype_isolate(page, migratetype, skip_hwpoisoned_pages)) {
187 undo_pfn = pfn; 187 undo_pfn = pfn;
188 goto undo; 188 goto undo;
189 } 189 }