diff options
author | Zlatko Calusic <zlatko.calusic@iskon.hr> | 2012-12-23 09:12:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-23 12:46:36 -0500 |
commit | 4ae0a48b5efc44a95f5e7bb578f9de71fd35bfd0 (patch) | |
tree | eb71914a38a71928cb6b528985eabafab3def51b /mm | |
parent | 9c016d61097cc39427a2f5025bdd97ac633d26a6 (diff) |
mm: modify pgdat_balanced() so that it also handles order-0
Teach pgdat_balanced() about order-0 allocations so that we can simplify
code in a few places in vmstat.c.
Suggested-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Zlatko Calusic <zlatko.calusic@iskon.hr>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/vmscan.c | 105 |
1 files changed, 45 insertions, 60 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index adc7e9058181..23291b9ae871 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -2452,12 +2452,16 @@ static bool zone_balanced(struct zone *zone, int order, | |||
2452 | } | 2452 | } |
2453 | 2453 | ||
2454 | /* | 2454 | /* |
2455 | * pgdat_balanced is used when checking if a node is balanced for high-order | 2455 | * pgdat_balanced() is used when checking if a node is balanced. |
2456 | * allocations. Only zones that meet watermarks and are in a zone allowed | 2456 | * |
2457 | * by the callers classzone_idx are added to balanced_pages. The total of | 2457 | * For order-0, all zones must be balanced! |
2458 | * balanced pages must be at least 25% of the zones allowed by classzone_idx | 2458 | * |
2459 | * for the node to be considered balanced. Forcing all zones to be balanced | 2459 | * For high-order allocations only zones that meet watermarks and are in a |
2460 | * for high orders can cause excessive reclaim when there are imbalanced zones. | 2460 | * zone allowed by the callers classzone_idx are added to balanced_pages. The |
2461 | * total of balanced pages must be at least 25% of the zones allowed by | ||
2462 | * classzone_idx for the node to be considered balanced. Forcing all zones to | ||
2463 | * be balanced for high orders can cause excessive reclaim when there are | ||
2464 | * imbalanced zones. | ||
2461 | * The choice of 25% is due to | 2465 | * The choice of 25% is due to |
2462 | * o a 16M DMA zone that is balanced will not balance a zone on any | 2466 | * o a 16M DMA zone that is balanced will not balance a zone on any |
2463 | * reasonable sized machine | 2467 | * reasonable sized machine |
@@ -2467,17 +2471,43 @@ static bool zone_balanced(struct zone *zone, int order, | |||
2467 | * Similarly, on x86-64 the Normal zone would need to be at least 1G | 2471 | * Similarly, on x86-64 the Normal zone would need to be at least 1G |
2468 | * to balance a node on its own. These seemed like reasonable ratios. | 2472 | * to balance a node on its own. These seemed like reasonable ratios. |
2469 | */ | 2473 | */ |
2470 | static bool pgdat_balanced(pg_data_t *pgdat, unsigned long balanced_pages, | 2474 | static bool pgdat_balanced(pg_data_t *pgdat, int order, int classzone_idx) |
2471 | int classzone_idx) | ||
2472 | { | 2475 | { |
2473 | unsigned long present_pages = 0; | 2476 | unsigned long present_pages = 0; |
2477 | unsigned long balanced_pages = 0; | ||
2474 | int i; | 2478 | int i; |
2475 | 2479 | ||
2476 | for (i = 0; i <= classzone_idx; i++) | 2480 | /* Check the watermark levels */ |
2477 | present_pages += pgdat->node_zones[i].present_pages; | 2481 | for (i = 0; i <= classzone_idx; i++) { |
2482 | struct zone *zone = pgdat->node_zones + i; | ||
2478 | 2483 | ||
2479 | /* A special case here: if zone has no page, we think it's balanced */ | 2484 | if (!populated_zone(zone)) |
2480 | return balanced_pages >= (present_pages >> 2); | 2485 | continue; |
2486 | |||
2487 | present_pages += zone->present_pages; | ||
2488 | |||
2489 | /* | ||
2490 | * A special case here: | ||
2491 | * | ||
2492 | * balance_pgdat() skips over all_unreclaimable after | ||
2493 | * DEF_PRIORITY. Effectively, it considers them balanced so | ||
2494 | * they must be considered balanced here as well! | ||
2495 | */ | ||
2496 | if (zone->all_unreclaimable) { | ||
2497 | balanced_pages += zone->present_pages; | ||
2498 | continue; | ||
2499 | } | ||
2500 | |||
2501 | if (zone_balanced(zone, order, 0, i)) | ||
2502 | balanced_pages += zone->present_pages; | ||
2503 | else if (!order) | ||
2504 | return false; | ||
2505 | } | ||
2506 | |||
2507 | if (order) | ||
2508 | return balanced_pages >= (present_pages >> 2); | ||
2509 | else | ||
2510 | return true; | ||
2481 | } | 2511 | } |
2482 | 2512 | ||
2483 | /* | 2513 | /* |
@@ -2489,10 +2519,6 @@ static bool pgdat_balanced(pg_data_t *pgdat, unsigned long balanced_pages, | |||
2489 | static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining, | 2519 | static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining, |
2490 | int classzone_idx) | 2520 | int classzone_idx) |
2491 | { | 2521 | { |
2492 | int i; | ||
2493 | unsigned long balanced = 0; | ||
2494 | bool all_zones_ok = true; | ||
2495 | |||
2496 | /* If a direct reclaimer woke kswapd within HZ/10, it's premature */ | 2522 | /* If a direct reclaimer woke kswapd within HZ/10, it's premature */ |
2497 | if (remaining) | 2523 | if (remaining) |
2498 | return false; | 2524 | return false; |
@@ -2511,39 +2537,7 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining, | |||
2511 | return false; | 2537 | return false; |
2512 | } | 2538 | } |
2513 | 2539 | ||
2514 | /* Check the watermark levels */ | 2540 | return pgdat_balanced(pgdat, order, classzone_idx); |
2515 | for (i = 0; i <= classzone_idx; i++) { | ||
2516 | struct zone *zone = pgdat->node_zones + i; | ||
2517 | |||
2518 | if (!populated_zone(zone)) | ||
2519 | continue; | ||
2520 | |||
2521 | /* | ||
2522 | * balance_pgdat() skips over all_unreclaimable after | ||
2523 | * DEF_PRIORITY. Effectively, it considers them balanced so | ||
2524 | * they must be considered balanced here as well if kswapd | ||
2525 | * is to sleep | ||
2526 | */ | ||
2527 | if (zone->all_unreclaimable) { | ||
2528 | balanced += zone->present_pages; | ||
2529 | continue; | ||
2530 | } | ||
2531 | |||
2532 | if (!zone_balanced(zone, order, 0, i)) | ||
2533 | all_zones_ok = false; | ||
2534 | else | ||
2535 | balanced += zone->present_pages; | ||
2536 | } | ||
2537 | |||
2538 | /* | ||
2539 | * For high-order requests, the balanced zones must contain at least | ||
2540 | * 25% of the nodes pages for kswapd to sleep. For order-0, all zones | ||
2541 | * must be balanced | ||
2542 | */ | ||
2543 | if (order) | ||
2544 | return pgdat_balanced(pgdat, balanced, classzone_idx); | ||
2545 | else | ||
2546 | return all_zones_ok; | ||
2547 | } | 2541 | } |
2548 | 2542 | ||
2549 | /* | 2543 | /* |
@@ -2571,7 +2565,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, | |||
2571 | int *classzone_idx) | 2565 | int *classzone_idx) |
2572 | { | 2566 | { |
2573 | struct zone *unbalanced_zone; | 2567 | struct zone *unbalanced_zone; |
2574 | unsigned long balanced; | ||
2575 | int i; | 2568 | int i; |
2576 | int end_zone = 0; /* Inclusive. 0 = ZONE_DMA */ | 2569 | int end_zone = 0; /* Inclusive. 0 = ZONE_DMA */ |
2577 | unsigned long total_scanned; | 2570 | unsigned long total_scanned; |
@@ -2605,7 +2598,6 @@ loop_again: | |||
2605 | int has_under_min_watermark_zone = 0; | 2598 | int has_under_min_watermark_zone = 0; |
2606 | 2599 | ||
2607 | unbalanced_zone = NULL; | 2600 | unbalanced_zone = NULL; |
2608 | balanced = 0; | ||
2609 | 2601 | ||
2610 | /* | 2602 | /* |
2611 | * Scan in the highmem->dma direction for the highest | 2603 | * Scan in the highmem->dma direction for the highest |
@@ -2761,8 +2753,6 @@ loop_again: | |||
2761 | * speculatively avoid congestion waits | 2753 | * speculatively avoid congestion waits |
2762 | */ | 2754 | */ |
2763 | zone_clear_flag(zone, ZONE_CONGESTED); | 2755 | zone_clear_flag(zone, ZONE_CONGESTED); |
2764 | if (i <= *classzone_idx) | ||
2765 | balanced += zone->present_pages; | ||
2766 | } | 2756 | } |
2767 | 2757 | ||
2768 | } | 2758 | } |
@@ -2776,7 +2766,7 @@ loop_again: | |||
2776 | pfmemalloc_watermark_ok(pgdat)) | 2766 | pfmemalloc_watermark_ok(pgdat)) |
2777 | wake_up(&pgdat->pfmemalloc_wait); | 2767 | wake_up(&pgdat->pfmemalloc_wait); |
2778 | 2768 | ||
2779 | if (!unbalanced_zone || (order && pgdat_balanced(pgdat, balanced, *classzone_idx))) | 2769 | if (pgdat_balanced(pgdat, order, *classzone_idx)) |
2780 | break; /* kswapd: all done */ | 2770 | break; /* kswapd: all done */ |
2781 | /* | 2771 | /* |
2782 | * OK, kswapd is getting into trouble. Take a nap, then take | 2772 | * OK, kswapd is getting into trouble. Take a nap, then take |
@@ -2800,12 +2790,7 @@ loop_again: | |||
2800 | } while (--sc.priority >= 0); | 2790 | } while (--sc.priority >= 0); |
2801 | out: | 2791 | out: |
2802 | 2792 | ||
2803 | /* | 2793 | if (!pgdat_balanced(pgdat, order, *classzone_idx)) { |
2804 | * order-0: All zones must meet high watermark for a balanced node | ||
2805 | * high-order: Balanced zones must make up at least 25% of the node | ||
2806 | * for the node to be balanced | ||
2807 | */ | ||
2808 | if (unbalanced_zone && (!order || !pgdat_balanced(pgdat, balanced, *classzone_idx))) { | ||
2809 | cond_resched(); | 2794 | cond_resched(); |
2810 | 2795 | ||
2811 | try_to_freeze(); | 2796 | try_to_freeze(); |