aboutsummaryrefslogtreecommitdiffstats
path: root/mm/compaction.c
diff options
context:
space:
mode:
authorMel Gorman <mel@csn.ul.ie>2011-01-13 18:45:56 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 20:32:33 -0500
commit3e7d344970673c5334cf7b5bb27c8c0942b06126 (patch)
tree832ecb4da5fd27efa5a503df5b96bfdee2a52ffd /mm/compaction.c
parentee64fc9354e515a79c7232cfde65c88ec627308b (diff)
mm: vmscan: reclaim order-0 and use compaction instead of lumpy reclaim
Lumpy reclaim is disruptive. It reclaims a large number of pages and ignores the age of the pages it reclaims. This can incur significant stalls and potentially increase the number of major faults. Compaction has reached the point where it is considered reasonably stable (meaning it has passed a lot of testing) and is a potential candidate for displacing lumpy reclaim. This patch introduces an alternative to lumpy reclaim whe compaction is available called reclaim/compaction. The basic operation is very simple - instead of selecting a contiguous range of pages to reclaim, a number of order-0 pages are reclaimed and then compaction is later by either kswapd (compact_zone_order()) or direct compaction (__alloc_pages_direct_compact()). [akpm@linux-foundation.org: fix build] [akpm@linux-foundation.org: use conventional task_struct naming] Signed-off-by: Mel Gorman <mel@csn.ul.ie> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Rik van Riel <riel@redhat.com> Acked-by: Johannes Weiner <hannes@cmpxchg.org> Cc: Andy Whitcroft <apw@shadowen.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.c89
1 files changed, 55 insertions, 34 deletions
diff --git a/mm/compaction.c b/mm/compaction.c
index 20011a850fef..8fe917ec7c11 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -384,10 +384,62 @@ static int compact_finished(struct zone *zone,
384 return COMPACT_CONTINUE; 384 return COMPACT_CONTINUE;
385} 385}
386 386
387/*
388 * compaction_suitable: Is this suitable to run compaction on this zone now?
389 * Returns
390 * COMPACT_SKIPPED - If there are too few free pages for compaction
391 * COMPACT_PARTIAL - If the allocation would succeed without compaction
392 * COMPACT_CONTINUE - If compaction should run now
393 */
394unsigned long compaction_suitable(struct zone *zone, int order)
395{
396 int fragindex;
397 unsigned long watermark;
398
399 /*
400 * Watermarks for order-0 must be met for compaction. Note the 2UL.
401 * This is because during migration, copies of pages need to be
402 * allocated and for a short time, the footprint is higher
403 */
404 watermark = low_wmark_pages(zone) + (2UL << order);
405 if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
406 return COMPACT_SKIPPED;
407
408 /*
409 * fragmentation index determines if allocation failures are due to
410 * low memory or external fragmentation
411 *
412 * index of -1 implies allocations might succeed dependingon watermarks
413 * index towards 0 implies failure is due to lack of memory
414 * index towards 1000 implies failure is due to fragmentation
415 *
416 * Only compact if a failure would be due to fragmentation.
417 */
418 fragindex = fragmentation_index(zone, order);
419 if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold)
420 return COMPACT_SKIPPED;
421
422 if (fragindex == -1 && zone_watermark_ok(zone, order, watermark, 0, 0))
423 return COMPACT_PARTIAL;
424
425 return COMPACT_CONTINUE;
426}
427
387static int compact_zone(struct zone *zone, struct compact_control *cc) 428static int compact_zone(struct zone *zone, struct compact_control *cc)
388{ 429{
389 int ret; 430 int ret;
390 431
432 ret = compaction_suitable(zone, cc->order);
433 switch (ret) {
434 case COMPACT_PARTIAL:
435 case COMPACT_SKIPPED:
436 /* Compaction is likely to fail */
437 return ret;
438 case COMPACT_CONTINUE:
439 /* Fall through to compaction */
440 ;
441 }
442
391 /* Setup to move all movable pages to the end of the zone */ 443 /* Setup to move all movable pages to the end of the zone */
392 cc->migrate_pfn = zone->zone_start_pfn; 444 cc->migrate_pfn = zone->zone_start_pfn;
393 cc->free_pfn = cc->migrate_pfn + zone->spanned_pages; 445 cc->free_pfn = cc->migrate_pfn + zone->spanned_pages;
@@ -429,7 +481,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
429 return ret; 481 return ret;
430} 482}
431 483
432static unsigned long compact_zone_order(struct zone *zone, 484unsigned long compact_zone_order(struct zone *zone,
433 int order, gfp_t gfp_mask) 485 int order, gfp_t gfp_mask)
434{ 486{
435 struct compact_control cc = { 487 struct compact_control cc = {
@@ -462,7 +514,6 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
462 enum zone_type high_zoneidx = gfp_zone(gfp_mask); 514 enum zone_type high_zoneidx = gfp_zone(gfp_mask);
463 int may_enter_fs = gfp_mask & __GFP_FS; 515 int may_enter_fs = gfp_mask & __GFP_FS;
464 int may_perform_io = gfp_mask & __GFP_IO; 516 int may_perform_io = gfp_mask & __GFP_IO;
465 unsigned long watermark;
466 struct zoneref *z; 517 struct zoneref *z;
467 struct zone *zone; 518 struct zone *zone;
468 int rc = COMPACT_SKIPPED; 519 int rc = COMPACT_SKIPPED;
@@ -480,43 +531,13 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
480 /* Compact each zone in the list */ 531 /* Compact each zone in the list */
481 for_each_zone_zonelist_nodemask(zone, z, zonelist, high_zoneidx, 532 for_each_zone_zonelist_nodemask(zone, z, zonelist, high_zoneidx,
482 nodemask) { 533 nodemask) {
483 int fragindex;
484 int status; 534 int status;
485 535
486 /*
487 * Watermarks for order-0 must be met for compaction. Note
488 * the 2UL. This is because during migration, copies of
489 * pages need to be allocated and for a short time, the
490 * footprint is higher
491 */
492 watermark = low_wmark_pages(zone) + (2UL << order);
493 if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
494 continue;
495
496 /*
497 * fragmentation index determines if allocation failures are
498 * due to low memory or external fragmentation
499 *
500 * index of -1 implies allocations might succeed depending
501 * on watermarks
502 * index towards 0 implies failure is due to lack of memory
503 * index towards 1000 implies failure is due to fragmentation
504 *
505 * Only compact if a failure would be due to fragmentation.
506 */
507 fragindex = fragmentation_index(zone, order);
508 if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold)
509 continue;
510
511 if (fragindex == -1 && zone_watermark_ok(zone, order, watermark, 0, 0)) {
512 rc = COMPACT_PARTIAL;
513 break;
514 }
515
516 status = compact_zone_order(zone, order, gfp_mask); 536 status = compact_zone_order(zone, order, gfp_mask);
517 rc = max(status, rc); 537 rc = max(status, rc);
518 538
519 if (zone_watermark_ok(zone, order, watermark, 0, 0)) 539 /* If a normal allocation would succeed, stop compacting */
540 if (zone_watermark_ok(zone, order, low_wmark_pages(zone), 0, 0))
520 break; 541 break;
521 } 542 }
522 543