Patchwork [2/2] make the compaction "skip ahead" logic robust

login
register
mail settings
Submitter Rik van Riel
Date Sept. 13, 2012, 7:48 p.m.
Message ID <20120913154824.44cc0e28@cuia.bos.redhat.com>
Download mbox | patch
Permalink /patch/183704/
State New
Headers show

Comments

Rik van Riel - Sept. 13, 2012, 7:48 p.m.
Make the "skip ahead" logic in compaction resistant to compaction
wrapping around to the end of the zone.  This can lead to less
efficient compaction when one thread has wrapped around to the
end of the zone, and another simultaneous compactor has not done
so yet. However, it should ensure that we do not suffer quadratic
behaviour any more.

Signed-off-by: Rik van Riel <riel@redhat.com>
Reported-by: Richard Davies <richard@daviesmail.org>

Patch

diff --git a/mm/compaction.c b/mm/compaction.c
index 771775d..0656759 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -431,6 +431,24 @@  static bool suitable_migration_target(struct page *page)
 }
 
 /*
+ * We scan the zone in a circular fashion, starting at
+ * zone->compact_cached_free_pfn. Be careful not to skip if
+ * one compacting thread has just wrapped back to the end of the
+ * zone, but another thread has not.
+ */
+static bool compaction_may_skip(struct zone *zone,
+				struct compact_control *cc)
+{
+	if (!cc->wrapped && zone->compact_free_pfn < cc->start_pfn)
+		return true;
+
+	if (cc->wrapped && zone_compact_free_pfn > cc->start_pfn)
+		return true;
+
+	return false;
+}
+
+/*
  * Based on information in the current compact_control, find blocks
  * suitable for isolating free pages from and then isolate them.
  */
@@ -471,13 +489,9 @@  static void isolate_freepages(struct zone *zone,
 
 		/*
 		 * Skip ahead if another thread is compacting in the area
-		 * simultaneously. If we wrapped around, we can only skip
-		 * ahead if zone->compact_cached_free_pfn also wrapped to
-		 * above our starting point.
+		 * simultaneously, and has finished with this page block.
 		 */
-		if (cc->order > 0 && (!cc->wrapped ||
-				      zone->compact_cached_free_pfn >
-				      cc->start_free_pfn))
+		if (cc->order > 0 && compaction_may_skip(zone, cc))
 			pfn = min(pfn, zone->compact_cached_free_pfn);
 
 		if (!pfn_valid(pfn))