X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=mm%2Fvmscan.c;h=febbc044e792c427264c908dfe1303ca87ea9c0b;hb=7080d306762f5e4a1418aec4f496af7f879c94c4;hp=2f7c6ae8fae07c23c0e539ef97f756448943920e;hpb=acf92b485cccf028177f46918e045c0c4e80ee10;p=karo-tx-linux.git diff --git a/mm/vmscan.c b/mm/vmscan.c index 2f7c6ae8fae0..febbc044e792 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -253,6 +253,8 @@ unsigned long shrink_slab(struct shrink_control *shrink, int shrink_ret = 0; long nr; long new_nr; + long batch_size = shrinker->batch ? shrinker->batch + : SHRINK_BATCH; /* * copy the current shrinker scan count into a local variable @@ -276,6 +278,21 @@ unsigned long shrink_slab(struct shrink_control *shrink, total_scan = max_pass; } + /* + * We need to avoid excessive windup on filesystem shrinkers + * due to large numbers of GFP_NOFS allocations causing the + * shrinkers to return -1 all the time. This results in a large + * nr being built up so when a shrink that can do some work + * comes along it empties the entire cache due to nr >>> + * max_pass. This is bad for sustaining a working set in + * memory. + * + * Hence only allow the shrinker to scan the entire cache when + * a large delta change is calculated directly. + */ + if (delta < max_pass / 4) + total_scan = min(total_scan, max_pass / 2); + /* * Avoid risking looping forever due to too large nr value: * never try to free more than twice the estimate number of @@ -288,19 +305,18 @@ unsigned long shrink_slab(struct shrink_control *shrink, nr_pages_scanned, lru_pages, max_pass, delta, total_scan); - while (total_scan >= SHRINK_BATCH) { - long this_scan = SHRINK_BATCH; + while (total_scan >= batch_size) { int nr_before; nr_before = do_shrinker_shrink(shrinker, shrink, 0); shrink_ret = do_shrinker_shrink(shrinker, shrink, - this_scan); + batch_size); if (shrink_ret == -1) break; if (shrink_ret < nr_before) ret += nr_before - shrink_ret; - count_vm_events(SLABS_SCANNED, this_scan); - total_scan -= this_scan; + count_vm_events(SLABS_SCANNED, batch_size); + total_scan -= batch_size; cond_resched(); }