aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/compaction.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/mm/compaction.c b/mm/compaction.c
index 9b94eaf537e4..6cc604bd5649 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -251,11 +251,18 @@ static bool too_many_isolated(struct zone *zone)
251 return isolated > (inactive + active) / 2; 251 return isolated > (inactive + active) / 2;
252} 252}
253 253
254/* possible outcome of isolate_migratepages */
255typedef enum {
256 ISOLATE_ABORT, /* Abort compaction now */
257 ISOLATE_NONE, /* No pages isolated, continue scanning */
258 ISOLATE_SUCCESS, /* Pages isolated, migrate */
259} isolate_migrate_t;
260
254/* 261/*
255 * Isolate all pages that can be migrated from the block pointed to by 262 * Isolate all pages that can be migrated from the block pointed to by
256 * the migrate scanner within compact_control. 263 * the migrate scanner within compact_control.
257 */ 264 */
258static unsigned long isolate_migratepages(struct zone *zone, 265static isolate_migrate_t isolate_migratepages(struct zone *zone,
259 struct compact_control *cc) 266 struct compact_control *cc)
260{ 267{
261 unsigned long low_pfn, end_pfn; 268 unsigned long low_pfn, end_pfn;
@@ -272,7 +279,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
272 /* Do not cross the free scanner or scan within a memory hole */ 279 /* Do not cross the free scanner or scan within a memory hole */
273 if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) { 280 if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
274 cc->migrate_pfn = end_pfn; 281 cc->migrate_pfn = end_pfn;
275 return 0; 282 return ISOLATE_NONE;
276 } 283 }
277 284
278 /* 285 /*
@@ -281,10 +288,14 @@ static unsigned long isolate_migratepages(struct zone *zone,
281 * delay for some time until fewer pages are isolated 288 * delay for some time until fewer pages are isolated
282 */ 289 */
283 while (unlikely(too_many_isolated(zone))) { 290 while (unlikely(too_many_isolated(zone))) {
291 /* async migration should just abort */
292 if (!cc->sync)
293 return ISOLATE_ABORT;
294
284 congestion_wait(BLK_RW_ASYNC, HZ/10); 295 congestion_wait(BLK_RW_ASYNC, HZ/10);
285 296
286 if (fatal_signal_pending(current)) 297 if (fatal_signal_pending(current))
287 return 0; 298 return ISOLATE_ABORT;
288 } 299 }
289 300
290 /* Time to isolate some pages for migration */ 301 /* Time to isolate some pages for migration */
@@ -369,7 +380,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
369 380
370 trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated); 381 trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
371 382
372 return cc->nr_migratepages; 383 return ISOLATE_SUCCESS;
373} 384}
374 385
375/* 386/*
@@ -535,8 +546,15 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
535 unsigned long nr_migrate, nr_remaining; 546 unsigned long nr_migrate, nr_remaining;
536 int err; 547 int err;
537 548
538 if (!isolate_migratepages(zone, cc)) 549 switch (isolate_migratepages(zone, cc)) {
550 case ISOLATE_ABORT:
551 ret = COMPACT_PARTIAL;
552 goto out;
553 case ISOLATE_NONE:
539 continue; 554 continue;
555 case ISOLATE_SUCCESS:
556 ;
557 }
540 558
541 nr_migrate = cc->nr_migratepages; 559 nr_migrate = cc->nr_migratepages;
542 err = migrate_pages(&cc->migratepages, compaction_alloc, 560 err = migrate_pages(&cc->migratepages, compaction_alloc,
@@ -560,6 +578,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
560 578
561 } 579 }
562 580
581out:
563 /* Release free pages and check accounting */ 582 /* Release free pages and check accounting */
564 cc->nr_freepages -= release_freepages(&cc->freepages); 583 cc->nr_freepages -= release_freepages(&cc->freepages);
565 VM_BUG_ON(cc->nr_freepages != 0); 584 VM_BUG_ON(cc->nr_freepages != 0);