History

vmscan: fix initial shrinker size handling

A shrinker function can return -1, means that it cannot do anything without a risk of deadlock. For example prune_super() does this if it cannot grab a superblock refrence, even if nr_to_scan=0. Currently we interpret this -1 as a ULONG_MAX size shrinker and evaluate `total_scan' according to this. So the next time around this shrinker can cause really big pressure. Let's skip such shrinkers instead. Also make total_scan signed, otherwise the check (total_scan < 0) below never works.

Konstantin Khlebnikov committed 14 years ago

Commit 635697c1 parent 09d96731 file · +6 −3Browse files

Unified · Split

mm/vmscan.c+6−3
@@ -247,14 +247,18 @@ unsigned long shrink_slab(struct shrink_control *shrink, · 246 unmodified lines
247 247
248 list_for_each_entry(shrinker, &shrinker_list, list) {248 list_for_each_entry(shrinker, &shrinker_list, list) {
249 unsigned long long delta;249 unsigned long long delta;
250 unsigned long total_scan;250 long total_scan;
251 unsigned long max_pass;251 long max_pass;
252 int shrink_ret = 0;252 int shrink_ret = 0;
253 long nr;253 long nr;
254 long new_nr;254 long new_nr;
255 long batch_size = shrinker->batch ? shrinker->batch255 long batch_size = shrinker->batch ? shrinker->batch
256 : SHRINK_BATCH;256 : SHRINK_BATCH;
257 257
258 max_pass = do_shrinker_shrink(shrinker, shrink, 0);
259 if (max_pass <= 0)
260 continue;
261
258 /*262 /*
259 * copy the current shrinker scan count into a local variable263 * copy the current shrinker scan count into a local variable
260 * and zero it so that other concurrent shrinker invocations264 * and zero it so that other concurrent shrinker invocations
@@ -265,7 +269,6 @@ unsigned long shrink_slab(struct shrink_control *shrink, · 4 unmodified lines
265 } while (cmpxchg(&shrinker->nr, nr, 0) != nr);269 } while (cmpxchg(&shrinker->nr, nr, 0) != nr);
266 270
267 total_scan = nr;271 total_scan = nr;
268 max_pass = do_shrinker_shrink(shrinker, shrink, 0);
269 delta = (4 * nr_pages_scanned) / shrinker->seeks;272 delta = (4 * nr_pages_scanned) / shrinker->seeks;
270 delta *= max_pass;273 delta *= max_pass;
271 do_div(delta, lru_pages + 1);274 do_div(delta, lru_pages + 1);