|
@@ -1318,6 +1318,17 @@ static enum compact_result __compact_finished(struct zone *zone,
|
|
|
if (is_via_compact_memory(cc->order))
|
|
|
return COMPACT_CONTINUE;
|
|
|
|
|
|
+ if (cc->finishing_block) {
|
|
|
+ /*
|
|
|
+ * We have finished the pageblock, but better check again that
|
|
|
+ * we really succeeded.
|
|
|
+ */
|
|
|
+ if (IS_ALIGNED(cc->migrate_pfn, pageblock_nr_pages))
|
|
|
+ cc->finishing_block = false;
|
|
|
+ else
|
|
|
+ return COMPACT_CONTINUE;
|
|
|
+ }
|
|
|
+
|
|
|
/* Direct compactor: Is a suitable page free? */
|
|
|
for (order = cc->order; order < MAX_ORDER; order++) {
|
|
|
struct free_area *area = &zone->free_area[order];
|
|
@@ -1338,8 +1349,29 @@ static enum compact_result __compact_finished(struct zone *zone,
|
|
|
* other migratetype buddy lists.
|
|
|
*/
|
|
|
if (find_suitable_fallback(area, order, migratetype,
|
|
|
- true, &can_steal) != -1)
|
|
|
- return COMPACT_SUCCESS;
|
|
|
+ true, &can_steal) != -1) {
|
|
|
+
|
|
|
+ /* movable pages are OK in any pageblock */
|
|
|
+ if (migratetype == MIGRATE_MOVABLE)
|
|
|
+ return COMPACT_SUCCESS;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We are stealing for a non-movable allocation. Make
|
|
|
+ * sure we finish compacting the current pageblock
|
|
|
+ * first so it is as free as possible and we won't
|
|
|
+ * have to steal another one soon. This only applies
|
|
|
+ * to sync compaction, as async compaction operates
|
|
|
+ * on pageblocks of the same migratetype.
|
|
|
+ */
|
|
|
+ if (cc->mode == MIGRATE_ASYNC ||
|
|
|
+ IS_ALIGNED(cc->migrate_pfn,
|
|
|
+ pageblock_nr_pages)) {
|
|
|
+ return COMPACT_SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ cc->finishing_block = true;
|
|
|
+ return COMPACT_CONTINUE;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return COMPACT_NO_SUITABLE_PAGE;
|