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
247247
248248 list_for_each_entry(shrinker, &shrinker_list, list) {
249249 unsigned long long delta;
250− unsigned long total_scan;
251− unsigned long max_pass;
250+ long total_scan;
251+ long max_pass;
252252 int shrink_ret = 0;
253253 long nr;
254254 long new_nr;
255255 long batch_size = shrinker->batch ? shrinker->batch
256256 : SHRINK_BATCH;
257257
258+ max_pass = do_shrinker_shrink(shrinker, shrink, 0);
259+ if (max_pass <= 0)
260+ continue;
261+
258262 /*
259263 * copy the current shrinker scan count into a local variable
260264 * and zero it so that other concurrent shrinker invocations
@@ -265,7 +269,6 @@ unsigned long shrink_slab(struct shrink_control *shrink, · 4 unmodified lines
265269 } while (cmpxchg(&shrinker->nr, nr, 0) != nr);
266270
267271 total_scan = nr;
268− max_pass = do_shrinker_shrink(shrinker, shrink, 0);
269272 delta = (4 * nr_pages_scanned) / shrinker->seeks;
270273 delta *= max_pass;
271274 do_div(delta, lru_pages + 1);