aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r--mm/vmscan.c29
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;