aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/compaction.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/mm/compaction.c b/mm/compaction.c
index 1427366ad673..79bfe0e06907 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -441,25 +441,23 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
441 441
442 /* Found a free page, break it into order-0 pages */ 442 /* Found a free page, break it into order-0 pages */
443 isolated = split_free_page(page); 443 isolated = split_free_page(page);
444 if (!isolated)
445 break;
446
444 total_isolated += isolated; 447 total_isolated += isolated;
448 cc->nr_freepages += isolated;
445 for (i = 0; i < isolated; i++) { 449 for (i = 0; i < isolated; i++) {
446 list_add(&page->lru, freelist); 450 list_add(&page->lru, freelist);
447 page++; 451 page++;
448 } 452 }
449 453 if (!strict && cc->nr_migratepages <= cc->nr_freepages) {
450 /* If a page was split, advance to the end of it */ 454 blockpfn += isolated;
451 if (isolated) { 455 break;
452 cc->nr_freepages += isolated;
453 if (!strict &&
454 cc->nr_migratepages <= cc->nr_freepages) {
455 blockpfn += isolated;
456 break;
457 }
458
459 blockpfn += isolated - 1;
460 cursor += isolated - 1;
461 continue;
462 } 456 }
457 /* Advance to the end of split page */
458 blockpfn += isolated - 1;
459 cursor += isolated - 1;
460 continue;
463 461
464isolate_fail: 462isolate_fail:
465 if (strict) 463 if (strict)
@@ -469,6 +467,9 @@ isolate_fail:
469 467
470 } 468 }
471 469
470 if (locked)
471 spin_unlock_irqrestore(&cc->zone->lock, flags);
472
472 /* 473 /*
473 * There is a tiny chance that we have read bogus compound_order(), 474 * There is a tiny chance that we have read bogus compound_order(),
474 * so be careful to not go outside of the pageblock. 475 * so be careful to not go outside of the pageblock.
@@ -490,9 +491,6 @@ isolate_fail:
490 if (strict && blockpfn < end_pfn) 491 if (strict && blockpfn < end_pfn)
491 total_isolated = 0; 492 total_isolated = 0;
492 493
493 if (locked)
494 spin_unlock_irqrestore(&cc->zone->lock, flags);
495
496 /* Update the pageblock-skip if the whole pageblock was scanned */ 494 /* Update the pageblock-skip if the whole pageblock was scanned */
497 if (blockpfn == end_pfn) 495 if (blockpfn == end_pfn)
498 update_pageblock_skip(cc, valid_page, total_isolated, false); 496 update_pageblock_skip(cc, valid_page, total_isolated, false);
@@ -1011,6 +1009,7 @@ static void isolate_freepages(struct compact_control *cc)
1011 block_end_pfn = block_start_pfn, 1009 block_end_pfn = block_start_pfn,
1012 block_start_pfn -= pageblock_nr_pages, 1010 block_start_pfn -= pageblock_nr_pages,
1013 isolate_start_pfn = block_start_pfn) { 1011 isolate_start_pfn = block_start_pfn) {
1012 unsigned long isolated;
1014 1013
1015 /* 1014 /*
1016 * This can iterate a massively long zone without finding any 1015 * This can iterate a massively long zone without finding any
@@ -1035,8 +1034,12 @@ static void isolate_freepages(struct compact_control *cc)
1035 continue; 1034 continue;
1036 1035
1037 /* Found a block suitable for isolating free pages from. */ 1036 /* Found a block suitable for isolating free pages from. */
1038 isolate_freepages_block(cc, &isolate_start_pfn, 1037 isolated = isolate_freepages_block(cc, &isolate_start_pfn,
1039 block_end_pfn, freelist, false); 1038 block_end_pfn, freelist, false);
1039 /* If isolation failed early, do not continue needlessly */
1040 if (!isolated && isolate_start_pfn < block_end_pfn &&
1041 cc->nr_migratepages > cc->nr_freepages)
1042 break;
1040 1043
1041 /* 1044 /*
1042 * If we isolated enough freepages, or aborted due to async 1045 * If we isolated enough freepages, or aborted due to async