diff options
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r-- | mm/vmscan.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 28130541270f..b0cd81c32de6 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -201,13 +201,25 @@ static int shrink_slab(unsigned long scanned, gfp_t gfp_mask, | |||
201 | list_for_each_entry(shrinker, &shrinker_list, list) { | 201 | list_for_each_entry(shrinker, &shrinker_list, list) { |
202 | unsigned long long delta; | 202 | unsigned long long delta; |
203 | unsigned long total_scan; | 203 | unsigned long total_scan; |
204 | unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask); | ||
204 | 205 | ||
205 | delta = (4 * scanned) / shrinker->seeks; | 206 | delta = (4 * scanned) / shrinker->seeks; |
206 | delta *= (*shrinker->shrinker)(0, gfp_mask); | 207 | delta *= max_pass; |
207 | do_div(delta, lru_pages + 1); | 208 | do_div(delta, lru_pages + 1); |
208 | shrinker->nr += delta; | 209 | shrinker->nr += delta; |
209 | if (shrinker->nr < 0) | 210 | if (shrinker->nr < 0) { |
210 | shrinker->nr = LONG_MAX; /* It wrapped! */ | 211 | printk(KERN_ERR "%s: nr=%ld\n", |
212 | __FUNCTION__, shrinker->nr); | ||
213 | shrinker->nr = max_pass; | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Avoid risking looping forever due to too large nr value: | ||
218 | * never try to free more than twice the estimate number of | ||
219 | * freeable entries. | ||
220 | */ | ||
221 | if (shrinker->nr > max_pass * 2) | ||
222 | shrinker->nr = max_pass * 2; | ||
211 | 223 | ||
212 | total_scan = shrinker->nr; | 224 | total_scan = shrinker->nr; |
213 | shrinker->nr = 0; | 225 | shrinker->nr = 0; |
@@ -407,7 +419,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) | |||
407 | if (PageWriteback(page)) | 419 | if (PageWriteback(page)) |
408 | goto keep_locked; | 420 | goto keep_locked; |
409 | 421 | ||
410 | referenced = page_referenced(page, 1, sc->priority <= 0); | 422 | referenced = page_referenced(page, 1); |
411 | /* In active use or really unfreeable? Activate it. */ | 423 | /* In active use or really unfreeable? Activate it. */ |
412 | if (referenced && page_mapping_inuse(page)) | 424 | if (referenced && page_mapping_inuse(page)) |
413 | goto activate_locked; | 425 | goto activate_locked; |
@@ -756,7 +768,7 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc) | |||
756 | if (page_mapped(page)) { | 768 | if (page_mapped(page)) { |
757 | if (!reclaim_mapped || | 769 | if (!reclaim_mapped || |
758 | (total_swap_pages == 0 && PageAnon(page)) || | 770 | (total_swap_pages == 0 && PageAnon(page)) || |
759 | page_referenced(page, 0, sc->priority <= 0)) { | 771 | page_referenced(page, 0)) { |
760 | list_add(&page->lru, &l_active); | 772 | list_add(&page->lru, &l_active); |
761 | continue; | 773 | continue; |
762 | } | 774 | } |
@@ -960,6 +972,8 @@ int try_to_free_pages(struct zone **zones, gfp_t gfp_mask) | |||
960 | sc.nr_reclaimed = 0; | 972 | sc.nr_reclaimed = 0; |
961 | sc.priority = priority; | 973 | sc.priority = priority; |
962 | sc.swap_cluster_max = SWAP_CLUSTER_MAX; | 974 | sc.swap_cluster_max = SWAP_CLUSTER_MAX; |
975 | if (!priority) | ||
976 | disable_swap_token(); | ||
963 | shrink_caches(zones, &sc); | 977 | shrink_caches(zones, &sc); |
964 | shrink_slab(sc.nr_scanned, gfp_mask, lru_pages); | 978 | shrink_slab(sc.nr_scanned, gfp_mask, lru_pages); |
965 | if (reclaim_state) { | 979 | if (reclaim_state) { |
@@ -1056,6 +1070,10 @@ loop_again: | |||
1056 | int end_zone = 0; /* Inclusive. 0 = ZONE_DMA */ | 1070 | int end_zone = 0; /* Inclusive. 0 = ZONE_DMA */ |
1057 | unsigned long lru_pages = 0; | 1071 | unsigned long lru_pages = 0; |
1058 | 1072 | ||
1073 | /* The swap token gets in the way of swapout... */ | ||
1074 | if (!priority) | ||
1075 | disable_swap_token(); | ||
1076 | |||
1059 | all_zones_ok = 1; | 1077 | all_zones_ok = 1; |
1060 | 1078 | ||
1061 | if (nr_pages == 0) { | 1079 | if (nr_pages == 0) { |
@@ -1360,6 +1378,7 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) | |||
1360 | sc.nr_reclaimed = 0; | 1378 | sc.nr_reclaimed = 0; |
1361 | /* scan at the highest priority */ | 1379 | /* scan at the highest priority */ |
1362 | sc.priority = 0; | 1380 | sc.priority = 0; |
1381 | disable_swap_token(); | ||
1363 | 1382 | ||
1364 | if (nr_pages > SWAP_CLUSTER_MAX) | 1383 | if (nr_pages > SWAP_CLUSTER_MAX) |
1365 | sc.swap_cluster_max = nr_pages; | 1384 | sc.swap_cluster_max = nr_pages; |