diff options
Diffstat (limited to 'mm/compaction.c')
-rw-r--r-- | mm/compaction.c | 89 |
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 | */ | ||
394 | unsigned 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 | |||
387 | static int compact_zone(struct zone *zone, struct compact_control *cc) | 428 | static 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 | ||
432 | static unsigned long compact_zone_order(struct zone *zone, | 484 | unsigned 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 | ||