aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/compaction.c140
1 files changed, 76 insertions, 64 deletions
diff --git a/mm/compaction.c b/mm/compaction.c
index 832c4183dccc..bdf6e13045ea 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -93,6 +93,27 @@ static inline bool compact_trylock_irqsave(spinlock_t *lock,
93 return compact_checklock_irqsave(lock, flags, false, cc); 93 return compact_checklock_irqsave(lock, flags, false, cc);
94} 94}
95 95
96/* Returns true if the page is within a block suitable for migration to */
97static bool suitable_migration_target(struct page *page)
98{
99 int migratetype = get_pageblock_migratetype(page);
100
101 /* Don't interfere with memory hot-remove or the min_free_kbytes blocks */
102 if (migratetype == MIGRATE_ISOLATE || migratetype == MIGRATE_RESERVE)
103 return false;
104
105 /* If the page is a large free page, then allow migration */
106 if (PageBuddy(page) && page_order(page) >= pageblock_order)
107 return true;
108
109 /* If the block is MIGRATE_MOVABLE or MIGRATE_CMA, allow migration */
110 if (migrate_async_suitable(migratetype))
111 return true;
112
113 /* Otherwise skip the block */
114 return false;
115}
116
96static void compact_capture_page(struct compact_control *cc) 117static void compact_capture_page(struct compact_control *cc)
97{ 118{
98 unsigned long flags; 119 unsigned long flags;
@@ -153,38 +174,56 @@ static void compact_capture_page(struct compact_control *cc)
153 * pages inside of the pageblock (even though it may still end up isolating 174 * pages inside of the pageblock (even though it may still end up isolating
154 * some pages). 175 * some pages).
155 */ 176 */
156static unsigned long isolate_freepages_block(unsigned long blockpfn, 177static unsigned long isolate_freepages_block(struct compact_control *cc,
178 unsigned long blockpfn,
157 unsigned long end_pfn, 179 unsigned long end_pfn,
158 struct list_head *freelist, 180 struct list_head *freelist,
159 bool strict) 181 bool strict)
160{ 182{
161 int nr_scanned = 0, total_isolated = 0; 183 int nr_scanned = 0, total_isolated = 0;
162 struct page *cursor; 184 struct page *cursor;
185 unsigned long nr_strict_required = end_pfn - blockpfn;
186 unsigned long flags;
187 bool locked = false;
163 188
164 cursor = pfn_to_page(blockpfn); 189 cursor = pfn_to_page(blockpfn);
165 190
166 /* Isolate free pages. This assumes the block is valid */ 191 /* Isolate free pages. */
167 for (; blockpfn < end_pfn; blockpfn++, cursor++) { 192 for (; blockpfn < end_pfn; blockpfn++, cursor++) {
168 int isolated, i; 193 int isolated, i;
169 struct page *page = cursor; 194 struct page *page = cursor;
170 195
171 if (!pfn_valid_within(blockpfn)) {
172 if (strict)
173 return 0;
174 continue;
175 }
176 nr_scanned++; 196 nr_scanned++;
197 if (!pfn_valid_within(blockpfn))
198 continue;
199 if (!PageBuddy(page))
200 continue;
201
202 /*
203 * The zone lock must be held to isolate freepages.
204 * Unfortunately this is a very coarse lock and can be
205 * heavily contended if there are parallel allocations
206 * or parallel compactions. For async compaction do not
207 * spin on the lock and we acquire the lock as late as
208 * possible.
209 */
210 locked = compact_checklock_irqsave(&cc->zone->lock, &flags,
211 locked, cc);
212 if (!locked)
213 break;
214
215 /* Recheck this is a suitable migration target under lock */
216 if (!strict && !suitable_migration_target(page))
217 break;
177 218
178 if (!PageBuddy(page)) { 219 /* Recheck this is a buddy page under lock */
179 if (strict) 220 if (!PageBuddy(page))
180 return 0;
181 continue; 221 continue;
182 }
183 222
184 /* Found a free page, break it into order-0 pages */ 223 /* Found a free page, break it into order-0 pages */
185 isolated = split_free_page(page); 224 isolated = split_free_page(page);
186 if (!isolated && strict) 225 if (!isolated && strict)
187 return 0; 226 break;
188 total_isolated += isolated; 227 total_isolated += isolated;
189 for (i = 0; i < isolated; i++) { 228 for (i = 0; i < isolated; i++) {
190 list_add(&page->lru, freelist); 229 list_add(&page->lru, freelist);
@@ -199,6 +238,18 @@ static unsigned long isolate_freepages_block(unsigned long blockpfn,
199 } 238 }
200 239
201 trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated); 240 trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated);
241
242 /*
243 * If strict isolation is requested by CMA then check that all the
244 * pages requested were isolated. If there were any failures, 0 is
245 * returned and CMA will fail.
246 */
247 if (strict && nr_strict_required != total_isolated)
248 total_isolated = 0;
249
250 if (locked)
251 spin_unlock_irqrestore(&cc->zone->lock, flags);
252
202 return total_isolated; 253 return total_isolated;
203} 254}
204 255
@@ -218,12 +269,17 @@ static unsigned long isolate_freepages_block(unsigned long blockpfn,
218unsigned long 269unsigned long
219isolate_freepages_range(unsigned long start_pfn, unsigned long end_pfn) 270isolate_freepages_range(unsigned long start_pfn, unsigned long end_pfn)
220{ 271{
221 unsigned long isolated, pfn, block_end_pfn, flags; 272 unsigned long isolated, pfn, block_end_pfn;
222 struct zone *zone = NULL; 273 struct zone *zone = NULL;
223 LIST_HEAD(freelist); 274 LIST_HEAD(freelist);
224 275
276 /* cc needed for isolate_freepages_block to acquire zone->lock */
277 struct compact_control cc = {
278 .sync = true,
279 };
280
225 if (pfn_valid(start_pfn)) 281 if (pfn_valid(start_pfn))
226 zone = page_zone(pfn_to_page(start_pfn)); 282 cc.zone = zone = page_zone(pfn_to_page(start_pfn));
227 283
228 for (pfn = start_pfn; pfn < end_pfn; pfn += isolated) { 284 for (pfn = start_pfn; pfn < end_pfn; pfn += isolated) {
229 if (!pfn_valid(pfn) || zone != page_zone(pfn_to_page(pfn))) 285 if (!pfn_valid(pfn) || zone != page_zone(pfn_to_page(pfn)))
@@ -236,10 +292,8 @@ isolate_freepages_range(unsigned long start_pfn, unsigned long end_pfn)
236 block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); 292 block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
237 block_end_pfn = min(block_end_pfn, end_pfn); 293 block_end_pfn = min(block_end_pfn, end_pfn);
238 294
239 spin_lock_irqsave(&zone->lock, flags); 295 isolated = isolate_freepages_block(&cc, pfn, block_end_pfn,
240 isolated = isolate_freepages_block(pfn, block_end_pfn,
241 &freelist, true); 296 &freelist, true);
242 spin_unlock_irqrestore(&zone->lock, flags);
243 297
244 /* 298 /*
245 * In strict mode, isolate_freepages_block() returns 0 if 299 * In strict mode, isolate_freepages_block() returns 0 if
@@ -483,29 +537,6 @@ next_pageblock:
483 537
484#endif /* CONFIG_COMPACTION || CONFIG_CMA */ 538#endif /* CONFIG_COMPACTION || CONFIG_CMA */
485#ifdef CONFIG_COMPACTION 539#ifdef CONFIG_COMPACTION
486
487/* Returns true if the page is within a block suitable for migration to */
488static bool suitable_migration_target(struct page *page)
489{
490
491 int migratetype = get_pageblock_migratetype(page);
492
493 /* Don't interfere with memory hot-remove or the min_free_kbytes blocks */
494 if (migratetype == MIGRATE_ISOLATE || migratetype == MIGRATE_RESERVE)
495 return false;
496
497 /* If the page is a large free page, then allow migration */
498 if (PageBuddy(page) && page_order(page) >= pageblock_order)
499 return true;
500
501 /* If the block is MIGRATE_MOVABLE or MIGRATE_CMA, allow migration */
502 if (migrate_async_suitable(migratetype))
503 return true;
504
505 /* Otherwise skip the block */
506 return false;
507}
508
509/* 540/*
510 * Returns the start pfn of the last page block in a zone. This is the starting 541 * Returns the start pfn of the last page block in a zone. This is the starting
511 * point for full compaction of a zone. Compaction searches for free pages from 542 * point for full compaction of a zone. Compaction searches for free pages from
@@ -529,7 +560,6 @@ static void isolate_freepages(struct zone *zone,
529{ 560{
530 struct page *page; 561 struct page *page;
531 unsigned long high_pfn, low_pfn, pfn, zone_end_pfn, end_pfn; 562 unsigned long high_pfn, low_pfn, pfn, zone_end_pfn, end_pfn;
532 unsigned long flags;
533 int nr_freepages = cc->nr_freepages; 563 int nr_freepages = cc->nr_freepages;
534 struct list_head *freelist = &cc->freepages; 564 struct list_head *freelist = &cc->freepages;
535 565
@@ -577,30 +607,12 @@ static void isolate_freepages(struct zone *zone,
577 if (!suitable_migration_target(page)) 607 if (!suitable_migration_target(page))
578 continue; 608 continue;
579 609
580 /* 610 /* Found a block suitable for isolating free pages from */
581 * Found a block suitable for isolating free pages from. Now
582 * we disabled interrupts, double check things are ok and
583 * isolate the pages. This is to minimise the time IRQs
584 * are disabled
585 */
586 isolated = 0; 611 isolated = 0;
587 612 end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
588 /* 613 isolated = isolate_freepages_block(cc, pfn, end_pfn,
589 * The zone lock must be held to isolate freepages. This 614 freelist, false);
590 * unfortunately this is a very coarse lock and can be 615 nr_freepages += isolated;
591 * heavily contended if there are parallel allocations
592 * or parallel compactions. For async compaction do not
593 * spin on the lock
594 */
595 if (!compact_trylock_irqsave(&zone->lock, &flags, cc))
596 break;
597 if (suitable_migration_target(page)) {
598 end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
599 isolated = isolate_freepages_block(pfn, end_pfn,
600 freelist, false);
601 nr_freepages += isolated;
602 }
603 spin_unlock_irqrestore(&zone->lock, flags);
604 616
605 /* 617 /*
606 * Record the highest PFN we isolated pages from. When next 618 * Record the highest PFN we isolated pages from. When next