aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmscan.c
diff options
context:
space:
mode:
authorZlatko Calusic <zlatko.calusic@iskon.hr>2012-12-23 09:12:54 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-23 12:46:36 -0500
commit4ae0a48b5efc44a95f5e7bb578f9de71fd35bfd0 (patch)
treeeb71914a38a71928cb6b528985eabafab3def51b /mm/vmscan.c
parent9c016d61097cc39427a2f5025bdd97ac633d26a6 (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/vmscan.c')
-rw-r--r--mm/vmscan.c105
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 */
2470static bool pgdat_balanced(pg_data_t *pgdat, unsigned long balanced_pages, 2474static 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,
2489static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining, 2519static 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);
2801out: 2791out:
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();