aboutsummaryrefslogtreecommitdiffstats
path: root/mm/compaction.c
diff options
context:
space:
mode:
authorShaohua Li <shli@kernel.org>2012-10-08 19:32:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 03:22:48 -0400
commite64c5237cf6ff474cb2f3f832f48f2b441dd9979 (patch)
tree88fb8ec8e9e2d32051aaacf90a306f7b124e4135 /mm/compaction.c
parentf2d52fe51c8c0a18cf5fbe583bad51090d12c146 (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.c17
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
915int sysctl_extfrag_threshold = 500; 922int sysctl_extfrag_threshold = 500;