]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
A shrinker function can return -1, means that it cannot do anything
authorKonstantin Khlebnikov <khlebnikov@openvz.org>
Wed, 24 Aug 2011 23:47:07 +0000 (09:47 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 22 Sep 2011 08:26:23 +0000 (18:26 +1000)
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.

Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org>
Cc: Dave Chinner <david@fromorbit.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/vmscan.c

index 21a7e49126abdfed43e64a6ac72132d36a9f54f6..17ff5f135d71755ac3afd65dfb3d156a110f7303 100644 (file)
@@ -247,14 +247,18 @@ unsigned long shrink_slab(struct shrink_control *shrink,
 
        list_for_each_entry(shrinker, &shrinker_list, list) {
                unsigned long long delta;
-               unsigned long total_scan;
-               unsigned long max_pass;
+               long total_scan;
+               long max_pass;
                int shrink_ret = 0;
                long nr;
                long new_nr;
                long batch_size = shrinker->batch ? shrinker->batch
                                                  : SHRINK_BATCH;
 
+               max_pass = do_shrinker_shrink(shrinker, shrink, 0);
+               if (max_pass <= 0)
+                       continue;
+
                /*
                 * copy the current shrinker scan count into a local variable
                 * and zero it so that other concurrent shrinker invocations
@@ -265,7 +269,6 @@ unsigned long shrink_slab(struct shrink_control *shrink,
                } while (cmpxchg(&shrinker->nr, nr, 0) != nr);
 
                total_scan = nr;
-               max_pass = do_shrinker_shrink(shrinker, shrink, 0);
                delta = (4 * nr_pages_scanned) / shrinker->seeks;
                delta *= max_pass;
                do_div(delta, lru_pages + 1);