diff options
author | Shaohua Li <shli@kernel.org> | 2012-10-08 19:32:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 03:22:48 -0400 |
commit | e64c5237cf6ff474cb2f3f832f48f2b441dd9979 (patch) | |
tree | 88fb8ec8e9e2d32051aaacf90a306f7b124e4135 /mm/compaction.c | |
parent | f2d52fe51c8c0a18cf5fbe583bad51090d12c146 (diff) |
mm: compaction: abort compaction loop if lock is contended or run too long
isolate_migratepages_range() might isolate no pages if for example when
zone->lru_lock is contended and running asynchronous compaction. In this
case, we should abort compaction, otherwise, compact_zone will run a
useless loop and make zone->lru_lock is even contended.
An additional check is added to ensure that cc.migratepages and
cc.freepages get properly drained whan compaction is aborted.
[minchan@kernel.org: Putback pages isolated for migration if aborting]
[akpm@linux-foundation.org: compact_zone_order requires non-NULL arg contended]
[akpm@linux-foundation.org: make compact_zone_order() require non-NULL arg `contended']
[minchan@kernel.org: Putback pages isolated for migration if aborting]
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Shaohua Li <shli@fusionio.com>
Signed-off-by: Mel Gorman <mgorman@suse.de>
Acked-by: Minchan Kim <minchan@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/compaction.c')
-rw-r--r-- | mm/compaction.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/mm/compaction.c b/mm/compaction.c index 1f61bcbd6262..0649cc1b3479 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -70,8 +70,7 @@ static bool compact_checklock_irqsave(spinlock_t *lock, unsigned long *flags, | |||
70 | 70 | ||
71 | /* async aborts if taking too long or contended */ | 71 | /* async aborts if taking too long or contended */ |
72 | if (!cc->sync) { | 72 | if (!cc->sync) { |
73 | if (cc->contended) | 73 | cc->contended = true; |
74 | *cc->contended = true; | ||
75 | return false; | 74 | return false; |
76 | } | 75 | } |
77 | 76 | ||
@@ -688,7 +687,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, | |||
688 | 687 | ||
689 | /* Perform the isolation */ | 688 | /* Perform the isolation */ |
690 | low_pfn = isolate_migratepages_range(zone, cc, low_pfn, end_pfn); | 689 | low_pfn = isolate_migratepages_range(zone, cc, low_pfn, end_pfn); |
691 | if (!low_pfn) | 690 | if (!low_pfn || cc->contended) |
692 | return ISOLATE_ABORT; | 691 | return ISOLATE_ABORT; |
693 | 692 | ||
694 | cc->migrate_pfn = low_pfn; | 693 | cc->migrate_pfn = low_pfn; |
@@ -848,6 +847,8 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) | |||
848 | switch (isolate_migratepages(zone, cc)) { | 847 | switch (isolate_migratepages(zone, cc)) { |
849 | case ISOLATE_ABORT: | 848 | case ISOLATE_ABORT: |
850 | ret = COMPACT_PARTIAL; | 849 | ret = COMPACT_PARTIAL; |
850 | putback_lru_pages(&cc->migratepages); | ||
851 | cc->nr_migratepages = 0; | ||
851 | goto out; | 852 | goto out; |
852 | case ISOLATE_NONE: | 853 | case ISOLATE_NONE: |
853 | continue; | 854 | continue; |
@@ -896,6 +897,7 @@ static unsigned long compact_zone_order(struct zone *zone, | |||
896 | bool sync, bool *contended, | 897 | bool sync, bool *contended, |
897 | struct page **page) | 898 | struct page **page) |
898 | { | 899 | { |
900 | unsigned long ret; | ||
899 | struct compact_control cc = { | 901 | struct compact_control cc = { |
900 | .nr_freepages = 0, | 902 | .nr_freepages = 0, |
901 | .nr_migratepages = 0, | 903 | .nr_migratepages = 0, |
@@ -903,13 +905,18 @@ static unsigned long compact_zone_order(struct zone *zone, | |||
903 | .migratetype = allocflags_to_migratetype(gfp_mask), | 905 | .migratetype = allocflags_to_migratetype(gfp_mask), |
904 | .zone = zone, | 906 | .zone = zone, |
905 | .sync = sync, | 907 | .sync = sync, |
906 | .contended = contended, | ||
907 | .page = page, | 908 | .page = page, |
908 | }; | 909 | }; |
909 | INIT_LIST_HEAD(&cc.freepages); | 910 | INIT_LIST_HEAD(&cc.freepages); |
910 | INIT_LIST_HEAD(&cc.migratepages); | 911 | INIT_LIST_HEAD(&cc.migratepages); |
911 | 912 | ||
912 | return compact_zone(zone, &cc); | 913 | ret = compact_zone(zone, &cc); |
914 | |||
915 | VM_BUG_ON(!list_empty(&cc.freepages)); | ||
916 | VM_BUG_ON(!list_empty(&cc.migratepages)); | ||
917 | |||
918 | *contended = cc.contended; | ||
919 | return ret; | ||
913 | } | 920 | } |
914 | 921 | ||
915 | int sysctl_extfrag_threshold = 500; | 922 | int sysctl_extfrag_threshold = 500; |