diff options
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r-- | mm/vmscan.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index f75d924cb4f4..03ca923c6656 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -130,6 +130,12 @@ static DECLARE_RWSEM(shrinker_rwsem); | |||
130 | #define scan_global_lru(sc) (1) | 130 | #define scan_global_lru(sc) (1) |
131 | #endif | 131 | #endif |
132 | 132 | ||
133 | static struct zone_reclaim_stat *get_reclaim_stat(struct zone *zone, | ||
134 | struct scan_control *sc) | ||
135 | { | ||
136 | return &zone->reclaim_stat; | ||
137 | } | ||
138 | |||
133 | /* | 139 | /* |
134 | * Add a shrinker callback to be called from the vm | 140 | * Add a shrinker callback to be called from the vm |
135 | */ | 141 | */ |
@@ -1029,6 +1035,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan, | |||
1029 | struct pagevec pvec; | 1035 | struct pagevec pvec; |
1030 | unsigned long nr_scanned = 0; | 1036 | unsigned long nr_scanned = 0; |
1031 | unsigned long nr_reclaimed = 0; | 1037 | unsigned long nr_reclaimed = 0; |
1038 | struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc); | ||
1032 | 1039 | ||
1033 | pagevec_init(&pvec, 1); | 1040 | pagevec_init(&pvec, 1); |
1034 | 1041 | ||
@@ -1072,10 +1079,14 @@ static unsigned long shrink_inactive_list(unsigned long max_scan, | |||
1072 | 1079 | ||
1073 | if (scan_global_lru(sc)) { | 1080 | if (scan_global_lru(sc)) { |
1074 | zone->pages_scanned += nr_scan; | 1081 | zone->pages_scanned += nr_scan; |
1075 | zone->recent_scanned[0] += count[LRU_INACTIVE_ANON]; | 1082 | reclaim_stat->recent_scanned[0] += |
1076 | zone->recent_scanned[0] += count[LRU_ACTIVE_ANON]; | 1083 | count[LRU_INACTIVE_ANON]; |
1077 | zone->recent_scanned[1] += count[LRU_INACTIVE_FILE]; | 1084 | reclaim_stat->recent_scanned[0] += |
1078 | zone->recent_scanned[1] += count[LRU_ACTIVE_FILE]; | 1085 | count[LRU_ACTIVE_ANON]; |
1086 | reclaim_stat->recent_scanned[1] += | ||
1087 | count[LRU_INACTIVE_FILE]; | ||
1088 | reclaim_stat->recent_scanned[1] += | ||
1089 | count[LRU_ACTIVE_FILE]; | ||
1079 | } | 1090 | } |
1080 | spin_unlock_irq(&zone->lru_lock); | 1091 | spin_unlock_irq(&zone->lru_lock); |
1081 | 1092 | ||
@@ -1136,7 +1147,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan, | |||
1136 | add_page_to_lru_list(zone, page, lru); | 1147 | add_page_to_lru_list(zone, page, lru); |
1137 | if (PageActive(page) && scan_global_lru(sc)) { | 1148 | if (PageActive(page) && scan_global_lru(sc)) { |
1138 | int file = !!page_is_file_cache(page); | 1149 | int file = !!page_is_file_cache(page); |
1139 | zone->recent_rotated[file]++; | 1150 | reclaim_stat->recent_rotated[file]++; |
1140 | } | 1151 | } |
1141 | if (!pagevec_add(&pvec, page)) { | 1152 | if (!pagevec_add(&pvec, page)) { |
1142 | spin_unlock_irq(&zone->lru_lock); | 1153 | spin_unlock_irq(&zone->lru_lock); |
@@ -1196,6 +1207,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
1196 | struct page *page; | 1207 | struct page *page; |
1197 | struct pagevec pvec; | 1208 | struct pagevec pvec; |
1198 | enum lru_list lru; | 1209 | enum lru_list lru; |
1210 | struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc); | ||
1199 | 1211 | ||
1200 | lru_add_drain(); | 1212 | lru_add_drain(); |
1201 | spin_lock_irq(&zone->lru_lock); | 1213 | spin_lock_irq(&zone->lru_lock); |
@@ -1208,7 +1220,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
1208 | */ | 1220 | */ |
1209 | if (scan_global_lru(sc)) { | 1221 | if (scan_global_lru(sc)) { |
1210 | zone->pages_scanned += pgscanned; | 1222 | zone->pages_scanned += pgscanned; |
1211 | zone->recent_scanned[!!file] += pgmoved; | 1223 | reclaim_stat->recent_scanned[!!file] += pgmoved; |
1212 | } | 1224 | } |
1213 | 1225 | ||
1214 | if (file) | 1226 | if (file) |
@@ -1251,7 +1263,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
1251 | * pages in get_scan_ratio. | 1263 | * pages in get_scan_ratio. |
1252 | */ | 1264 | */ |
1253 | if (scan_global_lru(sc)) | 1265 | if (scan_global_lru(sc)) |
1254 | zone->recent_rotated[!!file] += pgmoved; | 1266 | reclaim_stat->recent_rotated[!!file] += pgmoved; |
1255 | 1267 | ||
1256 | while (!list_empty(&l_inactive)) { | 1268 | while (!list_empty(&l_inactive)) { |
1257 | page = lru_to_page(&l_inactive); | 1269 | page = lru_to_page(&l_inactive); |
@@ -1344,6 +1356,7 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc, | |||
1344 | unsigned long anon, file, free; | 1356 | unsigned long anon, file, free; |
1345 | unsigned long anon_prio, file_prio; | 1357 | unsigned long anon_prio, file_prio; |
1346 | unsigned long ap, fp; | 1358 | unsigned long ap, fp; |
1359 | struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc); | ||
1347 | 1360 | ||
1348 | /* If we have no swap space, do not bother scanning anon pages. */ | 1361 | /* If we have no swap space, do not bother scanning anon pages. */ |
1349 | if (nr_swap_pages <= 0) { | 1362 | if (nr_swap_pages <= 0) { |
@@ -1376,17 +1389,17 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc, | |||
1376 | * | 1389 | * |
1377 | * anon in [0], file in [1] | 1390 | * anon in [0], file in [1] |
1378 | */ | 1391 | */ |
1379 | if (unlikely(zone->recent_scanned[0] > anon / 4)) { | 1392 | if (unlikely(reclaim_stat->recent_scanned[0] > anon / 4)) { |
1380 | spin_lock_irq(&zone->lru_lock); | 1393 | spin_lock_irq(&zone->lru_lock); |
1381 | zone->recent_scanned[0] /= 2; | 1394 | reclaim_stat->recent_scanned[0] /= 2; |
1382 | zone->recent_rotated[0] /= 2; | 1395 | reclaim_stat->recent_rotated[0] /= 2; |
1383 | spin_unlock_irq(&zone->lru_lock); | 1396 | spin_unlock_irq(&zone->lru_lock); |
1384 | } | 1397 | } |
1385 | 1398 | ||
1386 | if (unlikely(zone->recent_scanned[1] > file / 4)) { | 1399 | if (unlikely(reclaim_stat->recent_scanned[1] > file / 4)) { |
1387 | spin_lock_irq(&zone->lru_lock); | 1400 | spin_lock_irq(&zone->lru_lock); |
1388 | zone->recent_scanned[1] /= 2; | 1401 | reclaim_stat->recent_scanned[1] /= 2; |
1389 | zone->recent_rotated[1] /= 2; | 1402 | reclaim_stat->recent_rotated[1] /= 2; |
1390 | spin_unlock_irq(&zone->lru_lock); | 1403 | spin_unlock_irq(&zone->lru_lock); |
1391 | } | 1404 | } |
1392 | 1405 | ||
@@ -1402,11 +1415,11 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc, | |||
1402 | * proportional to the fraction of recently scanned pages on | 1415 | * proportional to the fraction of recently scanned pages on |
1403 | * each list that were recently referenced and in active use. | 1416 | * each list that were recently referenced and in active use. |
1404 | */ | 1417 | */ |
1405 | ap = (anon_prio + 1) * (zone->recent_scanned[0] + 1); | 1418 | ap = (anon_prio + 1) * (reclaim_stat->recent_scanned[0] + 1); |
1406 | ap /= zone->recent_rotated[0] + 1; | 1419 | ap /= reclaim_stat->recent_rotated[0] + 1; |
1407 | 1420 | ||
1408 | fp = (file_prio + 1) * (zone->recent_scanned[1] + 1); | 1421 | fp = (file_prio + 1) * (reclaim_stat->recent_scanned[1] + 1); |
1409 | fp /= zone->recent_rotated[1] + 1; | 1422 | fp /= reclaim_stat->recent_rotated[1] + 1; |
1410 | 1423 | ||
1411 | /* Normalize to percentages */ | 1424 | /* Normalize to percentages */ |
1412 | percent[0] = 100 * ap / (ap + fp + 1); | 1425 | percent[0] = 100 * ap / (ap + fp + 1); |