Skip to content

Commit

Permalink
mm: compaction: abort compaction if too many pages are isolated and c…
Browse files Browse the repository at this point in the history
…aller is asynchronous V2

Asynchronous compaction is used when promoting to huge pages.  This is all
very nice but if there are a number of processes in compacting memory, a
large number of pages can be isolated.  An "asynchronous" process can
stall for long periods of time as a result with a user reporting that
firefox can stall for 10s of seconds.  This patch aborts asynchronous
compaction if too many pages are isolated as it's better to fail a
hugepage promotion than stall a process.

[minchan.kim@gmail.com: return COMPACT_PARTIAL for abort]
Reported-and-tested-by: Ury Stankevich <urykhy@gmail.com>
Signed-off-by: Mel Gorman <mgorman@suse.de>
Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
Reviewed-by: Michal Hocko <mhocko@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Mel Gorman authored and Linus Torvalds committed Jun 16, 2011
1 parent d179e84 commit f9e35b3
Showing 1 changed file with 24 additions and 5 deletions.
29 changes: 24 additions & 5 deletions mm/compaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}

/*
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
}

/*
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down

0 comments on commit f9e35b3

Please sign in to comment.