aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r--mm/vmscan.c62
1 files changed, 37 insertions, 25 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 4f49535d4cd3..d036e59d302b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2310,7 +2310,8 @@ static bool pgdat_balanced(pg_data_t *pgdat, unsigned long balanced_pages,
2310 for (i = 0; i <= classzone_idx; i++) 2310 for (i = 0; i <= classzone_idx; i++)
2311 present_pages += pgdat->node_zones[i].present_pages; 2311 present_pages += pgdat->node_zones[i].present_pages;
2312 2312
2313 return balanced_pages > (present_pages >> 2); 2313 /* A special case here: if zone has no page, we think it's balanced */
2314 return balanced_pages >= (present_pages >> 2);
2314} 2315}
2315 2316
2316/* is kswapd sleeping prematurely? */ 2317/* is kswapd sleeping prematurely? */
@@ -2326,7 +2327,7 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining,
2326 return true; 2327 return true;
2327 2328
2328 /* Check the watermark levels */ 2329 /* Check the watermark levels */
2329 for (i = 0; i < pgdat->nr_zones; i++) { 2330 for (i = 0; i <= classzone_idx; i++) {
2330 struct zone *zone = pgdat->node_zones + i; 2331 struct zone *zone = pgdat->node_zones + i;
2331 2332
2332 if (!populated_zone(zone)) 2333 if (!populated_zone(zone))
@@ -2344,7 +2345,7 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining,
2344 } 2345 }
2345 2346
2346 if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone), 2347 if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone),
2347 classzone_idx, 0)) 2348 i, 0))
2348 all_zones_ok = false; 2349 all_zones_ok = false;
2349 else 2350 else
2350 balanced += zone->present_pages; 2351 balanced += zone->present_pages;
@@ -2451,7 +2452,6 @@ loop_again:
2451 if (!zone_watermark_ok_safe(zone, order, 2452 if (!zone_watermark_ok_safe(zone, order,
2452 high_wmark_pages(zone), 0, 0)) { 2453 high_wmark_pages(zone), 0, 0)) {
2453 end_zone = i; 2454 end_zone = i;
2454 *classzone_idx = i;
2455 break; 2455 break;
2456 } 2456 }
2457 } 2457 }
@@ -2510,18 +2510,18 @@ loop_again:
2510 KSWAPD_ZONE_BALANCE_GAP_RATIO); 2510 KSWAPD_ZONE_BALANCE_GAP_RATIO);
2511 if (!zone_watermark_ok_safe(zone, order, 2511 if (!zone_watermark_ok_safe(zone, order,
2512 high_wmark_pages(zone) + balance_gap, 2512 high_wmark_pages(zone) + balance_gap,
2513 end_zone, 0)) 2513 end_zone, 0)) {
2514 shrink_zone(priority, zone, &sc); 2514 shrink_zone(priority, zone, &sc);
2515 reclaim_state->reclaimed_slab = 0;
2516 nr_slab = shrink_slab(&shrink, sc.nr_scanned, lru_pages);
2517 sc.nr_reclaimed += reclaim_state->reclaimed_slab;
2518 total_scanned += sc.nr_scanned;
2519 2515
2520 if (zone->all_unreclaimable) 2516 reclaim_state->reclaimed_slab = 0;
2521 continue; 2517 nr_slab = shrink_slab(&shrink, sc.nr_scanned, lru_pages);
2522 if (nr_slab == 0 && 2518 sc.nr_reclaimed += reclaim_state->reclaimed_slab;
2523 !zone_reclaimable(zone)) 2519 total_scanned += sc.nr_scanned;
2524 zone->all_unreclaimable = 1; 2520
2521 if (nr_slab == 0 && !zone_reclaimable(zone))
2522 zone->all_unreclaimable = 1;
2523 }
2524
2525 /* 2525 /*
2526 * If we've done a decent amount of scanning and 2526 * If we've done a decent amount of scanning and
2527 * the reclaim ratio is low, start doing writepage 2527 * the reclaim ratio is low, start doing writepage
@@ -2531,6 +2531,12 @@ loop_again:
2531 total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2) 2531 total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2)
2532 sc.may_writepage = 1; 2532 sc.may_writepage = 1;
2533 2533
2534 if (zone->all_unreclaimable) {
2535 if (end_zone && end_zone == i)
2536 end_zone--;
2537 continue;
2538 }
2539
2534 if (!zone_watermark_ok_safe(zone, order, 2540 if (!zone_watermark_ok_safe(zone, order,
2535 high_wmark_pages(zone), end_zone, 0)) { 2541 high_wmark_pages(zone), end_zone, 0)) {
2536 all_zones_ok = 0; 2542 all_zones_ok = 0;
@@ -2709,8 +2715,8 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx)
2709 */ 2715 */
2710static int kswapd(void *p) 2716static int kswapd(void *p)
2711{ 2717{
2712 unsigned long order; 2718 unsigned long order, new_order;
2713 int classzone_idx; 2719 int classzone_idx, new_classzone_idx;
2714 pg_data_t *pgdat = (pg_data_t*)p; 2720 pg_data_t *pgdat = (pg_data_t*)p;
2715 struct task_struct *tsk = current; 2721 struct task_struct *tsk = current;
2716 2722
@@ -2740,17 +2746,23 @@ static int kswapd(void *p)
2740 tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD; 2746 tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
2741 set_freezable(); 2747 set_freezable();
2742 2748
2743 order = 0; 2749 order = new_order = 0;
2744 classzone_idx = MAX_NR_ZONES - 1; 2750 classzone_idx = new_classzone_idx = pgdat->nr_zones - 1;
2745 for ( ; ; ) { 2751 for ( ; ; ) {
2746 unsigned long new_order;
2747 int new_classzone_idx;
2748 int ret; 2752 int ret;
2749 2753
2750 new_order = pgdat->kswapd_max_order; 2754 /*
2751 new_classzone_idx = pgdat->classzone_idx; 2755 * If the last balance_pgdat was unsuccessful it's unlikely a
2752 pgdat->kswapd_max_order = 0; 2756 * new request of a similar or harder type will succeed soon
2753 pgdat->classzone_idx = MAX_NR_ZONES - 1; 2757 * so consider going to sleep on the basis we reclaimed at
2758 */
2759 if (classzone_idx >= new_classzone_idx && order == new_order) {
2760 new_order = pgdat->kswapd_max_order;
2761 new_classzone_idx = pgdat->classzone_idx;
2762 pgdat->kswapd_max_order = 0;
2763 pgdat->classzone_idx = pgdat->nr_zones - 1;
2764 }
2765
2754 if (order < new_order || classzone_idx > new_classzone_idx) { 2766 if (order < new_order || classzone_idx > new_classzone_idx) {
2755 /* 2767 /*
2756 * Don't sleep if someone wants a larger 'order' 2768 * Don't sleep if someone wants a larger 'order'
@@ -2763,7 +2775,7 @@ static int kswapd(void *p)
2763 order = pgdat->kswapd_max_order; 2775 order = pgdat->kswapd_max_order;
2764 classzone_idx = pgdat->classzone_idx; 2776 classzone_idx = pgdat->classzone_idx;
2765 pgdat->kswapd_max_order = 0; 2777 pgdat->kswapd_max_order = 0;
2766 pgdat->classzone_idx = MAX_NR_ZONES - 1; 2778 pgdat->classzone_idx = pgdat->nr_zones - 1;
2767 } 2779 }
2768 2780
2769 ret = try_to_freeze(); 2781 ret = try_to_freeze();