|
|
@@ -441,25 +441,23 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
|
|
|
|
|
|
/* Found a free page, break it into order-0 pages */
|
|
|
isolated = split_free_page(page);
|
|
|
+ if (!isolated)
|
|
|
+ break;
|
|
|
+
|
|
|
total_isolated += isolated;
|
|
|
+ cc->nr_freepages += isolated;
|
|
|
for (i = 0; i < isolated; i++) {
|
|
|
list_add(&page->lru, freelist);
|
|
|
page++;
|
|
|
}
|
|
|
-
|
|
|
- /* If a page was split, advance to the end of it */
|
|
|
- if (isolated) {
|
|
|
- cc->nr_freepages += isolated;
|
|
|
- if (!strict &&
|
|
|
- cc->nr_migratepages <= cc->nr_freepages) {
|
|
|
- blockpfn += isolated;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- blockpfn += isolated - 1;
|
|
|
- cursor += isolated - 1;
|
|
|
- continue;
|
|
|
+ if (!strict && cc->nr_migratepages <= cc->nr_freepages) {
|
|
|
+ blockpfn += isolated;
|
|
|
+ break;
|
|
|
}
|
|
|
+ /* Advance to the end of split page */
|
|
|
+ blockpfn += isolated - 1;
|
|
|
+ cursor += isolated - 1;
|
|
|
+ continue;
|
|
|
|
|
|
isolate_fail:
|
|
|
if (strict)
|
|
|
@@ -469,6 +467,9 @@ isolate_fail:
|
|
|
|
|
|
}
|
|
|
|
|
|
+ if (locked)
|
|
|
+ spin_unlock_irqrestore(&cc->zone->lock, flags);
|
|
|
+
|
|
|
/*
|
|
|
* There is a tiny chance that we have read bogus compound_order(),
|
|
|
* so be careful to not go outside of the pageblock.
|
|
|
@@ -490,9 +491,6 @@ isolate_fail:
|
|
|
if (strict && blockpfn < end_pfn)
|
|
|
total_isolated = 0;
|
|
|
|
|
|
- if (locked)
|
|
|
- spin_unlock_irqrestore(&cc->zone->lock, flags);
|
|
|
-
|
|
|
/* Update the pageblock-skip if the whole pageblock was scanned */
|
|
|
if (blockpfn == end_pfn)
|
|
|
update_pageblock_skip(cc, valid_page, total_isolated, false);
|
|
|
@@ -1011,6 +1009,7 @@ static void isolate_freepages(struct compact_control *cc)
|
|
|
block_end_pfn = block_start_pfn,
|
|
|
block_start_pfn -= pageblock_nr_pages,
|
|
|
isolate_start_pfn = block_start_pfn) {
|
|
|
+ unsigned long isolated;
|
|
|
|
|
|
/*
|
|
|
* This can iterate a massively long zone without finding any
|
|
|
@@ -1035,8 +1034,12 @@ static void isolate_freepages(struct compact_control *cc)
|
|
|
continue;
|
|
|
|
|
|
/* Found a block suitable for isolating free pages from. */
|
|
|
- isolate_freepages_block(cc, &isolate_start_pfn,
|
|
|
- block_end_pfn, freelist, false);
|
|
|
+ isolated = isolate_freepages_block(cc, &isolate_start_pfn,
|
|
|
+ block_end_pfn, freelist, false);
|
|
|
+ /* If isolation failed early, do not continue needlessly */
|
|
|
+ if (!isolated && isolate_start_pfn < block_end_pfn &&
|
|
|
+ cc->nr_migratepages > cc->nr_freepages)
|
|
|
+ break;
|
|
|
|
|
|
/*
|
|
|
* If we isolated enough freepages, or aborted due to async
|