diff options
-rw-r--r-- | mm/compaction.c | 29 |
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 */ | ||
255 | typedef 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 | */ |
258 | static unsigned long isolate_migratepages(struct zone *zone, | 265 | static 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 | ||
581 | out: | ||
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); |