summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/compaction.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/mm/compaction.c b/mm/compaction.c
index e609415059e8..78ae182aaf34 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1971,6 +1971,7 @@ static enum compact_result compact_zone(struct compact_control *cc)
unsigned long end_pfn = zone_end_pfn(cc->zone);
unsigned long last_migrated_pfn;
const bool sync = cc->mode != MIGRATE_ASYNC;
+ bool update_cached;
cc->migratetype = gfpflags_to_migratetype(cc->gfp_mask);
ret = compaction_suitable(cc->zone, cc->order, cc->alloc_flags,
@@ -2018,6 +2019,17 @@ static enum compact_result compact_zone(struct compact_control *cc)
last_migrated_pfn = 0;
+ /*
+ * Migrate has separate cached PFNs for ASYNC and SYNC* migration on
+ * the basis that some migrations will fail in ASYNC mode. However,
+ * if the cached PFNs match and pageblocks are skipped due to having
+ * no isolation candidates, then the sync state does not matter.
+ * Until a pageblock with isolation candidates is found, keep the
+ * cached PFNs in sync to avoid revisiting the same blocks.
+ */
+ update_cached = !sync &&
+ cc->zone->compact_cached_migrate_pfn[0] == cc->zone->compact_cached_migrate_pfn[1];
+
trace_mm_compaction_begin(start_pfn, cc->migrate_pfn,
cc->free_pfn, end_pfn, sync);
@@ -2049,6 +2061,11 @@ static enum compact_result compact_zone(struct compact_control *cc)
last_migrated_pfn = 0;
goto out;
case ISOLATE_NONE:
+ if (update_cached) {
+ cc->zone->compact_cached_migrate_pfn[1] =
+ cc->zone->compact_cached_migrate_pfn[0];
+ }
+
/*
* We haven't isolated and migrated anything, but
* there might still be unflushed migrations from
@@ -2056,6 +2073,7 @@ static enum compact_result compact_zone(struct compact_control *cc)
*/
goto check_drain;
case ISOLATE_SUCCESS:
+ update_cached = false;
last_migrated_pfn = start_pfn;
;
}