|
@@ -251,11 +251,18 @@ static bool too_many_isolated(struct zone *zone)
|
|
|
return isolated > (inactive + active) / 2;
|
|
|
}
|
|
|
|
|
|
+/* possible outcome of isolate_migratepages */
|
|
|
+typedef enum {
|
|
|
+ ISOLATE_ABORT, /* Abort compaction now */
|
|
|
+ ISOLATE_NONE, /* No pages isolated, continue scanning */
|
|
|
+ ISOLATE_SUCCESS, /* Pages isolated, migrate */
|
|
|
+} isolate_migrate_t;
|
|
|
+
|
|
|
/*
|
|
|
* Isolate all pages that can be migrated from the block pointed to by
|
|
|
* the migrate scanner within compact_control.
|
|
|
*/
|
|
|
-static unsigned long isolate_migratepages(struct zone *zone,
|
|
|
+static isolate_migrate_t isolate_migratepages(struct zone *zone,
|
|
|
struct compact_control *cc)
|
|
|
{
|
|
|
unsigned long low_pfn, end_pfn;
|
|
@@ -272,7 +279,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
|
|
|
/* Do not cross the free scanner or scan within a memory hole */
|
|
|
if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
|
|
|
cc->migrate_pfn = end_pfn;
|
|
|
- return 0;
|
|
|
+ return ISOLATE_NONE;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -281,10 +288,14 @@ static unsigned long isolate_migratepages(struct zone *zone,
|
|
|
* delay for some time until fewer pages are isolated
|
|
|
*/
|
|
|
while (unlikely(too_many_isolated(zone))) {
|
|
|
+ /* async migration should just abort */
|
|
|
+ if (!cc->sync)
|
|
|
+ return ISOLATE_ABORT;
|
|
|
+
|
|
|
congestion_wait(BLK_RW_ASYNC, HZ/10);
|
|
|
|
|
|
if (fatal_signal_pending(current))
|
|
|
- return 0;
|
|
|
+ return ISOLATE_ABORT;
|
|
|
}
|
|
|
|
|
|
/* Time to isolate some pages for migration */
|
|
@@ -369,7 +380,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
|
|
|
|
|
|
trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
|
|
|
|
|
|
- return cc->nr_migratepages;
|
|
|
+ return ISOLATE_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -535,8 +546,15 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
|
|
|
unsigned long nr_migrate, nr_remaining;
|
|
|
int err;
|
|
|
|
|
|
- if (!isolate_migratepages(zone, cc))
|
|
|
+ switch (isolate_migratepages(zone, cc)) {
|
|
|
+ case ISOLATE_ABORT:
|
|
|
+ ret = COMPACT_PARTIAL;
|
|
|
+ goto out;
|
|
|
+ case ISOLATE_NONE:
|
|
|
continue;
|
|
|
+ case ISOLATE_SUCCESS:
|
|
|
+ ;
|
|
|
+ }
|
|
|
|
|
|
nr_migrate = cc->nr_migratepages;
|
|
|
err = migrate_pages(&cc->migratepages, compaction_alloc,
|
|
@@ -560,6 +578,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
|
|
|
|
|
|
}
|
|
|
|
|
|
+out:
|
|
|
/* Release free pages and check accounting */
|
|
|
cc->nr_freepages -= release_freepages(&cc->freepages);
|
|
|
VM_BUG_ON(cc->nr_freepages != 0);
|