diff options
-rw-r--r-- | include/linux/mmzone.h | 4 | ||||
-rw-r--r-- | mm/page_alloc.c | 2 | ||||
-rw-r--r-- | mm/vmscan.c | 39 | ||||
-rw-r--r-- | mm/vmstat.c | 8 |
4 files changed, 35 insertions, 18 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index dd8487f0442f..db976b9f8791 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -334,9 +334,9 @@ struct zone { | |||
334 | 334 | ||
335 | /* Fields commonly accessed by the page reclaim scanner */ | 335 | /* Fields commonly accessed by the page reclaim scanner */ |
336 | spinlock_t lru_lock; | 336 | spinlock_t lru_lock; |
337 | struct { | 337 | struct zone_lru { |
338 | struct list_head list; | 338 | struct list_head list; |
339 | unsigned long nr_scan; | 339 | unsigned long nr_saved_scan; /* accumulated for batching */ |
340 | } lru[NR_LRU_LISTS]; | 340 | } lru[NR_LRU_LISTS]; |
341 | 341 | ||
342 | struct zone_reclaim_stat reclaim_stat; | 342 | struct zone_reclaim_stat reclaim_stat; |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 131655cdb6b2..e5b8f628d166 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -3657,7 +3657,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, | |||
3657 | zone_pcp_init(zone); | 3657 | zone_pcp_init(zone); |
3658 | for_each_lru(l) { | 3658 | for_each_lru(l) { |
3659 | INIT_LIST_HEAD(&zone->lru[l].list); | 3659 | INIT_LIST_HEAD(&zone->lru[l].list); |
3660 | zone->lru[l].nr_scan = 0; | 3660 | zone->lru[l].nr_saved_scan = 0; |
3661 | } | 3661 | } |
3662 | zone->reclaim_stat.recent_rotated[0] = 0; | 3662 | zone->reclaim_stat.recent_rotated[0] = 0; |
3663 | zone->reclaim_stat.recent_rotated[1] = 0; | 3663 | zone->reclaim_stat.recent_rotated[1] = 0; |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 9673437a5457..d4da097533ce 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -1492,6 +1492,26 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc, | |||
1492 | percent[1] = 100 - percent[0]; | 1492 | percent[1] = 100 - percent[0]; |
1493 | } | 1493 | } |
1494 | 1494 | ||
1495 | /* | ||
1496 | * Smallish @nr_to_scan's are deposited in @nr_saved_scan, | ||
1497 | * until we collected @swap_cluster_max pages to scan. | ||
1498 | */ | ||
1499 | static unsigned long nr_scan_try_batch(unsigned long nr_to_scan, | ||
1500 | unsigned long *nr_saved_scan, | ||
1501 | unsigned long swap_cluster_max) | ||
1502 | { | ||
1503 | unsigned long nr; | ||
1504 | |||
1505 | *nr_saved_scan += nr_to_scan; | ||
1506 | nr = *nr_saved_scan; | ||
1507 | |||
1508 | if (nr >= swap_cluster_max) | ||
1509 | *nr_saved_scan = 0; | ||
1510 | else | ||
1511 | nr = 0; | ||
1512 | |||
1513 | return nr; | ||
1514 | } | ||
1495 | 1515 | ||
1496 | /* | 1516 | /* |
1497 | * This is a basic per-zone page freer. Used by both kswapd and direct reclaim. | 1517 | * This is a basic per-zone page freer. Used by both kswapd and direct reclaim. |
@@ -1517,14 +1537,11 @@ static void shrink_zone(int priority, struct zone *zone, | |||
1517 | scan >>= priority; | 1537 | scan >>= priority; |
1518 | scan = (scan * percent[file]) / 100; | 1538 | scan = (scan * percent[file]) / 100; |
1519 | } | 1539 | } |
1520 | if (scanning_global_lru(sc)) { | 1540 | if (scanning_global_lru(sc)) |
1521 | zone->lru[l].nr_scan += scan; | 1541 | nr[l] = nr_scan_try_batch(scan, |
1522 | nr[l] = zone->lru[l].nr_scan; | 1542 | &zone->lru[l].nr_saved_scan, |
1523 | if (nr[l] >= swap_cluster_max) | 1543 | swap_cluster_max); |
1524 | zone->lru[l].nr_scan = 0; | 1544 | else |
1525 | else | ||
1526 | nr[l] = 0; | ||
1527 | } else | ||
1528 | nr[l] = scan; | 1545 | nr[l] = scan; |
1529 | } | 1546 | } |
1530 | 1547 | ||
@@ -2124,11 +2141,11 @@ static void shrink_all_zones(unsigned long nr_pages, int prio, | |||
2124 | l == LRU_ACTIVE_FILE)) | 2141 | l == LRU_ACTIVE_FILE)) |
2125 | continue; | 2142 | continue; |
2126 | 2143 | ||
2127 | zone->lru[l].nr_scan += (lru_pages >> prio) + 1; | 2144 | zone->lru[l].nr_saved_scan += (lru_pages >> prio) + 1; |
2128 | if (zone->lru[l].nr_scan >= nr_pages || pass > 3) { | 2145 | if (zone->lru[l].nr_saved_scan >= nr_pages || pass > 3) { |
2129 | unsigned long nr_to_scan; | 2146 | unsigned long nr_to_scan; |
2130 | 2147 | ||
2131 | zone->lru[l].nr_scan = 0; | 2148 | zone->lru[l].nr_saved_scan = 0; |
2132 | nr_to_scan = min(nr_pages, lru_pages); | 2149 | nr_to_scan = min(nr_pages, lru_pages); |
2133 | nr_reclaimed += shrink_list(l, nr_to_scan, zone, | 2150 | nr_reclaimed += shrink_list(l, nr_to_scan, zone, |
2134 | sc, prio); | 2151 | sc, prio); |
diff --git a/mm/vmstat.c b/mm/vmstat.c index 415110772c73..84c055556911 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -718,10 +718,10 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, | |||
718 | low_wmark_pages(zone), | 718 | low_wmark_pages(zone), |
719 | high_wmark_pages(zone), | 719 | high_wmark_pages(zone), |
720 | zone->pages_scanned, | 720 | zone->pages_scanned, |
721 | zone->lru[LRU_ACTIVE_ANON].nr_scan, | 721 | zone->lru[LRU_ACTIVE_ANON].nr_saved_scan, |
722 | zone->lru[LRU_INACTIVE_ANON].nr_scan, | 722 | zone->lru[LRU_INACTIVE_ANON].nr_saved_scan, |
723 | zone->lru[LRU_ACTIVE_FILE].nr_scan, | 723 | zone->lru[LRU_ACTIVE_FILE].nr_saved_scan, |
724 | zone->lru[LRU_INACTIVE_FILE].nr_scan, | 724 | zone->lru[LRU_INACTIVE_FILE].nr_saved_scan, |
725 | zone->spanned_pages, | 725 | zone->spanned_pages, |
726 | zone->present_pages); | 726 | zone->present_pages); |
727 | 727 | ||